Changes in / [5cb9461:1a2c1c0]


Ignore:
Files:
8 added
20 edited

Legend:

Unmodified
Added
Removed
  • Makefile

    r5cb9461 r1a2c1c0  
    1111# Program variables
    1212objects = bitlbee.o dcc.o help.o ipc.o irc.o irc_im.o irc_channel.o irc_commands.o irc_send.o irc_user.o irc_util.o nick.o $(OTR_BI) query.o root_commands.o set.o storage.o $(STORAGE_OBJS)
    13 headers = bitlbee.h commands.h conf.h config.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h lib/events.h lib/ftutil.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/account.h protocols/bee.h protocols/ft.h protocols/nogaim.h
     13headers = bitlbee.h commands.h conf.h config.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h lib/events.h lib/ftutil.h lib/http_client.h lib/ini.h lib/json.h lib/json_util.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/account.h protocols/bee.h protocols/ft.h protocols/nogaim.h
    1414subdirs = lib protocols
    1515
  • configure

    r5cb9461 r1a2c1c0  
    211211echo CFLAGS+=-I${srcdir} -I${srcdir}/lib -I${srcdir}/protocols -I. >> Makefile.settings
    212212
    213 echo CFLAGS+=-DHAVE_CONFIG_H >> Makefile.settings
     213echo CFLAGS+=-DHAVE_CONFIG_H -D_GNU_SOURCE >> Makefile.settings
    214214
    215215if [ -n "$CC" ]; then
  • lib/http_client.c

    r5cb9461 r1a2c1c0  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2012 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2013 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    6969        req->request_length = strlen( request );
    7070        req->redir_ttl = 3;
     71        req->content_length = -1;
    7172       
    7273        if( getenv( "BITLBEE_DEBUG" ) )
     
    9697        request = g_strdup_printf( "GET %s HTTP/1.0\r\n"
    9798                                   "Host: %s\r\n"
    98                                    "Connection: close\r\n"
    9999                                   "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n"
    100100                                   "\r\n", url->file, url->host );
     
    193193}
    194194
     195typedef enum {
     196        CR_OK,
     197        CR_EOF,
     198        CR_ERROR,
     199        CR_ABORT,
     200} http_ret_t;
     201
    195202static gboolean http_handle_headers( struct http_request *req );
     203static http_ret_t http_process_chunked_data( struct http_request *req, const char *buffer, int len );
     204static http_ret_t http_process_data( struct http_request *req, const char *buffer, int len );
    196205
    197206static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond )
     
    199208        struct http_request *req = data;
    200209        char buffer[4096];
    201         char *s;
    202         size_t content_length;
    203210        int st;
    204211       
     
    244251        }
    245252       
    246         if( st > 0 && !req->sbuf )
    247         {
    248                 req->reply_headers = g_realloc( req->reply_headers, req->bytes_read + st + 1 );
    249                 memcpy( req->reply_headers + req->bytes_read, buffer, st );
    250                 req->bytes_read += st;
    251                
    252                 st = 0;
    253         }
    254        
    255         if( st >= 0 && ( req->flags & HTTPC_STREAMING ) )
    256         {
    257                 if( !req->reply_body &&
    258                     ( strstr( req->reply_headers, "\r\n\r\n" ) ||
    259                       strstr( req->reply_headers, "\n\n" ) ) )
    260                 {
    261                         size_t hlen;
    262                        
    263                         /* We've now received all headers, so process them once
    264                            before we start feeding back data. */
    265                         if( !http_handle_headers( req ) )
    266                                 return FALSE;
    267                        
    268                         hlen = req->reply_body - req->reply_headers;
    269                        
    270                         req->sblen = req->bytes_read - hlen;
    271                         req->sbuf = g_memdup( req->reply_body, req->sblen + 1 );
    272                         req->reply_headers = g_realloc( req->reply_headers, hlen + 1 );
    273                        
    274                         req->reply_body = req->sbuf;
    275                 }
    276                
    277                 if( st > 0 )
    278                 {
    279                         int pos = req->reply_body - req->sbuf;
    280                         req->sbuf = g_realloc( req->sbuf, req->sblen + st + 1 );
    281                         memcpy( req->sbuf + req->sblen, buffer, st );
    282                         req->bytes_read += st;
    283                         req->sblen += st;
    284                         req->sbuf[req->sblen] = '\0';
    285                         req->reply_body = req->sbuf + pos;
    286                         req->body_size = req->sblen - pos;
    287                 }
    288                
    289                 if( req->reply_body )
    290                         req->func( req );
    291         }
     253        if( st > 0 )
     254        {
     255                http_ret_t c;
     256               
     257                if( req->flags & HTTPC_CHUNKED )
     258                        c = http_process_chunked_data( req, buffer, st );
     259                else
     260                        c = http_process_data( req, buffer, st );
     261               
     262                if( c == CR_EOF )
     263                        goto eof;
     264                else if( c == CR_ERROR || c == CR_ABORT )
     265                        return FALSE;
     266        }
     267       
     268        if( req->content_length != -1 &&
     269            req->body_size >= req->content_length )
     270                goto eof;
    292271       
    293272        if( ssl_pending( req->ssl ) )
     
    311290                goto cleanup;
    312291        }
    313        
    314         if( !( req->flags & HTTPC_STREAMING ) )
    315         {
    316                 /* Returns FALSE if we were redirected, in which case we should abort
    317                    and not run any callback yet. */
    318                 if( !http_handle_headers( req ) )
    319                         return FALSE;
    320         }
    321292
    322293cleanup:
     
    326297                closesocket( req->fd );
    327298       
    328         if( ( s = get_rfc822_header( req->reply_headers, "Content-Length", 0 ) ) &&
    329             sscanf( s, "%zd", &content_length ) == 1 )
    330         {
    331                 if( content_length < req->body_size )
    332                 {
    333                         req->status_code = -1;
    334                         g_free( req->status_string );
    335                         req->status_string = g_strdup( "Response truncated" );
    336                 }
    337         }
    338         g_free( s );
     299        if( req->body_size < req->content_length )
     300        {
     301                req->status_code = -1;
     302                g_free( req->status_string );
     303                req->status_string = g_strdup( "Response truncated" );
     304        }
    339305       
    340306        if( getenv( "BITLBEE_DEBUG" ) && req )
     
    347313}
    348314
     315static http_ret_t http_process_chunked_data( struct http_request *req, const char *buffer, int len )
     316{
     317        char *chunk, *eos, *s;
     318       
     319        if( len < 0 )
     320                return TRUE;
     321       
     322        if( len > 0 )
     323        {
     324                req->cbuf = g_realloc( req->cbuf, req->cblen + len + 1 );
     325                memcpy( req->cbuf + req->cblen, buffer, len );
     326                req->cblen += len;
     327                req->cbuf[req->cblen] = '\0';
     328        }
     329       
     330        /* Turns out writing a proper chunked-encoding state machine is not
     331           that simple. :-( I've tested this one feeding it byte by byte so
     332           I hope it's solid now. */
     333        chunk = req->cbuf;
     334        eos = req->cbuf + req->cblen;
     335        while( TRUE )
     336        {
     337                int clen = 0;
     338               
     339                /* Might be a \r\n from the last chunk. */
     340                s = chunk;
     341                while( isspace( *s ) )
     342                        s ++;
     343                /* Chunk length. Might be incomplete. */
     344                if( s < eos && sscanf( s, "%x", &clen ) != 1 )
     345                        return CR_ERROR;
     346                while( isxdigit( *s ) )
     347                        s ++;
     348               
     349                /* If we read anything here, it *must* be \r\n. */
     350                if( strncmp( s, "\r\n", MIN( 2, eos - s ) ) != 0 )
     351                        return CR_ERROR;
     352                s += 2;
     353               
     354                if( s >= eos )
     355                        break;
     356               
     357                /* 0-length chunk means end of response. */     
     358                if( clen == 0 )
     359                        return CR_EOF;
     360               
     361                /* Wait for the whole chunk to arrive. */
     362                if( s + clen > eos )
     363                        break;
     364                if( http_process_data( req, s, clen ) != CR_OK )
     365                        return CR_ABORT;
     366               
     367                chunk = s + clen;
     368        }
     369       
     370        if( chunk != req->cbuf )
     371        {
     372                req->cblen = eos - chunk;
     373                s = g_memdup( chunk, req->cblen + 1 );
     374                g_free( req->cbuf );
     375                req->cbuf = s;
     376        }
     377       
     378        return CR_OK;
     379}
     380
     381static http_ret_t http_process_data( struct http_request *req, const char *buffer, int len )
     382{
     383        if( len <= 0 )
     384                return CR_OK;
     385       
     386        if( !req->reply_body )
     387        {
     388                req->reply_headers = g_realloc( req->reply_headers, req->bytes_read + len + 1 );
     389                memcpy( req->reply_headers + req->bytes_read, buffer, len );
     390                req->bytes_read += len;
     391                req->reply_headers[req->bytes_read] = '\0';
     392               
     393                if( strstr( req->reply_headers, "\r\n\r\n" ) ||
     394                    strstr( req->reply_headers, "\n\n" ) )
     395                {
     396                        /* We've now received all headers. Look for something
     397                           interesting. */
     398                        if( !http_handle_headers( req ) )
     399                                return CR_ABORT;
     400                       
     401                        /* Start parsing the body as chunked if required. */
     402                        if( req->flags & HTTPC_CHUNKED )
     403                                return http_process_chunked_data( req, NULL, 0 );
     404                }
     405        }
     406        else
     407        {
     408                int pos = req->reply_body - req->sbuf;
     409                req->sbuf = g_realloc( req->sbuf, req->sblen + len + 1 );
     410                memcpy( req->sbuf + req->sblen, buffer, len );
     411                req->bytes_read += len;
     412                req->sblen += len;
     413                req->sbuf[req->sblen] = '\0';
     414                req->reply_body = req->sbuf + pos;
     415                req->body_size = req->sblen - pos;
     416        }
     417       
     418        if( ( req->flags & HTTPC_STREAMING ) && req->reply_body )
     419                req->func( req );
     420       
     421        return CR_OK;
     422}
     423
    349424/* Splits headers and body. Checks result code, in case of 300s it'll handle
    350425   redirects. If this returns FALSE, don't call any callbacks! */
    351426static gboolean http_handle_headers( struct http_request *req )
    352427{
    353         char *end1, *end2;
     428        char *end1, *end2, *s;
    354429        int evil_server = 0;
    355430       
     
    377452        }
    378453       
    379         *end1 = 0;
     454        *end1 = '\0';
    380455       
    381456        if( getenv( "BITLBEE_DEBUG" ) )
     
    387462                req->reply_body = end1 + 2;
    388463       
    389         req->body_size = req->reply_headers + req->bytes_read - req->reply_body;
     464        /* Separately allocated space for headers and body. */
     465        req->sblen = req->body_size = req->reply_headers + req->bytes_read - req->reply_body;
     466        req->sbuf = req->reply_body = g_memdup( req->reply_body, req->body_size + 1 );
     467        req->reply_headers = g_realloc( req->reply_headers, end1 - req->reply_headers + 1 );
    390468       
    391469        if( ( end1 = strchr( req->reply_headers, ' ' ) ) != NULL )
     
    452530                           don't need this yet anyway, I won't implement it. */
    453531                       
    454                         req->status_string = g_strdup( "Can't handle recursive redirects" );
     532                        req->status_string = g_strdup( "Can't handle relative redirects" );
    455533                       
    456534                        return TRUE;
     
    460538                        /* A whole URL */
    461539                        url_t *url;
    462                         char *s;
     540                        char *s, *version, *headers;
    463541                        const char *new_method;
    464542                       
     
    488566                                return TRUE;
    489567                        }
     568                        headers = s;
    490569                       
    491570                        /* More or less HTTP/1.0 compliant, from my reading of RFC 2616.
     
    507586                                new_method = "POST";
    508587                       
     588                        if( ( version = strstr( req->request, " HTTP/" ) ) &&
     589                            ( s = strstr( version, "\r\n" ) ) )
     590                        {
     591                                version ++;
     592                                version = g_strndup( version, s - version );
     593                        }
     594                        else
     595                                version = g_strdup( "HTTP/1.0" );
     596                       
    509597                        /* Okay, this isn't fun! We have to rebuild the request... :-( */
    510                         new_request = g_strdup_printf( "%s %s HTTP/1.0\r\nHost: %s%s",
    511                                                        new_method, url->file, url->host, s );
     598                        new_request = g_strdup_printf( "%s %s %s\r\nHost: %s%s",
     599                                                       new_method, url->file, version,
     600                                                       url->host, headers );
    512601                       
    513602                        new_host = g_strdup( url->host );
     
    521610                       
    522611                        g_free( url );
     612                        g_free( version );
    523613                }
    524614               
     
    557647                g_free( req->request );
    558648                g_free( req->reply_headers );
     649                g_free( req->sbuf );
    559650                req->request = new_request;
    560651                req->request_length = strlen( new_request );
    561652                req->bytes_read = req->bytes_written = req->inpa = 0;
    562653                req->reply_headers = req->reply_body = NULL;
     654                req->sbuf = req->cbuf = NULL;
     655                req->sblen = req->cblen = 0;
    563656               
    564657                return FALSE;
     658        }
     659
     660        if( ( s = get_rfc822_header( req->reply_headers, "Content-Length", 0 ) ) &&
     661            sscanf( s, "%d", &req->content_length ) != 1 )
     662                req->content_length = -1;
     663        g_free( s );
     664       
     665        if( ( s = get_rfc822_header( req->reply_headers, "Transfer-Encoding", 0 ) ) )
     666        {
     667                if( strcasestr( s, "chunked" ) )
     668                {
     669                        req->flags |= HTTPC_CHUNKED;
     670                        req->cbuf = req->sbuf;
     671                        req->cblen = req->sblen;
     672                       
     673                        req->reply_body = req->sbuf = g_strdup( "" );
     674                        req->body_size = req->sblen = 0;
     675                }
     676                g_free( s );
    565677        }
    566678       
     
    607719        g_free( req->status_string );
    608720        g_free( req->sbuf );
     721        g_free( req->cbuf );
    609722        g_free( req );
    610723}
  • lib/http_client.h

    r5cb9461 r1a2c1c0  
    4242        HTTPC_STREAMING = 1,
    4343        HTTPC_EOF = 2,
     44        HTTPC_CHUNKED = 4,
    4445       
    4546        /* Let's reserve 0x1000000+ for lib users. */
     
    7778        int bytes_written;
    7879        int bytes_read;
     80        int content_length;     /* "Content-Length:" header or -1 */
    7981       
    8082        /* Used in streaming mode. Caller should read from reply_body. */
    8183        char *sbuf;
    8284        size_t sblen;
     85       
     86        /* Chunked encoding only. Raw chunked stream is decoded from here. */
     87        char *cbuf;
     88        size_t cblen;
    8389};
    8490
  • lib/oauth.c

    r5cb9461 r1a2c1c0  
    262262                             "Content-Type: application/x-www-form-urlencoded\r\n"
    263263                             "Content-Length: %zd\r\n"
    264                              "Connection: close\r\n"
    265264                             "\r\n"
    266265                             "%s", url_p.file, url_p.host, strlen( post ), post );
  • lib/oauth2.c

    r5cb9461 r1a2c1c0  
    22*                                                                           *
    33*  BitlBee - An IRC to IM gateway                                           *
    4 *  Simple OAuth client (consumer) implementation.                           *
     4*  Simple OAuth2 client (consumer) implementation.                          *
    55*                                                                           *
    6 *  Copyright 2010-2012 Wilmer van der Gaast <wilmer@gaast.net>              *
     6*  Copyright 2010-2013 Wilmer van der Gaast <wilmer@gaast.net>              *
    77*                                                                           *
    88*  This program is free software; you can redistribute it and/or modify     *
     
    2222\***************************************************************************/
    2323
     24/* Out of protest, I should rename this file. OAuth2 is a pathetic joke, and
     25   of all things, DEFINITELY NOT A STANDARD. The only thing various OAuth2
     26   implementations have in common is that name, wrongfully stolen from
     27   a pretty nice standard called OAuth 1.0a. That, and the fact that they
     28   use JSON. Wait, no, Facebook's version doesn't use JSON. For some of its
     29   responses.
     30   
     31   Apparently too many people were too retarded to comprehend the elementary
     32   bits of crypto in OAuth 1.0a (took me one afternoon to implement) so
     33   the standard was replaced with what comes down to a complicated scheme
     34   around what's really just application-specific passwords.
     35   
     36   And then a bunch of mostly incompatible implementations. Great work, guys.
     37   
     38   http://hueniverse.com/2012/07/oauth-2-0-and-the-road-to-hell/ */
     39
    2440#include <glib.h>
    2541#include "http_client.h"
     
    2743#include "oauth.h"
    2844#include "json.h"
     45#include "json_util.h"
    2946#include "url.h"
    3047
     
    7996                             "Content-Type: application/x-www-form-urlencoded\r\n"
    8097                             "Content-Length: %zd\r\n"
    81                              "Connection: close\r\n"
    8298                             "\r\n"
    8399                             "%s", url_p.file, url_p.host, strlen( args_s ), args_s );
     
    99115}
    100116
     117static char* oauth2_parse_error( json_value *e )
     118{
     119        /* This does a reasonable job with some of the flavours of error
     120           responses I've seen. Because apparently it's not standardised. */
     121       
     122        if( e->type == json_object )
     123        {
     124                /* Facebook style */
     125                const char *msg = json_o_str( e, "message" );
     126                const char *type = json_o_str( e, "type" );
     127                json_value *code_o = json_o_get( e, "code" );
     128                int code = 0;
     129               
     130                if( code_o && code_o->type == json_integer )
     131                        code = code_o->u.integer;
     132               
     133                return g_strdup_printf( "Error %d: %s", code, msg ? msg : type ? type : "Unknown error" );
     134        }
     135        else if( e->type == json_string )
     136        {
     137                return g_strdup( e->u.string.ptr );
     138        }
     139        return NULL;
     140}
     141
    101142static void oauth2_access_token_done( struct http_request *req )
    102143{
    103144        struct oauth2_access_token_data *cb_data = req->data;
    104         char *atoken = NULL, *rtoken = NULL;
     145        char *atoken = NULL, *rtoken = NULL, *error = NULL;
    105146        char *content_type;
    106147       
     
    110151        content_type = get_rfc822_header( req->reply_headers, "Content-Type", 0 );
    111152       
    112         if( req->status_code != 200 )
    113         {
    114         }
    115         else if( content_type && strstr( content_type, "application/json" ) )
     153        if( content_type && ( strstr( content_type, "application/json" ) ||
     154                              strstr( content_type, "text/javascript" ) ) )
    116155        {
    117156                json_value *js = json_parse( req->reply_body );
    118157                if( js && js->type == json_object )
    119158                {
    120                         int i;
    121                        
    122                         for( i = 0; i < js->u.object.length; i ++ )
     159                        JSON_O_FOREACH( js, k, v )
    123160                        {
    124                                 if( js->u.object.values[i].value->type != json_string )
     161                                if( strcmp( k, "error" ) == 0 )
     162                                        error = oauth2_parse_error( v );
     163                                if( v->type != json_string )
    125164                                        continue;
    126                                 if( strcmp( js->u.object.values[i].name, "access_token" ) == 0 )
    127                                         atoken = g_strdup( js->u.object.values[i].value->u.string.ptr );
    128                                 if( strcmp( js->u.object.values[i].name, "refresh_token" ) == 0 )
    129                                         rtoken = g_strdup( js->u.object.values[i].value->u.string.ptr );
     165                                if( strcmp( k, "access_token" ) == 0 )
     166                                        atoken = g_strdup( v->u.string.ptr );
     167                                if( strcmp( k, "refresh_token" ) == 0 )
     168                                        rtoken = g_strdup( v->u.string.ptr );
    130169                        }
    131170                }
     
    144183        if( getenv( "BITLBEE_DEBUG" ) )
    145184                printf( "Extracted atoken=%s rtoken=%s\n", atoken, rtoken );
     185        if( !atoken && !rtoken && !error )
     186                error = g_strdup( "Unusuable response" );
    146187       
    147         cb_data->func( cb_data->data, atoken, rtoken );
     188        cb_data->func( cb_data->data, atoken, rtoken, error );
    148189        g_free( content_type );
    149190        g_free( atoken );
    150191        g_free( rtoken );
     192        g_free( error );
    151193        g_free( cb_data );
    152194}
  • lib/oauth2.h

    r5cb9461 r1a2c1c0  
    44*  Simple OAuth2 client (consumer) implementation.                          *
    55*                                                                           *
    6 *  Copyright 2010-2011 Wilmer van der Gaast <wilmer@gaast.net>              *
     6*  Copyright 2010-2013 Wilmer van der Gaast <wilmer@gaast.net>              *
    77*                                                                           *
    88*  This program is free software; you can redistribute it and/or modify     *
     
    2525   module, and from http://code.google.com/apis/accounts/docs/OAuth2.html . */
    2626
    27 typedef void (*oauth2_token_callback)( gpointer data, const char *atoken, const char *rtoken );
     27typedef void (*oauth2_token_callback)( gpointer data, const char *atoken,
     28                                       const char *rtoken, const char *error );
    2829
    2930struct oauth2_service
  • lib/proxy.c

    r5cb9461 r1a2c1c0  
    158158                }
    159159
    160                 event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port, fd);
     160                event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port_, fd);
    161161       
    162162                if (connect(fd, phb->gai_cur->ai_addr, phb->gai_cur->ai_addrlen) < 0 && !sockerr_again()) {
  • lib/ssl_nss.c

    r5cb9461 r1a2c1c0  
    152152        conn->func = func;
    153153        conn->data = data;
    154         conn->hostname = hostname;
     154        conn->hostname = g_strdup(hostname);
    155155
    156156        /* For now, SSL verification is globally enabled by setting the cafile
     
    296296                PR_Close(conn->prfd);
    297297
    298         g_free(conn->hostname);
     298        g_free(conn->hostname);
    299299        g_free(conn);
    300300}
  • nick.c

    r5cb9461 r1a2c1c0  
    392392       
    393393        for( i = 0; nick[i]; i ++ )
    394                 nick[i] = tab[(int)nick[i]];
     394                if( nick[i] < 0x7f )
     395                        nick[i] = tab[(int)nick[i]];
    395396       
    396397        return nick_ok( irc, nick );
  • protocols/jabber/sasl.c

    r5cb9461 r1a2c1c0  
    483483}
    484484
    485 static void sasl_oauth2_got_token( gpointer data, const char *access_token, const char *refresh_token );
     485static void sasl_oauth2_got_token( gpointer data, const char *access_token, const char *refresh_token, const char *error );
    486486
    487487int sasl_oauth2_get_refresh_token( struct im_connection *ic, const char *msg )
     
    514514}
    515515
    516 static void sasl_oauth2_got_token( gpointer data, const char *access_token, const char *refresh_token )
     516static void sasl_oauth2_got_token( gpointer data, const char *access_token, const char *refresh_token, const char *error )
    517517{
    518518        struct im_connection *ic = data;
     
    527527        if( access_token == NULL )
    528528        {
    529                 imcb_error( ic, "OAuth failure (missing access token)" );
     529                imcb_error( ic, "OAuth failure (%s)", error );
    530530                imc_logout( ic, TRUE );
    531531                return;
  • protocols/oscar/oscar.c

    r5cb9461 r1a2c1c0  
    981981               
    982982                if (args->icbmflags & AIM_IMFLAGS_UNICODE)
    983                         src = "UNICODEBIG";
     983                        src = "UCS-2BE";
    984984                else
    985985                        src = "ISO8859-1";
     
    17691769                                args.flags |= AIM_IMFLAGS_ISO_8859_1;
    17701770                                len = ret;
    1771                         } else if ((ret = do_iconv("UTF-8", "UNICODEBIG", message, s, len, BUF_LONG)) >= 0) {
     1771                        } else if ((ret = do_iconv("UTF-8", "UCS-2BE", message, s, len, BUF_LONG)) >= 0) {
    17721772                                args.flags |= AIM_IMFLAGS_UNICODE;
    17731773                                len = ret;
     
    24062406                        flags |= AIM_CHATFLAGS_ISO_8859_1;
    24072407                        len = ret;
    2408                 } else if ((ret = do_iconv("UTF-8", "UNICODEBIG", message, s, len, BUF_LONG)) >= 0) {
     2408                } else if ((ret = do_iconv("UTF-8", "UCS-2BE", message, s, len, BUF_LONG)) >= 0) {
    24092409                        flags |= AIM_CHATFLAGS_UNICODE;
    24102410                        len = ret;
  • protocols/skype/README

    r5cb9461 r1a2c1c0  
    5858connects to Skype, finally BitlBee can connect to `skyped`.
    5959
    60 === Installing under Frugalware or Debian
    61 
    62 - Install the necessary packages:
    63 
    64 ----
    65 # pacman-g2 -S bitlbee-skype
    66 ----
    67 
    68 or
     60=== Installing
     61
     62Either use your package manager to install the Skype plugin, using something
     63like:
    6964
    7065----
     
    7267----
    7368
    74 (the later from the unstable repo)
    75 
    76 and you don't have to compile anything manually.
    77 
    78 === Installing under OS X
    79 
    80 - Install the necessary packages from ports:
    81 
    82 NOTE: You have to edit the Portfile manually to include the install-dev target,
    83 just append install-dev after install-etc.
    84 
    85 ----
    86 # port -v install bitlbee
    87 ----
    88 
    89 and you have to install `bitlbee-skype` and `skype4py` from
    90 source.
    91 
    92 === Installing from source
    93 
    94 NOTE: bitlbee-skype by default builds and installs skyped and the
    95 plugin. In case you just want to install the plugin for a public server
    96 or you want to use skyped with a public server (like
    97 `bitlbee1.asnetinc.net`), you don't need both.
    98 
    99 - You need the latest stable BitlBee release (unless you want to use a
    100   public server):
    101 
    102 ----
    103 $ wget http://get.bitlbee.org/src/bitlbee-@BITLBEE_VERSION@.tar.gz
    104 $ tar xf bitlbee-@BITLBEE_VERSION@.tar.gz
    105 $ cd bitlbee-@BITLBEE_VERSION@
    106 ----
    107 
    108 - Now compile and install it:
    109 
    110 ----
    111 $ ./configure
    112 $ make
    113 # make install install-dev
    114 ----
    115 
    116 - To install http://skype4py.sourceforge.net/[Skype4Py] from source
    117   (unless you want to install the plugin for a public server):
    118 
    119 ----
    120 $ tar -zxvf Skype4Py-x.x.x.x.tar.gz
    121 $ cd Skype4Py-x.x.x.x
    122 # python setup.py install
    123 ----
    124 
    125 - Get the plugin code (in an empty dir, or whereever you want, it does
    126   not matter):
    127 
    128 ----
    129 $ wget http://vmiklos.hu/project/bitlbee-skype/bitlbee-skype-@VERSION@.tar.gz
    130 $ tar xf bitlbee-skype-@VERSION@.tar.gz
    131 $ cd bitlbee-skype-@VERSION@
    132 ----
    133 
    134 - Compile and install it:
    135 
    136 ----
    137 $ ./configure
    138 $ make
    139 # make install
    140 ----
    141 
    142 This will install the plugin to where BitlBee expects them, which is
    143 `/usr/local/lib/bitlbee` if you installed BitlBee from source.
     69Or install http://sourceforge.net/projects/skype4py/[Skype4Py], and build
     70BitlBee with `--skype=1`.
    14471
    14572=== Configuring
  • protocols/skype/skype.c

    r5cb9461 r1a2c1c0  
    344344        ptr++;
    345345        if (!strncmp(ptr, "ONLINESTATUS ", 13)) {
    346                         if (!strcmp(user, sd->username))
    347                                 return;
    348                         if (!set_getbool(&ic->acc->set, "test_join")
     346                if (!strlen(user) || !strcmp(user, sd->username))
     347                        return;
     348                if (!set_getbool(&ic->acc->set, "test_join")
    349349                                && !strcmp(user, "echo123"))
    350                                 return;
     350                        return;
    351351                ptr = g_strdup_printf("%s@skype.com", user);
    352352                imcb_add_buddy(ic, ptr, skype_group_by_username(ic, user));
     
    10161016                }
    10171017        } else if (!strncmp(info, "MEMBERS ", 8) || !strncmp(info, "ACTIVEMEMBERS ", 14) ) {
    1018                 info += 8;
     1018                if (!strncmp(info, "MEMBERS ", 8))
     1019                        info += 8;
     1020                else
     1021                        info += 14;
    10191022                gc = bee_chat_by_title(ic->bee, ic, id);
    10201023                /* Hack! We set ->data to TRUE
     
    15641567
    15651568        s = set_add(&acc->set, "mood_text", NULL, skype_set_mood_text, acc);
    1566         s->flags |= ACC_SET_NOSAVE | ACC_SET_ONLINE_ONLY;
     1569        s->flags |= SET_NOSAVE | ACC_SET_ONLINE_ONLY;
    15671570
    15681571        s = set_add(&acc->set, "call", NULL, skype_set_call, acc);
  • protocols/skype/skyped.py

    r5cb9461 r1a2c1c0  
    273273                if options.log:
    274274                        sock = open(options.log, "a")
    275                         sock.write(prefix + ": " + sanitized)
     275                        sock.write("%s: %s\n" % (prefix, sanitized))
    276276                        sock.close()
    277277
  • protocols/skype/test.py

    r5cb9461 r1a2c1c0  
    113113                self.mock("groupchat-leave")
    114114       
     115        def testGroupchatMsg(self):
     116                self.mock("groupchat-msg")
     117       
     118        def testGroupchatTopic(self):
     119                self.mock("groupchat-topic")
     120       
    115121        def testCalledYes(self):
    116122                self.mock("called-yes")
     
    125131                self.mock("group-read")
    126132
     133        def testGroupAdd(self):
     134                self.mock("group-add")
     135
    127136        def testCtcpHelp(self):
    128137                self.mock("ctcp-help")
     
    130139        def testSetMoodText(self):
    131140                self.mock("set-mood-text")
     141       
     142        def testAwaySet(self):
     143                self.mock("away-set")
    132144
    133145if __name__ == '__main__':
  • protocols/twitter/twitter.c

    r5cb9461 r1a2c1c0  
    158158{
    159159        struct twitter_data *td = ic->proto_data;
     160        const char *url = set_getstr(&ic->acc->set, "base_url");
    160161
    161162        imcb_log(ic, "Requesting OAuth request token");
     163       
     164        if (!strstr(url, "twitter.com") && !strstr(url, "identi.ca"))
     165                imcb_log(ic, "Warning: OAuth only works with identi.ca and "
     166                             "Twitter.");
    162167
    163168        td->oauth_info = oauth_request_token(get_oauth_service(ic), twitter_oauth_callback, ic);
     
    178183        td = ic->proto_data;
    179184        if (info->stage == OAUTH_REQUEST_TOKEN) {
    180                 char name[strlen(ic->acc->user) + 9], *msg;
     185                char *name, *msg;
    181186
    182187                if (info->request_token == NULL) {
     
    186191                }
    187192
    188                 sprintf(name, "%s_%s", td->prefix, ic->acc->user);
     193                name = g_strdup_printf("%s_%s", td->prefix, ic->acc->user);
    189194                msg = g_strdup_printf("To finish OAuth authentication, please visit "
    190195                                      "%s and respond with the resulting PIN code.",
    191196                                      info->auth_url);
    192197                imcb_buddy_msg(ic, name, msg, 0, 0);
     198                g_free(name);
    193199                g_free(msg);
    194200        } else if (info->stage == OAUTH_ACCESS_TOKEN) {
     
    283289        char *def_url;
    284290        char *def_tul;
     291        char *def_mentions;
    285292
    286293        if (strcmp(acc->prpl->name, "twitter") == 0) {
    287294                def_url = TWITTER_API_URL;
    288295                def_tul = "20";
     296                def_mentions = "true";
    289297        } else {                /* if( strcmp( acc->prpl->name, "identica" ) == 0 ) */
    290298                def_url = IDENTICA_API_URL;
    291299                def_tul = "0";
     300                def_mentions = "false";
    292301        }
    293302
     
    302311        s->flags |= ACC_SET_OFFLINE_ONLY;
    303312
    304         s = set_add(&acc->set, "fetch_mentions", "true", set_eval_bool, acc);
     313        s = set_add(&acc->set, "fetch_mentions", def_mentions, set_eval_bool, acc);
    305314
    306315        s = set_add(&acc->set, "message_length", "140", set_eval_int, acc);
  • protocols/twitter/twitter_http.c

    r5cb9461 r1a2c1c0  
    7878       
    7979        // Make the request.
    80         g_string_printf(request, "%s %s%s%s%s HTTP/1.0\r\n"
     80        g_string_printf(request, "%s %s%s%s%s HTTP/1.1\r\n"
    8181                        "Host: %s\r\n"
    8282                        "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n",
  • protocols/twitter/twitter_lib.h

    r5cb9461 r1a2c1c0  
    2929#include "twitter_http.h"
    3030
    31 #define TWITTER_API_URL "http://api.twitter.com/1.1"
     31#define TWITTER_API_URL "https://api.twitter.com/1.1"
    3232#define IDENTICA_API_URL "https://identi.ca/api"
    3333
  • storage_xml.c

    r5cb9461 r1a2c1c0  
    174174        char *fn, buf[2048];
    175175        int fd, st;
    176         struct xt_parser *xp;
     176        struct xt_parser *xp = NULL;
    177177        struct xt_node *node;
    178178        storage_status_t ret = STORAGE_OTHER_ERROR;
Note: See TracChangeset for help on using the changeset viewer.