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 ") + CMD_DESC( + "Exports contacts to a csv file.") + CMD_ARGS( + { "", "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 #include #include +#include +#include +#include +#include #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);