[svn-upgrade] Integrating new upstream version, bti (024)
[debian/bti.git] / bti.c
diff --git a/bti.c b/bti.c
index fe4c6e2..1f1279e 100644 (file)
--- a/bti.c
+++ b/bti.c
@@ -38,6 +38,7 @@
 #include <libxml/parser.h>
 #include <libxml/tree.h>
 #include <pcre.h>
+#include <termios.h>
 
 
 #define zalloc(size)   calloc(size, 1)
@@ -65,7 +66,8 @@ enum action {
        ACTION_USER    = 2,
        ACTION_REPLIES = 4,
        ACTION_PUBLIC  = 8,
-       ACTION_UNKNOWN = 16
+       ACTION_GROUP   = 16,
+       ACTION_UNKNOWN = 32
 };
 
 struct session {
@@ -77,6 +79,7 @@ struct session {
        char *homedir;
        char *logfile;
        char *user;
+       char *group;
        char *hosturl;
        int bash;
        int shrink_urls;
@@ -102,9 +105,10 @@ static void display_help(void)
        fprintf(stdout, "  --account accountname\n");
        fprintf(stdout, "  --password password\n");
        fprintf(stdout, "  --action action\n");
-       fprintf(stdout, "    ('update', 'friends', 'public', 'replies' "
-               "or 'user')\n");
+       fprintf(stdout, "    ('update', 'friends', 'public', 'replies', "
+               "'group' or 'user')\n");
        fprintf(stdout, "  --user screenname\n");
+       fprintf(stdout, "  --group groupname\n");
        fprintf(stdout, "  --proxy PROXY:PORT\n");
        fprintf(stdout, "  --host HOST\n");
        fprintf(stdout, "  --logfile logfile\n");
@@ -144,6 +148,7 @@ static void session_free(struct session *session)
        free(session->time);
        free(session->homedir);
        free(session->user);
+       free(session->group);
        free(session->hosturl);
        free(session);
 }
@@ -184,6 +189,7 @@ static const char *update_uri  = "/update.xml";
 static const char *public_uri  = "/public_timeline.xml";
 static const char *friends_uri = "/friends_timeline.xml";
 static const char *replies_uri = "/replies.xml";
+static const char *group_uri = "/../laconica/groups/timeline/";
 
 static CURL *curl_init(void)
 {
@@ -350,7 +356,7 @@ static int send_request(struct session *session)
                curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
                slist = curl_slist_append(slist, "Expect:");
                curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
-               
+
                sprintf(endpoint, "%s%s", session->hosturl, update_uri);
                curl_easy_setopt(curl, CURLOPT_URL, endpoint);
                curl_easy_setopt(curl, CURLOPT_USERPWD, user_password);
@@ -366,21 +372,29 @@ static int send_request(struct session *session)
 
                break;
        case ACTION_USER:
-               sprintf(endpoint, "%s%s%s.xml?page=%d", session->hosturl, user_uri,
-                               session->user, session->page);
+               sprintf(endpoint, "%s%s%s.xml?page=%d", session->hosturl,
+                       user_uri, session->user, session->page);
                curl_easy_setopt(curl, CURLOPT_URL, endpoint);
 
                break;
        case ACTION_REPLIES:
                snprintf(user_password, sizeof(user_password), "%s:%s",
                         session->account, session->password);
-               sprintf(endpoint, "%s%s?page=%d", session->hosturl, replies_uri, session->page);
+               sprintf(endpoint, "%s%s?page=%d", session->hosturl, replies_uri,
+                       session->page);
                curl_easy_setopt(curl, CURLOPT_URL, endpoint);
                curl_easy_setopt(curl, CURLOPT_USERPWD, user_password);
 
                break;
        case ACTION_PUBLIC:
-               sprintf(endpoint, "%s%s?page=%d", session->hosturl, public_uri, session->page);
+               sprintf(endpoint, "%s%s?page=%d", session->hosturl, public_uri,
+                       session->page);
+               curl_easy_setopt(curl, CURLOPT_URL, endpoint);
+
+               break;
+       case ACTION_GROUP:
+               sprintf(endpoint, "%s%s%s.xml?page=%d", session->hosturl,
+                               group_uri, session->group, session->page);
                curl_easy_setopt(curl, CURLOPT_URL, endpoint);
 
                break;
@@ -501,14 +515,13 @@ static void parse_configfile(struct session *session)
                        if (!strncasecmp(c, "true", 4) ||
                                        !strncasecmp(c, "yes", 3))
                                shrink_urls = 1;
-               }
-               else if (!strncasecmp(c, "verbose", 7) &&
+               } else if (!strncasecmp(c, "verbose", 7) &&
                                (c[7] == '=')) {
                        c += 8;
                        if (!strncasecmp(c, "true", 4) ||
                                        !strncasecmp(c, "yes", 3))
                                verbose = 1;
-               }       
+               }
        } while (!feof(config_file));
 
        if (password)
@@ -546,6 +559,8 @@ static void parse_configfile(struct session *session)
                        session->action = ACTION_REPLIES;
                else if (strcasecmp(action, "public") == 0)
                        session->action = ACTION_PUBLIC;
