about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJames Booth <boothj5@gmail.com>2015-11-25 00:41:37 +0000
committerJames Booth <boothj5@gmail.com>2015-11-25 00:41:37 +0000
commitc14d5b77e0da4cfbf43b6cb87e24383795a824b5 (patch)
tree5a6a9998adfe76b4301894546791cf1f0c4746f1
parenta2f5e921f2e5fb4158aad14928882e694e5d8a85 (diff)
parentdf2726bdf550d1da2d2f4d57dca04ae847123604 (diff)
downloadprofani-tty-c14d5b77e0da4cfbf43b6cb87e24383795a824b5.tar.gz
Merge remote-tracking branch 'incertia/export-command'
-rw-r--r--CHANGELOG1
-rw-r--r--src/command/command.c14
-rw-r--r--src/command/commands.c95
-rw-r--r--src/command/commands.h1
4 files changed, 111 insertions, 0 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 7a113907..cf0f3030 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -9,6 +9,7 @@
 - Last Activity (xep-0012)
 - Run command sequence with /script
 - Account startscript property
+- Add /export command
 
 0.4.7
 =====
diff --git a/src/command/command.c b/src/command/command.c
index bc2ee121..3e9adc9c 100644
--- a/src/command/command.c
+++ b/src/command/command.c
@@ -1766,6 +1766,20 @@ static struct cmd_t command_defs[] =
             "/script run myscript",
             "/script show somescript")
     },
+
+    { "/export",
+        cmd_export, parse_args, 1, 1, NULL,
+        CMD_NOTAGS
+        CMD_SYN(
+            "/export <filepath>")
+        CMD_DESC(
+            "Exports contacts to a csv file.")
+        CMD_ARGS(
+            { "<filepath>", "Path to the output file." })
+        CMD_EXAMPLES(
+            "/export /path/to/output.csv",
+            "/export ~/contacts.csv")
+    },
 };
 
 static Autocomplete commands_ac;
diff --git a/src/command/commands.c b/src/command/commands.c
index c17dca43..1fa8cc24 100644
--- a/src/command/commands.c
+++ b/src/command/commands.c
@@ -39,6 +39,10 @@
 #include <errno.h>
 #include <assert.h>
 #include <glib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
 
 #include "chat_session.h"
 #include "command/commands.h"
@@ -793,6 +797,97 @@ cmd_script(ProfWin *window, const char *const command, gchar **args)
     return TRUE;
 }
 
+/* escape a string into csv and write it to the file descriptor */
+static int
+_writecsv(int fd, const char *const str)
+{
+    if (!str) return 0;
+    size_t len = strlen(str);
+    char *s = malloc(2 * len * sizeof(char));
+    char *c = s;
+    int i = 0;
+    for (; i < strlen(str); i++) {
+        if (str[i] != '"') *c++ = str[i];
+        else { *c++ = '"'; *c++ = '"'; len++; }
+    }
+    if (-1 == write(fd, s, len)) {
+        cons_show("error: failed to write '%s' to the requested file: %s", s, strerror(errno));
+        return -1;
+    }
+    free(s);
+    return 0;
+}
+
+gboolean
+cmd_export(ProfWin *window, const char *const command, gchar **args)
+{
+    jabber_conn_status_t conn_status = jabber_get_connection_status();
+
+    if (conn_status != JABBER_CONNECTED) {
+        cons_show("You are not currently connected.");
+        cons_show("");
+        return TRUE;
+    } else {
+        GString *fname = g_string_new("");
+        GSList *list = NULL;
+        int fd;
+
+        /* deal with the ~ convention for $HOME */
+        if (args[0][0] == '~') {
+            fname = g_string_append(fname, getenv("HOME"));
+            fname = g_string_append(fname, args[0] + 1);
+        } else {
+            fname = g_string_append(fname, args[0]);
+        }
+
+        fd = open(fname->str, O_WRONLY | O_CREAT, 00600);
+        g_string_free(fname, TRUE);
+
+        if (-1 == fd) {
+            cons_show("error: cannot open %s: %s", args[0], strerror(errno));
+            cons_show("");
+            return TRUE;
+        }
+
+        if (-1 == write(fd, "jid,name\n", strlen("jid,name\n"))) goto write_error;
+
+        list = roster_get_contacts(ROSTER_ORD_NAME, TRUE);
+        if (list) {
+            GSList *curr = list;
+            while (curr){
+                PContact contact = curr->data;
+                const char *jid = p_contact_barejid(contact);
+                const char  *name = p_contact_name(contact);
+
+                /* write the data to the file */
+                if (-1 == write(fd, "\"", 1)) goto write_error;
+                if (-1 == _writecsv(fd, jid)) goto write_error;
+                if (-1 == write(fd, "\",\"", 3)) goto write_error;
+                if (-1 == _writecsv(fd, name)) goto write_error;
+                if (-1 == write(fd, "\"\n", 2)) goto write_error;
+
+                /* loop */
+                curr = g_slist_next(curr);
+            }
+            cons_show("Contacts exported successfully");
+            cons_show("");
+        } else {
+            cons_show("No contacts in roster.");
+            cons_show("");
+        }
+
+        g_slist_free(list);
+        close(fd);
+        return TRUE;
+write_error:
+        cons_show("error: write failed: %s", strerror(errno));
+        cons_show("");
+        g_slist_free(list);
+        close(fd);
+        return TRUE;
+    }
+}
+
 gboolean
 cmd_sub(ProfWin *window, const char *const command, gchar **args)
 {
diff --git a/src/command/commands.h b/src/command/commands.h
index 4256387e..501046d4 100644
--- a/src/command/commands.h
+++ b/src/command/commands.h
@@ -150,6 +150,7 @@ gboolean cmd_resource(ProfWin *window, const char *const command, gchar **args);
 gboolean cmd_inpblock(ProfWin *window, const char *const command, gchar **args);
 gboolean cmd_encwarn(ProfWin *window, const char *const command, gchar **args);
 gboolean cmd_script(ProfWin *window, const char *const command, gchar **args);
+gboolean cmd_export(ProfWin *window, const char *const command, gchar **args);
 
 gboolean cmd_form_field(ProfWin *window, char *tag, gchar **args);