Changes in / [ca0981a:ec86b22]


Ignore:
Files:
2 added
17 edited

Legend:

Unmodified
Added
Removed
  • doc/user-guide/commands.xml

    rca0981a rec86b22  
    7979                                                To send tweets yourself, send them to the twitter_(yourusername) contact, or just write in the groupchat channel if you enabled that option.
    8080                                        </para>
     81
     82                                        <para>
     83                                                Since Twitter now requires OAuth authentication, you should not enter your Twitter password into BitlBee. Just type a bogus password. The first time you log in, BitlBee will start OAuth authentication. (See <emphasis>help set oauth</emphasis>.)
     84                                        </para>
    8185                                </description>
    8286                        </bitlbee-command>
     
    659663        </bitlbee-setting>
    660664
     665        <bitlbee-setting name="message_length" type="integer" scope="account">
     666                <default>140</default>
     667
     668                <description>
     669                        <para>
     670                                Since Twitter rejects messages longer than 140 characters, BitlBee can count message length and emit a warning instead of waiting for Twitter to reject it.
     671                        </para>
     672
     673                        <para>
     674                                You can change this limit here but this won't disable length checks on Twitter's side. You can also set it to 0 to disable the check in case you believe BitlBee doesn't count the characters correctly.
     675                        </para>
     676                </description>
     677
     678        </bitlbee-setting>
     679
    661680        <bitlbee-setting name="mode" type="string" scope="account">
    662681                <possible-values>one, many, chat</possible-values>
     
    703722        </bitlbee-setting>
    704723
     724        <bitlbee-setting name="oauth" type="boolean" scope="account">
     725                <default>true</default>
     726
     727                <description>
     728                        <para>
     729                                This enables OAuth authentication for Twitter accounts. From June 2010 this will be mandatory.
     730                        </para>
     731
     732                        <para>
     733                                With OAuth enabled, you shouldn't tell BitlBee your Twitter password. Just add your account with a bogus password and type <emphasis>account on</emphasis>. BitlBee will then give you a URL to authenticate with Twitter. If this succeeds, Twitter will return a PIN code which you can give back to BitlBee to finish the process.
     734                        </para>
     735
     736                        <para>
     737                                The resulting access token will be saved permanently, so you have to do this only once.
     738                        </para>
     739                </description>
     740
     741        </bitlbee-setting>
     742
    705743        <bitlbee-setting name="ops" type="string" scope="global">
    706744                <default>both</default>
     
    834872                        <para>
    835873                                Can be set for Jabber- and OSCAR-connections. For Jabber, you might have to set this if the servername isn't equal to the part after the @ in the Jabber handle. For OSCAR this shouldn't be necessary anymore in recent BitlBee versions.
     874                        </para>
     875                </description>
     876        </bitlbee-setting>
     877
     878        <bitlbee-setting name="show_offline" type="boolean" scope="global">
     879                <default>false</default>
     880
     881                <description>
     882                        <para>
     883                                If enabled causes BitlBee to also show offline users in Channel. Online-users will get op, away-users voice and offline users none of both. This option takes effect as soon as you reconnect.
    836884                        </para>
    837885                </description>
  • irc.c

    rca0981a rec86b22  
    202202        s = set_add( &irc->set, "root_nick", irc->mynick, set_eval_root_nick, irc );
    203203        s = set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc );
     204        s = set_add( &irc->set, "show_offline", "false", set_eval_bool, irc );
    204205        s = set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc );
    205206        s = set_add( &irc->set, "status", NULL,  set_eval_away_status, irc );
  • lib/Makefile

    rca0981a rec86b22  
    1010
    1111# [SH] Program variables
    12 objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o ftutil.o
     12objects = arc.o base64.o $(EVENT_HANDLER) ftutil.o http_client.o ini.o md5.o misc.o oauth.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o
    1313
    1414CFLAGS += -Wall
  • lib/misc.c

    rca0981a rec86b22  
    306306        for( i = j = 0; t[i]; i ++, j ++ )
    307307        {
    308                 /* if( t[i] <= ' ' || ((unsigned char *)t)[i] >= 128 || t[i] == '%' ) */
    309                 if( !isalnum( t[i] ) )
     308                if( !isalnum( t[i] ) && !strchr( "._-~", t[i] ) )
    310309                {
    311310                        sprintf( s + j, "%%%02X", ((unsigned char*)t)[i] );
  • lib/url.c

    rca0981a rec86b22  
    2727
    2828/* Convert an URL to a url_t structure */
    29 int url_set( url_t *url, char *set_url )
     29int url_set( url_t *url, const char *set_url )
    3030{
    3131        char s[MAX_STRING+1];
  • lib/url.h

    rca0981a rec86b22  
    4242} url_t;
    4343
    44 int url_set( url_t *url, char *set_url );
     44int url_set( url_t *url, const char *set_url );
  • lib/xmltree.c

    rca0981a rec86b22  
    449449        while( node )
    450450        {
    451                 if( g_strcasecmp( node->name, name ) == 0 )
     451                char *colon;
     452               
     453                if( g_strcasecmp( node->name, name ) == 0 ||
     454                    ( ( colon = strchr( node->name, ':' ) ) &&
     455                      g_strcasecmp( colon + 1, name ) == 0 ) )
    452456                        break;
    453457               
     
    461465{
    462466        int i;
     467        char *colon;
    463468       
    464469        if( !node )
     
    468473                if( g_strcasecmp( node->attr[i].key, key ) == 0 )
    469474                        break;
     475       
     476        /* This is an awful hack that only takes care of namespace prefixes
     477           inside a tag. Since IMHO excessive namespace usage in XMPP is
     478           massive overkill anyway (this code exists for almost four years
     479           now and never really missed it): Meh. */
     480        if( !node->attr[i].key && strcmp( key, "xmlns" ) == 0 &&
     481            ( colon = strchr( node->name, ':' ) ) )
     482        {
     483                *colon = '\0';
     484                for( i = 0; node->attr[i].key; i ++ )
     485                        if( strncmp( node->attr[i].key, "xmlns:", 6 ) == 0 &&
     486                            strcmp( node->attr[i].key + 6, node->name ) == 0 )
     487                                break;
     488                *colon = ':';
     489        }
    470490       
    471491        return node->attr[i].value;
  • protocols/jabber/conference.c

    rca0981a rec86b22  
    272272                }
    273273               
    274                 if( bud != jc->me )
    275                 {
     274                if( bud != jc->me && bud->flags & JBFLAG_IS_ANONYMOUS )
     275                {
     276                        /* If JIDs are anonymized, add them to the local
     277                           list for the duration of this chat. */
    276278                        imcb_add_buddy( ic, bud->ext_jid, NULL );
    277279                        imcb_buddy_nick_hint( ic, bud->ext_jid, bud->resource );
  • protocols/msn/sb.c

    rca0981a rec86b22  
    334334        struct msn_data *md = ic->proto_data;
    335335       
    336         if( msn_handler( sb->handler ) == -1 )
     336        if( msn_handler( sb->handler ) != -1 )
     337                return TRUE;
     338       
     339        if( sb->msgq != NULL )
    337340        {
    338341                time_t now = time( NULL );
     342                char buf[1024];
    339343               
    340344                if( now - md->first_sb_failure > 600 )
     
    353357                                      "There might be problems delivering your messages." );
    354358               
    355                 if( sb->msgq != NULL )
    356                 {
    357                         char buf[1024];
    358                        
    359                         if( md->msgq == NULL )
    360                         {
    361                                 md->msgq = sb->msgq;
    362                         }
    363                         else
    364                         {
    365                                 GSList *l;
    366                                
    367                                 for( l = md->msgq; l->next; l = l->next );
    368                                 l->next = sb->msgq;
    369                         }
    370                         sb->msgq = NULL;
    371                        
    372                         debug( "Moved queued messages back to the main queue, creating a new switchboard to retry." );
    373                         g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId );
    374                         if( !msn_write( ic, buf, strlen( buf ) ) )
    375                                 return FALSE;
    376                 }
    377                
    378                 msn_sb_destroy( sb );
    379                
    380                 return FALSE;
    381         }
    382         else
    383         {
    384                 return TRUE;
    385         }
     359                if( md->msgq == NULL )
     360                {
     361                        md->msgq = sb->msgq;
     362                }
     363                else
     364                {
     365                        GSList *l;
     366                       
     367                        for( l = md->msgq; l->next; l = l->next );
     368                        l->next = sb->msgq;
     369                }
     370                sb->msgq = NULL;
     371               
     372                debug( "Moved queued messages back to the main queue, "
     373                       "creating a new switchboard to retry." );
     374                g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId );
     375                if( !msn_write( ic, buf, strlen( buf ) ) )
     376                        return FALSE;
     377        }
     378       
     379        msn_sb_destroy( sb );
     380        return FALSE;
    386381}
    387382
  • protocols/nogaim.c

    rca0981a rec86b22  
    665665        u->away = u->status_msg = NULL;
    666666       
    667         if( ( flags & OPT_LOGGED_IN ) && !u->online )
    668         {
     667        if( set_getbool( &ic->irc->set, "show_offline" ) && !u->online )
     668        {
     669                /* always set users as online */
    669670                irc_spawn( ic->irc, u );
    670671                u->online = 1;
     672                if( !( flags & OPT_LOGGED_IN ) )
     673                {
     674                        /* set away message if user isn't really online */
     675                        u->away = g_strdup( "User is offline" );
     676                }
     677        }
     678        else if( ( flags & OPT_LOGGED_IN ) && !u->online )
     679        {
     680                irc_spawn( ic->irc, u );
     681                u->online = 1;
    671682        }
    672683        else if( !( flags & OPT_LOGGED_IN ) && u->online )
     
    674685                struct groupchat *c;
    675686               
    676                 irc_kill( ic->irc, u );
    677                 u->online = 0;
    678                
    679                 /* Remove him/her from the groupchats to prevent PART messages after he/she QUIT already */
    680                 for( c = ic->groupchats; c; c = c->next )
    681                         remove_chat_buddy_silent( c, handle );
    682         }
    683        
     687                if( set_getbool( &ic->irc->set, "show_offline" ) )
     688                {
     689                        /* keep offline users in channel and set away message to "offline" */
     690                        u->away = g_strdup( "User is offline" );
     691
     692                        /* Keep showing him/her in the control channel but not in groupchats. */
     693                        for( c = ic->groupchats; c; c = c->next )
     694                        {
     695                                if( remove_chat_buddy_silent( c, handle ) && c->joined )
     696                                        irc_part( c->ic->irc, u, c->channel );
     697                        }
     698                }
     699                else
     700                {
     701                        /* kill offline users */
     702                        irc_kill( ic->irc, u );
     703                        u->online = 0;
     704
     705                        /* Remove him/her from the groupchats to prevent PART messages after he/she QUIT already */
     706                        for( c = ic->groupchats; c; c = c->next )
     707                                remove_chat_buddy_silent( c, handle );
     708                }
     709        }
     710
    684711        if( flags & OPT_AWAY )
    685712        {
     
    706733        }
    707734       
    708         /* LISPy... */
    709         if( ( set_getbool( &ic->irc->set, "away_devoice" ) ) &&         /* Don't do a thing when user doesn't want it */
    710             ( u->online ) &&                                            /* Don't touch offline people */
    711             ( ( ( u->online != oo ) && !u->away ) ||                    /* Voice joining people */
    712               ( ( u->online == oo ) && ( oa == !u->away ) ) ) )         /* (De)voice people changing state */
     735        /* early if-clause for show_offline even if there is some redundant code here because this isn't LISP but C ;) */
     736        if( set_getbool( &ic->irc->set, "show_offline" ) && set_getbool( &ic->irc->set, "away_devoice" ) )
    713737        {
    714738                char *from;
     
    723747                                                            ic->irc->myhost );
    724748                }
    725                 irc_write( ic->irc, ":%s MODE %s %cv %s", from, ic->irc->channel,
    726                                                           u->away?'-':'+', u->nick );
    727                 g_free( from );
     749
     750                /* if we use show_offline, we op online users, voice away users, and devoice/deop offline users */
     751                if( flags & OPT_LOGGED_IN )
     752                {
     753                        /* user is "online" (either really online or away) */
     754                        irc_write( ic->irc, ":%s MODE %s %cv%co %s %s", from, ic->irc->channel,
     755                                                                  u->away?'+':'-', u->away?'-':'+', u->nick, u->nick );
     756                }
     757                else
     758                {
     759                        /* user is offline */
     760                        irc_write( ic->irc, ":%s MODE %s -vo %s %s", from, ic->irc->channel, u->nick, u->nick );
     761                }
     762        }
     763        else
     764        {
     765                /* LISPy... */
     766                if( ( set_getbool( &ic->irc->set, "away_devoice" ) ) &&         /* Don't do a thing when user doesn't want it */
     767                    ( u->online ) &&                                            /* Don't touch offline people */
     768                    ( ( ( u->online != oo ) && !u->away ) ||                    /* Voice joining people */
     769                      ( ( u->online == oo ) && ( oa == !u->away ) ) ) )         /* (De)voice people changing state */
     770                {
     771                        char *from;
     772
     773                        if( set_getbool( &ic->irc->set, "simulate_netsplit" ) )
     774                        {
     775                                from = g_strdup( ic->irc->myhost );
     776                        }
     777                        else
     778                        {
     779                                from = g_strdup_printf( "%s!%s@%s", ic->irc->mynick, ic->irc->mynick,
     780                                                                    ic->irc->myhost );
     781                        }
     782                        irc_write( ic->irc, ":%s MODE %s %cv %s", from, ic->irc->channel,
     783                                                                  u->away?'-':'+', u->nick );
     784                        g_free( from );
     785                }
    728786        }
    729787}
     
    12021260                return g_strdup_printf( "\x02[\x02\x02\x02%04d-%02d-%02d "
    12031261                                        "%02d:%02d:%02d\x02]\x02 ",
    1204                                         msg.tm_year + 1900, msg.tm_mon, msg.tm_mday,
     1262                                        msg.tm_year + 1900, msg.tm_mon + 1, msg.tm_mday,
    12051263                                        msg.tm_hour, msg.tm_min, msg.tm_sec );
    12061264}
  • protocols/oscar/oscar.c

    rca0981a rec86b22  
    205205static int gaim_icbm_param_info  (aim_session_t *, aim_frame_t *, ...);
    206206static int gaim_parse_genericerr (aim_session_t *, aim_frame_t *, ...);
    207 static int gaim_memrequest       (aim_session_t *, aim_frame_t *, ...);
    208207static int gaim_selfinfo         (aim_session_t *, aim_frame_t *, ...);
    209208static int gaim_offlinemsg       (aim_session_t *, aim_frame_t *, ...);
     
    570569        aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ERROR, gaim_parse_genericerr, 0);
    571570        aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BOS, AIM_CB_BOS_ERROR, gaim_parse_genericerr, 0);
    572         aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, 0x1f, gaim_memrequest, 0);
    573571        aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SELFINFO, gaim_selfinfo, 0);
    574572        aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSG, gaim_offlinemsg, 0);
     
    604602}
    605603
    606 struct pieceofcrap {
    607         struct im_connection *ic;
    608         unsigned long offset;
    609         unsigned long len;
    610         char *modname;
    611         int fd;
    612         aim_conn_t *conn;
    613         unsigned int inpa;
    614 };
    615 
    616 static gboolean damn_you(gpointer data, gint source, b_input_condition c)
    617 {
    618         struct pieceofcrap *pos = data;
    619         struct oscar_data *od = pos->ic->proto_data;
    620         char in = '\0';
    621         int x = 0;
    622         unsigned char m[17];
    623 
    624         while (read(pos->fd, &in, 1) == 1) {
    625                 if (in == '\n')
    626                         x++;
    627                 else if (in != '\r')
    628                         x = 0;
    629                 if (x == 2)
    630                         break;
    631                 in = '\0';
    632         }
    633         if (in != '\n') {
    634                 imcb_error(pos->ic, "Gaim was unable to get a valid hash for logging into AIM."
    635                                 " You may be disconnected shortly.");
    636                 b_event_remove(pos->inpa);
    637                 closesocket(pos->fd);
    638                 g_free(pos);
    639                 return FALSE;
    640         }
    641         /* [WvG] Wheeeee! Who needs error checking anyway? ;-) */
    642         read(pos->fd, m, 16);
    643         m[16] = '\0';
    644         b_event_remove(pos->inpa);
    645         closesocket(pos->fd);
    646         aim_sendmemblock(od->sess, pos->conn, 0, 16, m, AIM_SENDMEMBLOCK_FLAG_ISHASH);
    647         g_free(pos);
    648        
    649         return FALSE;
    650 }
    651 
    652 static gboolean straight_to_hell(gpointer data, gint source, b_input_condition cond) {
    653         struct pieceofcrap *pos = data;
    654         char buf[BUF_LONG];
    655 
    656         if (source < 0) {
    657                 imcb_error(pos->ic, "Gaim was unable to get a valid hash for logging into AIM."
    658                                 " You may be disconnected shortly.");
    659                 if (pos->modname)
    660                         g_free(pos->modname);
    661                 g_free(pos);
    662                 return FALSE;
    663         }
    664 
    665         g_snprintf(buf, sizeof(buf), "GET " AIMHASHDATA
    666                         "?offset=%ld&len=%ld&modname=%s HTTP/1.0\n\n",
    667                         pos->offset, pos->len, pos->modname ? pos->modname : "");
    668         write(pos->fd, buf, strlen(buf));
    669         if (pos->modname)
    670                 g_free(pos->modname);
    671         pos->inpa = b_input_add(pos->fd, B_EV_IO_READ, damn_you, pos);
    672         return FALSE;
    673 }
    674 
    675604/* size of icbmui.ocm, the largest module in AIM 3.5 */
    676605#define AIM_MAX_FILE_SIZE 98304
    677 
    678 int gaim_memrequest(aim_session_t *sess, aim_frame_t *fr, ...) {
    679         va_list ap;
    680         struct pieceofcrap *pos;
    681         guint32 offset, len;
    682         char *modname;
    683         int fd;
    684 
    685         va_start(ap, fr);
    686         offset = (guint32)va_arg(ap, unsigned long);
    687         len = (guint32)va_arg(ap, unsigned long);
    688         modname = va_arg(ap, char *);
    689         va_end(ap);
    690 
    691         if (len == 0) {
    692                 aim_sendmemblock(sess, fr->conn, offset, len, NULL,
    693                                 AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
    694                 return 1;
    695         }
    696         /* uncomment this when you're convinced it's right. remember, it's been wrong before.
    697         if (offset > AIM_MAX_FILE_SIZE || len > AIM_MAX_FILE_SIZE) {
    698                 char *buf;
    699                 int i = 8;
    700                 if (modname)
    701                         i += strlen(modname);
    702                 buf = g_malloc(i);
    703                 i = 0;
    704                 if (modname) {
    705                         memcpy(buf, modname, strlen(modname));
    706                         i += strlen(modname);
    707                 }
    708                 buf[i++] = offset & 0xff;
    709                 buf[i++] = (offset >> 8) & 0xff;
    710                 buf[i++] = (offset >> 16) & 0xff;
    711                 buf[i++] = (offset >> 24) & 0xff;
    712                 buf[i++] = len & 0xff;
    713                 buf[i++] = (len >> 8) & 0xff;
    714                 buf[i++] = (len >> 16) & 0xff;
    715                 buf[i++] = (len >> 24) & 0xff;
    716                 aim_sendmemblock(sess, command->conn, offset, i, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
    717                 g_free(buf);
    718                 return 1;
    719         }
    720         */
    721 
    722         pos = g_new0(struct pieceofcrap, 1);
    723         pos->ic = sess->aux_data;
    724         pos->conn = fr->conn;
    725 
    726         pos->offset = offset;
    727         pos->len = len;
    728         pos->modname = modname ? g_strdup(modname) : NULL;
    729 
    730         fd = proxy_connect("gaim.sourceforge.net", 80, straight_to_hell, pos);
    731         if (fd < 0) {
    732                 if (pos->modname)
    733                         g_free(pos->modname);
    734                 g_free(pos);
    735                 imcb_error(sess->aux_data, "Gaim was unable to get a valid hash for logging into AIM."
    736                                 " You may be disconnected shortly.");
    737         }
    738         pos->fd = fd;
    739 
    740         return 1;
    741 }
    742606
    743607static int gaim_parse_login(aim_session_t *sess, aim_frame_t *fr, ...) {
     
    26512515        char * chatname;
    26522516       
    2653         chatname = g_strdup_printf("%s%d", ic->acc->user, chat_id++);
     2517        chatname = g_strdup_printf("%s%s_%d", isdigit(*ic->acc->user) ? "icq_" : "",
     2518                                   ic->acc->user, chat_id++);
    26542519 
    26552520        ret = oscar_chat_join(ic, chatname, NULL, NULL);
  • protocols/twitter/twitter.c

    rca0981a rec86b22  
    2323
    2424#include "nogaim.h"
     25#include "oauth.h"
    2526#include "twitter.h"
    2627#include "twitter_http.h"
    2728#include "twitter_lib.h"
    28 
    2929
    3030/**
     
    5050        return (ic->flags & OPT_LOGGED_IN) == OPT_LOGGED_IN;
    5151}
     52
     53static void twitter_main_loop_start( struct im_connection *ic )
     54{
     55        struct twitter_data *td = ic->proto_data;
     56       
     57        imcb_log( ic, "Connecting to Twitter" );
     58
     59        // Run this once. After this queue the main loop function.
     60        twitter_main_loop(ic, -1, 0);
     61
     62        // Queue the main_loop
     63        // Save the return value, so we can remove the timeout on logout.
     64        td->main_loop_id = b_timeout_add(60000, twitter_main_loop, ic);
     65}
     66
     67
     68static const struct oauth_service twitter_oauth =
     69{
     70        "http://api.twitter.com/oauth/request_token",
     71        "http://api.twitter.com/oauth/access_token",
     72        "http://api.twitter.com/oauth/authorize",
     73        .consumer_key = "xsDNKJuNZYkZyMcu914uEA",
     74        .consumer_secret = "FCxqcr0pXKzsF9ajmP57S3VQ8V6Drk4o2QYtqMcOszo",
     75};
     76
     77static gboolean twitter_oauth_callback( struct oauth_info *info );
     78
     79static void twitter_oauth_start( struct im_connection *ic )
     80{
     81        struct twitter_data *td = ic->proto_data;
     82       
     83        imcb_log( ic, "Requesting OAuth request token" );
     84
     85        td->oauth_info = oauth_request_token( &twitter_oauth, twitter_oauth_callback, ic );
     86}
     87
     88static gboolean twitter_oauth_callback( struct oauth_info *info )
     89{
     90        struct im_connection *ic = info->data;
     91        struct twitter_data *td;
     92       
     93        if( !g_slist_find( twitter_connections, ic ) )
     94                return FALSE;
     95       
     96        td = ic->proto_data;
     97        if( info->stage == OAUTH_REQUEST_TOKEN )
     98        {
     99                char name[strlen(ic->acc->user)+9], *msg;
     100               
     101                if( info->request_token == NULL )
     102                {
     103                        imcb_error( ic, "OAuth error: %s", info->http->status_string );
     104                        imc_logout( ic, TRUE );
     105                        return FALSE;
     106                }
     107               
     108                sprintf( name, "twitter_%s", ic->acc->user );
     109                msg = g_strdup_printf( "To finish OAuth authentication, please visit "
     110                                       "%s and respond with the resulting PIN code.",
     111                                       info->auth_url );
     112                imcb_buddy_msg( ic, name, msg, 0, 0 );
     113                g_free( msg );
     114        }
     115        else if( info->stage == OAUTH_ACCESS_TOKEN )
     116        {
     117                if( info->token == NULL || info->token_secret == NULL )
     118                {
     119                        imcb_error( ic, "OAuth error: %s", info->http->status_string );
     120                        imc_logout( ic, TRUE );
     121                        return FALSE;
     122                }
     123               
     124                /* IM mods didn't do this so far and it's ugly but I should
     125                   be able to get away with it... */
     126                g_free( ic->acc->pass );
     127                ic->acc->pass = oauth_to_string( info );
     128               
     129                twitter_main_loop_start( ic );
     130        }
     131       
     132        return TRUE;
     133}
     134
    52135
    53136static char *set_eval_mode( set_t *set, char *value )
     
    61144}
    62145
     146static gboolean twitter_length_check( struct im_connection *ic, gchar *msg )
     147{
     148        int max = set_getint( &ic->acc->set, "message_length" ), len;
     149       
     150        if( max == 0 || ( len = g_utf8_strlen( msg, -1 ) ) <= max )
     151                return TRUE;
     152       
     153        imcb_error( ic, "Maximum message length exceeded: %d > %d", len, max );
     154       
     155        return FALSE;
     156}
     157
    63158static void twitter_init( account_t *acc )
    64159{
    65160        set_t *s;
     161       
     162        s = set_add( &acc->set, "message_length", "140", set_eval_int, acc );
    66163       
    67164        s = set_add( &acc->set, "mode", "one", set_eval_mode, acc );
    68165        s->flags |= ACC_SET_OFFLINE_ONLY;
     166       
     167        s = set_add( &acc->set, "oauth", "true", set_eval_bool, acc );
    69168}
    70169
     
    80179
    81180        twitter_connections = g_slist_append( twitter_connections, ic );
    82 
     181        ic->proto_data = td;
     182        ic->flags |= OPT_DOES_HTML;
     183       
    83184        td->user = acc->user;
    84         td->pass = acc->pass;
     185        if( !set_getbool( &acc->set, "oauth" ) )
     186                td->pass = g_strdup( acc->pass );
     187        else if( strstr( acc->pass, "oauth_token=" ) )
     188                td->oauth_info = oauth_from_string( acc->pass, &twitter_oauth );
    85189        td->home_timeline_id = 0;
    86 
    87         ic->proto_data = td;
    88 
    89         imcb_log( ic, "Connecting to Twitter" );
    90 
    91         // Run this once. After this queue the main loop function.
    92         twitter_main_loop(ic, -1, 0);
    93 
    94         // Queue the main_loop
    95         // Save the return value, so we can remove the timeout on logout.
    96         td->main_loop_id = b_timeout_add(60000, twitter_main_loop, ic);
    97190       
    98191        sprintf( name, "twitter_%s", acc->user );
    99192        imcb_add_buddy( ic, name, NULL );
    100193        imcb_buddy_status( ic, name, OPT_LOGGED_IN, NULL, NULL );
     194       
     195        if( td->pass || td->oauth_info )
     196                twitter_main_loop_start( ic );
     197        else
     198                twitter_oauth_start( ic );
    101199}
    102200
     
    119217        if( td )
    120218        {
     219                oauth_info_free( td->oauth_info );
     220                g_free( td->pass );
    121221                g_free( td );
    122222        }
     
    130230static int twitter_buddy_msg( struct im_connection *ic, char *who, char *message, int away )
    131231{
     232        struct twitter_data *td = ic->proto_data;
     233       
    132234        if (g_strncasecmp(who, "twitter_", 8) == 0 &&
    133235            g_strcasecmp(who + 8, ic->acc->user) == 0)
    134                 twitter_post_status(ic, message);
     236        {
     237                if( set_getbool( &ic->acc->set, "oauth" ) &&
     238                    td->oauth_info && td->oauth_info->token == NULL )
     239                {
     240                        if( !oauth_access_token( message, td->oauth_info ) )
     241                        {
     242                                imcb_error( ic, "OAuth error: %s", "Failed to send access token request" );
     243                                imc_logout( ic, TRUE );
     244                                return FALSE;
     245                        }
     246                }
     247                else if( twitter_length_check(ic, message) )
     248                        twitter_post_status(ic, message);
     249        }
    135250        else
     251        {
    136252                twitter_direct_messages_new(ic, who, message);
    137        
     253        }
    138254        return( 0 );
    139255}
     
    160276static void twitter_chat_msg( struct groupchat *c, char *message, int flags )
    161277{
    162         if( c && message )
     278        if( c && message && twitter_length_check(c->ic, message))
    163279                twitter_post_status(c->ic, message);
    164280}
  • protocols/twitter/twitter.h

    rca0981a rec86b22  
    3737        char* user;
    3838        char* pass;
     39        struct oauth_info *oauth_info;
    3940        guint64 home_timeline_id;
    4041        gint main_loop_id;
  • protocols/twitter/twitter_http.c

    rca0981a rec86b22  
    2929****************************************************************************/
    3030
    31 #include "twitter_http.h"
    3231#include "twitter.h"
    3332#include "bitlbee.h"
     
    3534#include "misc.h"
    3635#include "base64.h"
     36#include "oauth.h"
    3737#include <ctype.h>
    3838#include <errno.h>
     39
     40#include "twitter_http.h"
    3941
    4042
     
    4547 * This is actually pretty generic function... Perhaps it should move to the lib/http_client.c
    4648 */
    47 void *twitter_http(char *url_string, http_input_function func, gpointer data, int is_post, char* user, char* pass, char** arguments, int arguments_len)
     49void *twitter_http(char *url_string, http_input_function func, gpointer data, int is_post, char* user, char* pass, struct oauth_info* oi, char** arguments, int arguments_len)
    4850{
    4951        url_t *url = g_new0( url_t, 1 );
     
    110112
    111113        // If a pass and user are given we append them to the request.
    112         if (userpass_base64)
     114        if (oi)
     115        {
     116                char *full_header;
     117               
     118                full_header = oauth_http_header(oi, is_post ? "POST" : "GET",
     119                                                url_string, url_arguments);
     120               
     121                tmp = g_strdup_printf("%sAuthorization: %s\r\n", request, full_header);
     122                g_free(request);
     123                g_free(full_header);
     124                request = tmp;
     125        }
     126        else if (userpass_base64)
    113127        {
    114128                tmp = g_strdup_printf("%sAuthorization: Basic %s\r\n", request, userpass_base64);
  • protocols/twitter/twitter_http.h

    rca0981a rec86b22  
    2828#include "http_client.h"
    2929
     30struct oauth_info;
     31
    3032void *twitter_http(char *url_string, http_input_function func, gpointer data, int is_post,
    31                                         char* user, char* pass, char** arguments, int arguments_len);
     33                   char* user, char* pass, struct oauth_info *oi, char** arguments, int arguments_len);
    3234
    3335#endif //_TWITTER_HTTP_H
  • protocols/twitter/twitter_lib.c

    rca0981a rec86b22  
    130130        args[0] = "cursor";
    131131        args[1] = g_strdup_printf ("%d", next_cursor);
    132         twitter_http(TWITTER_FRIENDS_IDS_URL, twitter_http_get_friends_ids, ic, 0, td->user, td->pass, args, 2);
     132        twitter_http(TWITTER_FRIENDS_IDS_URL, twitter_http_get_friends_ids, ic, 0, td->user, td->pass, td->oauth_info, args, 2);
    133133
    134134        g_free(args[1]);
     
    396396        }
    397397
    398         twitter_http(TWITTER_HOME_TIMELINE_URL, twitter_http_get_home_timeline, ic, 0, td->user, td->pass, args, td->home_timeline_id ? 4 : 2);
     398        twitter_http(TWITTER_HOME_TIMELINE_URL, twitter_http_get_home_timeline, ic, 0, td->user, td->pass, td->oauth_info, args, td->home_timeline_id ? 4 : 2);
    399399
    400400        g_free(args[1]);
     
    510510        {
    511511                td->http_fails = 0;
    512                 if (!ic->flags & OPT_LOGGED_IN)
     512                if (!(ic->flags & OPT_LOGGED_IN))
    513513                        imcb_connected(ic);
    514514        }
     
    620620        args[1] = g_strdup_printf ("%d", next_cursor);
    621621
    622         twitter_http(TWITTER_SHOW_FRIENDS_URL, twitter_http_get_statuses_friends, ic, 0, td->user, td->pass, args, 2);
     622        twitter_http(TWITTER_SHOW_FRIENDS_URL, twitter_http_get_statuses_friends, ic, 0, td->user, td->pass, td->oauth_info, args, 2);
    623623
    624624        g_free(args[1]);
     
    654654        args[0] = "status";
    655655        args[1] = msg;
    656         twitter_http(TWITTER_STATUS_UPDATE_URL, twitter_http_post_status, ic, 1, td->user, td->pass, args, 2);
     656        twitter_http(TWITTER_STATUS_UPDATE_URL, twitter_http_post_status, ic, 1, td->user, td->pass, td->oauth_info, args, 2);
    657657//      g_free(args[1]);
    658658}
     
    672672        args[3] = msg;
    673673        // Use the same callback as for twitter_post_status, since it does basically the same.
    674         twitter_http(TWITTER_DIRECT_MESSAGES_NEW_URL, twitter_http_post_status, ic, 1, td->user, td->pass, args, 4);
     674        twitter_http(TWITTER_DIRECT_MESSAGES_NEW_URL, twitter_http_post_status, ic, 1, td->user, td->pass, td->oauth_info, args, 4);
    675675//      g_free(args[1]);
    676676//      g_free(args[3]);
  • protocols/yahoo/yahoo.c

    rca0981a rec86b22  
    138138        struct im_connection *ic = imcb_new( acc );
    139139        struct byahoo_data *yd = ic->proto_data = g_new0( struct byahoo_data, 1 );
     140        char *s;
    140141       
    141142        yd->logged_in = FALSE;
    142143        yd->current_status = YAHOO_STATUS_AVAILABLE;
     144       
     145        if( ( s = strchr( acc->user, '@' ) ) && g_strcasecmp( s, "@yahoo.com" ) == 0 )
     146                imcb_error( ic, "Your Yahoo! username should just be a username. "
     147                                "Do not include any @domain part." );
    143148       
    144149        imcb_log( ic, "Connecting" );
     
    828833        YList *m;
    829834       
     835        if( g_strcasecmp( who, ic->acc->user ) == 0 )
     836                /* WTF, Yahoo! seems to echo these now? */
     837                return;
     838       
    830839        inv = g_malloc( sizeof( struct byahoo_conf_invitation ) );
    831840        memset( inv, 0, sizeof( struct byahoo_conf_invitation ) );
Note: See TracChangeset for help on using the changeset viewer.