+               else if (strcasecmp(action, "group") == 0)
+                       session->action = ACTION_GROUP;
                else
                        session->action = ACTION_UNKNOWN;
                free(action);
@@ -614,6 +629,10 @@ static void log_session(struct session *session, int retval)
                fprintf(log_file, "%s: host=%s retrieving public timeline\n",
                        session->time, host);
                break;
+       case ACTION_GROUP:
+               fprintf(log_file, "%s: host=%s retrieving group timeline\n",
+                       session->time, host);
+               break;
        default:
                break;
        }
@@ -637,6 +656,32 @@ static char *get_string_from_stdin(void)
        return string;
 }
 
+static void read_password(char *buf, size_t len)
+{
+       char pwd[80];
+       int retval;
+       struct termios old;
+       struct termios tp;
+
+       tcgetattr(0, &tp);
+       old = tp;
+
+       tp.c_lflag &= (~ECHO);
+       tcsetattr(0, TCSANOW, &tp);
+
+       fprintf(stdout, "Enter twitter password: ");
+       fflush(stdout);
+       tcflow(0, TCOOFF);
+       retval = scanf("%79s", pwd);
+       tcflow(0, TCOON);
+       fprintf(stdout, "\n");
+
+       tcsetattr(0, TCSANOW, &old);
+
+       strncpy(buf, pwd, len);
+       buf[len-1] = '\0';
+}
+
 static int find_urls(const char *tweet, int **pranges)
 {
        /*
@@ -910,6 +955,7 @@ int main(int argc, char *argv[], char *envp[])
                { "proxy", 1, NULL, 'P' },
                { "action", 1, NULL, 'A' },
                { "user", 1, NULL, 'u' },
+               { "group", 1, NULL, 'G' },
                { "logfile", 1, NULL, 'L' },
                { "shrink-urls", 0, NULL, 's' },
                { "help", 0, NULL, 'h' },
@@ -922,6 +968,7 @@ int main(int argc, char *argv[], char *envp[])
        struct session *session;
        pid_t child;
        char *tweet;
+       static char password[80];
        int retval = 0;
        int option;
        char *http_proxy;
@@ -960,7 +1007,7 @@ int main(int argc, char *argv[], char *envp[])
        parse_configfile(session);
 
        while (1) {
-               option = getopt_long_only(argc, argv, "dp:P:H:a:A:u:hg:snVv",
+               option = getopt_long_only(argc, argv, "dp:P:H:a:A:u:hg:G:snVv",
                                          options, NULL);
                if (option == -1)
                        break;
@@ -1005,6 +1052,8 @@ int main(int argc, char *argv[], char *envp[])
                                session->action = ACTION_REPLIES;
                        else if (strcasecmp(optarg, "public") == 0)
                                session->action = ACTION_PUBLIC;
+                       else if (strcasecmp(optarg, "group") == 0)
+                               session->action = ACTION_GROUP;
                        else
                                session->action = ACTION_UNKNOWN;
                        dbg("action = %d\n", session->action);
@@ -1015,6 +1064,13 @@ int main(int argc, char *argv[], char *envp[])
                        session->user = strdup(optarg);
                        dbg("user = %s\n", session->user);
                        break;
+
+               case 'G':
+                       if (session->group)
+                               free(session->group);
+                       session->group = strdup(optarg);
+                       dbg("group = %s\n", session->group);
+                       break;
                case 'L':
                        if (session->logfile)
                                free(session->logfile);
@@ -1067,18 +1123,28 @@ int main(int argc, char *argv[], char *envp[])
        if (session->action == ACTION_UNKNOWN) {
                fprintf(stderr, "Unknown action, valid actions are:\n");
                fprintf(stderr, "'update', 'friends', 'public', "
-                       "'replies' or 'user'.\n");
+                       "'replies', 'group' or 'user'.\n");
                goto exit;
        }
 
+       if (session->host == HOST_TWITTER && session->action == ACTION_GROUP) {
+               fprintf(stderr, "Groups only work in Identi.ca.\n");
+               goto exit;
+       }
+
+       if (session->action == ACTION_GROUP && !session->group) {
+               fprintf(stdout, "Enter group name: ");
+               session->group = readline(NULL);
+       }
+
        if (!session->account) {
                fprintf(stdout, "Enter twitter account: ");
                session->account = readline(NULL);
        }
 
        if (!session->password) {
-               fprintf(stdout, "Enter twitter password: ");
-               session->password = readline(NULL);
+               read_password(password, sizeof(password));
+               session->password = strdup(password);
        }
 
        if (session->action == ACTION_UPDATE) {
@@ -1096,7 +1162,8 @@ int main(int argc, char *argv[], char *envp[])
 
                session->tweet = zalloc(strlen(tweet) + 10);
                if (session->bash)
-                       sprintf(session->tweet, "%c %s", getuid() ? '$' : '#', tweet);
+                       sprintf(session->tweet, "%c %s",
+                               getuid() ? '$' : '#', tweet);
                else
                        sprintf(session->tweet, "%s", tweet);