Ticket #53: 8bit-charset.diff

File 8bit-charset.diff, 24.6 KB (added by darkk, 3 years ago)

patch for configurable encoding for icq accounts

  • .bzrignore

    === modified file '.bzrignore'
     
    1212bitlbee.pc 
    1313.gdb_history 
    1414tests/check 
     15description-pak 
     16*.tgz 
    1517*.gcda 
    1618*.gcov 
    1719*.gcno 
  • Makefile

    === modified file 'Makefile'
     
    4242        $(MAKE) -C tests clean 
    4343 
    4444distclean: clean $(subdirs) 
     45        $(MAKE) -C tests distclean 
    4546        rm -f Makefile.settings config.h bitlbee.pc 
    4647        find . -name 'DEADJOE' -o -name '*.orig' -o -name '*.rej' -o -name '*~' -exec rm -f {} \; 
    47         $(MAKE) -C test distclean 
    4848 
    4949check: all 
    5050        $(MAKE) -C tests 
     
    110110endif 
    111111 
    112112encode: crypting.c 
    113         $(CC) crypting.c protocols/md5.c $(CFLAGS) -o encode -DCRYPTING_MAIN $(CFLAGS) $(EFLAGS) $(LFLAGS) 
     113        $(CC) crypting.c lib/md5.c $(CFLAGS) -o encode -DCRYPTING_MAIN $(CFLAGS) $(EFLAGS) $(LFLAGS) 
    114114 
    115115decode: encode 
    116116        cp encode decode 
  • account.c

    === modified file 'account.c'
     
    4949        a->irc = irc; 
    5050         
    5151        s = set_add( &a->set, "auto_connect", "true", set_eval_account, a ); 
    52         s->flags |= ACC_SET_NOSAVE; 
     52        s->flags |= SET_NOSAVE; 
    5353         
    5454        s = set_add( &a->set, "auto_reconnect", "true", set_eval_bool, a ); 
    5555         
    5656        s = set_add( &a->set, "password", NULL, set_eval_account, a ); 
    57         s->flags |= ACC_SET_NOSAVE; 
     57        s->flags |= SET_NOSAVE; 
    5858         
    5959        s = set_add( &a->set, "username", NULL, set_eval_account, a ); 
    60         s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; 
     60        s->flags |= SET_NOSAVE | ACC_SET_OFFLINE_ONLY; 
    6161        set_setstr( &a->set, "username", user ); 
    6262         
    6363        a->nicks = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, g_free ); 
  • account.h

    === modified file 'account.h'
     
    5252 
    5353char *set_eval_account( set_t *set, char *value ); 
    5454 
    55 #define ACC_SET_NOSAVE          1 
    5655#define ACC_SET_OFFLINE_ONLY    2 
    5756#define ACC_SET_ONLINE_ONLY     4 
    5857 
  • bitlbee.h

    === modified file 'bitlbee.h'
     
    117117 
    118118extern char *CONF_FILE; 
    119119 
     120#include "set.h" 
    120121#include "irc.h" 
    121122#include "storage.h" 
    122 #include "set.h" 
    123123#include "nogaim.h" 
    124124#include "commands.h" 
    125125#include "account.h" 
  • configure

    === modified file 'configure'
     
    140140fi 
    141141 
    142142if [ "$debug" = "1" ]; then 
    143         echo 'CFLAGS=-g' >> Makefile.settings 
     143        echo 'CFLAGS=-g -Wall -Werror' >> Makefile.settings 
    144144        echo 'DEBUG=1' >> Makefile.settings 
    145145        echo '#define DEBUG' >> config.h 
    146146else 
  • doc/user-guide/commands.xml

    === modified file 'doc/user-guide/commands.xml'
     
    620620                </description> 
    621621        </bitlbee-setting> 
    622622 
     623        <bitlbee-setting name="8bit_charset_out" type="string" scope="account"> 
     624                <default>iso8859-1</default> 
     625                <possible-values>you can get a list of all possible values by doing 'iconv -l' in a shell</possible-values> 
     626                <description> 
     627                        <para> 
     628                                If you want to behave like buggy ICQ client and send 8bit messages in some 8bit encoding and not in unicode, than you can modify this variable. 
     629                        </para> 
     630 
     631                        <para> 
     632                                BUT DON'T TOUCH THIS VARIABLE UNLESS YOU'RE SURE WHAT YOU'RE DOING. You've been wanred. 
     633                        </para> 
     634                </description> 
     635        </bitlbee-setting> 
     636 
     637        <bitlbee-setting name="8bit_charset_in" type="string" scope="account"> 
     638                <default>iso8859-1</default> 
     639                <possible-values>you can get a list of all possible values by doing 'iconv -l' in a shell</possible-values> 
     640                <description> 
     641                        <para> 
     642                                Some ICQ clients send 8-bit messages in local 8-bit encoding (e.g. cp1251 for Russia) and not in unicode, but they mark the message as 8-bit, so we have to recode it properly. 
     643                        </para> 
     644 
     645                        <para> 
     646                                If you don't know what's the best value for this, at least iso8859-1 is the best choice for most Western countries. That's default one and that is usually used in ICQ protocol. 
     647                        </para> 
     648                </description> 
     649        </bitlbee-setting> 
     650 
    623651        <bitlbee-setting name="web_aware" type="string" scope="account"> 
    624652                <default>false</default> 
    625653 
  • log.c

    === modified file 'log.c'
     
    2626#define BITLBEE_CORE 
    2727#include "bitlbee.h" 
    2828#include <syslog.h> 
     29#include <assert.h> 
    2930 
    3031static log_t logoutput; 
    3132 
     
    4748        return; 
    4849} 
    4950 
    50 void log_link(int level, int output) { 
    51         /* I know it's ugly, but it works and I didn't feel like messing with pointer to function pointers */ 
     51void log_link(loglvl_t level, logoutput_t output) { 
     52        log_somewhere_f log_func; 
    5253 
    53         if(level == LOGLVL_INFO) { 
    54                 if(output == LOGOUTPUT_NULL) 
    55                         logoutput.informational = &log_null;     
    56                 else if(output == LOGOUTPUT_IRC) 
    57                         logoutput.informational = &log_irc;      
    58                 else if(output == LOGOUTPUT_SYSLOG) 
    59                         logoutput.informational = &log_syslog;   
    60                 else if(output == LOGOUTPUT_CONSOLE)  
    61                         logoutput.informational = &log_console;  
     54        switch (output) { 
     55                case LOGOUTPUT_NULL:    log_func = log_null;    break; 
     56                case LOGOUTPUT_IRC:     log_func = log_irc;     break; 
     57                case LOGOUTPUT_SYSLOG:  log_func = log_syslog;  break; 
     58                case LOGOUTPUT_CONSOLE: log_func = log_console; break; 
     59                default: assert(0 == 1); return; 
    6260        } 
    63         else if(level == LOGLVL_WARNING) { 
    64                 if(output == LOGOUTPUT_NULL) 
    65                         logoutput.warning = &log_null; 
    66                 else if(output == LOGOUTPUT_IRC) 
    67                         logoutput.warning = &log_irc; 
    68                 else if(output == LOGOUTPUT_SYSLOG) 
    69                         logoutput.warning = &log_syslog; 
    70                 else if(output == LOGOUTPUT_CONSOLE) 
    71                         logoutput.warning = &log_console; 
     61 
     62        switch (level) { 
     63                case LOGLVL_INFO:    logoutput.informational = log_func; break; 
     64                case LOGLVL_WARNING: logoutput.warning       = log_func; break; 
     65                case LOGLVL_ERROR:   logoutput.error         = log_func; break; 
     66#ifdef DEBUG 
     67                case LOGLVL_DEBUG:   logoutput.debug         = log_func; break; 
     68#endif 
     69                default: assert(0 == 1); return; 
    7270        } 
    73         else if(level == LOGLVL_ERROR) { 
    74                 if(output == LOGOUTPUT_NULL) 
    75                         logoutput.error = &log_null; 
    76                 else if(output == LOGOUTPUT_IRC) 
    77                         logoutput.error = &log_irc; 
    78                 else if(output == LOGOUTPUT_SYSLOG) 
    79                         logoutput.error = &log_syslog; 
    80                 else if(output == LOGOUTPUT_CONSOLE) 
    81                         logoutput.error = &log_console; 
    82         } 
    83 #ifdef DEBUG 
    84         else if(level == LOGLVL_DEBUG) { 
    85                 if(output == LOGOUTPUT_NULL) 
    86                         logoutput.debug = &log_null; 
    87                 else if(output == LOGOUTPUT_IRC) 
    88                         logoutput.debug = &log_irc; 
    89                 else if(output == LOGOUTPUT_SYSLOG) 
    90                         logoutput.debug = &log_syslog; 
    91                 else if(output == LOGOUTPUT_CONSOLE) 
    92                         logoutput.debug = &log_console; 
    93         } 
    94 #endif 
    95         return;  
    96  
    9771} 
    9872 
    99 void log_message(int level, char *message, ... ) { 
     73void log_message(loglvl_t level, char *message, ... ) { 
    10074 
    10175        va_list ap; 
    10276        char *msgstring; 
  • log.h

    === modified file 'log.h'
     
    4242        LOGOUTPUT_CONSOLE, 
    4343} logoutput_t; 
    4444 
     45typedef void (*log_somewhere_f)(int level, char *logmessage); 
    4546typedef struct log_t { 
    46         void (*error)(int level, char *logmessage); 
    47         void (*warning)(int level, char *logmessage);  
    48         void (*informational)(int level, char *logmessage); 
     47        log_somewhere_f error; 
     48        log_somewhere_f warning; 
     49        log_somewhere_f informational; 
    4950#ifdef DEBUG 
    50         void (*debug)(int level, char *logmessage); 
     51        log_somewhere_f debug; 
    5152#endif 
    5253} log_t; 
    5354 
    5455void log_init(void); 
    55 void log_link(int level, int output); 
    56 void log_message(int level, char *message, ...) G_GNUC_PRINTF( 2, 3 ); 
     56void log_link(loglvl_t level, logoutput_t output); 
     57void log_message(loglvl_t level, char *message, ...) G_GNUC_PRINTF( 2, 3 ); 
    5758void log_error(char *functionname); 
    5859 
    5960#endif 
  • protocols/jabber/jabber.c

    === modified file 'protocols/jabber/jabber.c'
     
    15061506        s->flags |= ACC_SET_OFFLINE_ONLY; 
    15071507         
    15081508        s = set_add( &acc->set, "server", NULL, set_eval_account, acc ); 
    1509         s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; 
     1509        s->flags |= SET_NOSAVE | ACC_SET_OFFLINE_ONLY; 
    15101510         
    15111511        s = set_add( &acc->set, "ssl", "false", set_eval_bool, acc ); 
    15121512        s->flags |= ACC_SET_OFFLINE_ONLY; 
  • protocols/msn/msn.c

    === modified file 'protocols/msn/msn.c'
     
    3333        set_t *s; 
    3434         
    3535        s = set_add( &acc->set, "display_name", NULL, msn_set_display_name, acc ); 
    36         s->flags |= ACC_SET_NOSAVE | ACC_SET_ONLINE_ONLY; 
     36        s->flags |= SET_NOSAVE | ACC_SET_ONLINE_ONLY; 
    3737} 
    3838 
    3939static void msn_login( account_t *acc ) 
  • protocols/oscar/im.c

    === modified file 'protocols/oscar/im.c'
     
    114114 *                        made up of UNICODE duples.  If you set 
    115115 *                        this, you'd better be damn sure you know 
    116116 *                        what you're doing. 
    117  *   AIM_IMFLAGS_ISO_8859_1 -- The message contains the ASCII8 subset 
    118  *                        known as ISO-8859-1.   
    119  * 
     117 *   AIM_IMFLAGS_LOCAL_8BIT -- The message contains some 8bit (it was 
     118 *                             _ISO_8859_1 before, but we have to support 
     119 *                             other 8bit encodings) 
     120 *  
    120121 * Generally, you should use the lowest encoding possible to send 
    121122 * your message.  If you only use basic punctuation and the generic 
    122123 * Latin alphabet, use ASCII7 (no flags).  If you happen to use non-ASCII7 
     
    278279                } else { 
    279280                        if (args->flags & AIM_IMFLAGS_UNICODE) 
    280281                                aimbs_put16(&fr->data, 0x0002); 
    281                         else if (args->flags & AIM_IMFLAGS_ISO_8859_1) 
     282                        else if (args->flags & AIM_IMFLAGS_LOCAL_8BIT) 
    282283                                aimbs_put16(&fr->data, 0x0003); 
    283284                        else 
    284285                                aimbs_put16(&fr->data, 0x0000); 
     
    12131214                        else if (args->charset == 0x0002) 
    12141215                                args->icbmflags |= AIM_IMFLAGS_UNICODE; 
    12151216                        else if (args->charset == 0x0003) 
    1216                                 args->icbmflags |= AIM_IMFLAGS_ISO_8859_1; 
     1217                                args->icbmflags |= AIM_IMFLAGS_LOCAL_8BIT; 
    12171218                        else if (args->charset == 0xffff) 
    12181219                                ; /* no encoding (yeep!) */ 
    12191220 
     
    16771678 
    16781679        args.uin = aimbs_getle32(&meat); 
    16791680        args.type = aimbs_getle16(&meat); 
    1680         args.msg = (char *)aimbs_getraw(&meat, aimbs_getle16(&meat)); 
     1681        args.msglen = aimbs_getle16(&meat); 
     1682        args.msg = (char *)aimbs_getraw(&meat, args.msglen); 
    16811683 
    16821684        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 
    16831685                ret = userfunc(sess, rx, channel, userinfo, &args); 
  • protocols/oscar/im.h

    === modified file 'protocols/oscar/im.h'
     
    1919#define AIM_IMFLAGS_AWAY                0x0001 /* mark as an autoreply */ 
    2020#define AIM_IMFLAGS_ACK                 0x0002 /* request a receipt notice */ 
    2121#define AIM_IMFLAGS_UNICODE             0x0004 
    22 #define AIM_IMFLAGS_ISO_8859_1          0x0008 
     22#define AIM_IMFLAGS_LOCAL_8BIT          0x0008 
    2323#define AIM_IMFLAGS_BUDDYREQ            0x0010 /* buddy icon requested */ 
    2424#define AIM_IMFLAGS_HASICON             0x0020 /* already has icon */ 
    2525#define AIM_IMFLAGS_SUBENC_MACINTOSH    0x0040 /* damn that Steve Jobs! */ 
     
    180180        guint32 uin; /* Of the sender of the ICBM */ 
    181181        guint16 type; 
    182182        char *msg; /* Reason for auth request, deny, or accept */ 
     183        size_t msglen; 
    183184}; 
    184185 
    185186int aim_send_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args); 
  • protocols/oscar/oscar.c

    === modified file 'protocols/oscar/oscar.c'
     
    360360        set_t *s; 
    361361         
    362362        s = set_add( &acc->set, "server", NULL, set_eval_account, acc ); 
    363         s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; 
     363        s->flags |= SET_NOSAVE | ACC_SET_OFFLINE_ONLY; 
     364 
     365        s = set_add( &acc->set, "8bit_charset_in", "ISO8859-1", set_eval_charset, acc ); 
     366        s = set_add( &acc->set, "8bit_charset_out", "ISO8859-1", set_eval_charset, acc ); 
    364367         
    365368        if (isdigit(acc->user[0])) { 
    366369                s = set_add( &acc->set, "web_aware", "false", set_eval_bool, acc ); 
     
    10571060        return 1; 
    10581061} 
    10591062 
     1063static int is_8bit(char *buf, size_t buflen) { 
     1064        int i; 
     1065        for (i = 0; i < buflen; i++) { 
     1066                if (buf[i] & 0x80) 
     1067                        return 1; 
     1068        } 
     1069        return 0; 
     1070} 
     1071 
     1072/** icbmflags: 
     1073 * AIM_IMFLAGS_UNICODE      msg should be in UNICODEBIG 
     1074 * AIM_IMFLAGS_LOCAL_8BIT   msg should be in "8bit_charset_in" 
     1075 * other flags are ignored 
     1076 */ 
     1077static void decode_incomingim(struct gaim_connection *gc, char *handle, char *msg, size_t msglen, guint32 icbmflags, char *out, size_t outlen) 
     1078{ 
     1079        char msg_is_8bit = is_8bit(msg, msglen); 
     1080 
     1081        if ( msg_is_8bit && !(icbmflags & (AIM_IMFLAGS_UNICODE | AIM_IMFLAGS_LOCAL_8BIT)) ) 
     1082                if (set_getbool(&gc->irc->set, "debug")) 
     1083                        serv_got_crap(gc, _("DEBUG: (%s): 8bit ascii message declared as 7bit one came..."), handle); 
     1084         
     1085        if ( (icbmflags & AIM_IMFLAGS_UNICODE) || msg_is_8bit ) { 
     1086                char *src; 
     1087                 
     1088                if (icbmflags & AIM_IMFLAGS_UNICODE) 
     1089                        src = "UNICODEBIG"; // should we check for utf8 ? 
     1090                else  
     1091                        src = set_getstr(&gc->acc->set, "8bit_charset_in"); 
     1092                 
     1093                /* Try to use iconv first to convert the message to UTF8 - which is what BitlBee expects */ 
     1094                if (do_iconv(src, "UTF-8", msg, out, msglen, outlen) >= 0) { 
     1095                        // Successfully converted! 
     1096                } else if (icbmflags & AIM_IMFLAGS_UNICODE) { 
     1097                        int i; 
     1098                         
     1099                        for (i = 0, out[0] = '\0'; i < msglen; i += 2) { 
     1100                                unsigned short uni; 
     1101                                 
     1102                                uni = ((msg[i] & 0xff) << 8) | (msg[i+1] & 0xff); 
     1103         
     1104                                if ( uni < 128 ) { /* ASCII */ 
     1105                                        g_snprintf(out+strlen(out), outlen-strlen(out), "%c", uni); 
     1106                                } else { /* something else, do UNICODE entity */ 
     1107                                        g_snprintf(out+strlen(out), outlen-strlen(out), "&#%04x;", uni); 
     1108                                } 
     1109                        } 
     1110                } else { 
     1111                        if (set_getbool(&gc->irc->set, "debug")) 
     1112                                serv_got_crap(gc, _("DEBUG: (%s): Can't convert from %s to UTF-8, sending as-is"), handle, src); 
     1113                        g_snprintf(out, outlen, "%s", msg); 
     1114                } 
     1115        } else { 
     1116                g_snprintf(out, outlen, "%s", msg); 
     1117        } 
     1118} 
     1119 
    10601120static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args) { 
    10611121        char *tmp = g_malloc(BUF_LONG + 1); 
    10621122        struct gaim_connection *gc = sess->aux_data; 
     
    10641124         
    10651125        if (args->icbmflags & AIM_IMFLAGS_AWAY) 
    10661126                flags |= IM_FLAG_AWAY; 
    1067          
    1068         if ((args->icbmflags & AIM_IMFLAGS_UNICODE) || (args->icbmflags & AIM_IMFLAGS_ISO_8859_1)) { 
    1069                 char *src; 
    1070                  
    1071                 if (args->icbmflags & AIM_IMFLAGS_UNICODE) 
    1072                         src = "UNICODEBIG"; 
    1073                 else 
    1074                         src = "ISO8859-1"; 
    1075                  
    1076                 /* Try to use iconv first to convert the message to UTF8 - which is what BitlBee expects */ 
    1077                 if (do_iconv(src, "UTF-8", args->msg, tmp, args->msglen, BUF_LONG) >= 0) { 
    1078                         // Successfully converted! 
    1079                 } else if (args->icbmflags & AIM_IMFLAGS_UNICODE) { 
    1080                         int i; 
    1081                          
    1082                         for (i = 0, tmp[0] = '\0'; i < args->msglen; i += 2) { 
    1083                                 unsigned short uni; 
    1084                                  
    1085                                 uni = ((args->msg[i] & 0xff) << 8) | (args->msg[i+1] & 0xff); 
    1086          
    1087                                 if ((uni < 128) || ((uni >= 160) && (uni <= 255))) { /* ISO 8859-1 */ 
    1088                                         g_snprintf(tmp+strlen(tmp), BUF_LONG-strlen(tmp), "%c", uni); 
    1089                                 } else { /* something else, do UNICODE entity */ 
    1090                                         g_snprintf(tmp+strlen(tmp), BUF_LONG-strlen(tmp), "&#%04x;", uni); 
    1091                                 } 
    1092                         } 
    1093                 } else { 
    1094                         g_snprintf(tmp, BUF_LONG, "%s", args->msg); 
    1095                 } 
    1096         } else 
    1097                 g_snprintf(tmp, BUF_LONG, "%s", args->msg); 
     1127 
     1128        decode_incomingim(gc, userinfo->sn, args->msg, args->msglen, args->icbmflags, tmp, BUF_LONG); 
    10981129         
    10991130        strip_linefeed(tmp); 
    11001131        serv_got_im(gc, userinfo->sn, tmp, flags, time(NULL), -1); 
     
    11921223                case 0x0001: { /* An almost-normal instant message.  Mac ICQ sends this.  It's peculiar. */ 
    11931224                        char *uin, *message; 
    11941225                        uin = g_strdup_printf("%u", args->uin); 
    1195                         message = g_strdup(args->msg); 
     1226                        message = g_malloc(BUF_LONG + 1); 
     1227                        decode_incomingim(gc, uin, args->msg, args->msglen, 0, message, BUF_LONG); 
    11961228                        strip_linefeed(message); 
    11971229                        serv_got_im(gc, uin, message, 0, time(NULL), -1); 
    11981230                        g_free(uin); 
     
    17871819 
    17881820        switch (msg->type) { 
    17891821                case 0x0001: { /* Basic offline message */ 
    1790                         char sender[32]; 
    1791                         char *dialog_msg = g_strdup(msg->msg); 
     1822                        char *uin = g_strdup_printf("%u", msg->sender); 
     1823                        char *message = g_malloc(BUF_LONG + 1); 
     1824                        int msglen = strlen(msg->msg); 
    17921825                        time_t t = get_time(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0); 
    1793                         g_snprintf(sender, sizeof(sender), "%u", msg->sender); 
    1794                         strip_linefeed(dialog_msg); 
    1795                         serv_got_im(gc, sender, dialog_msg, 0, t, -1); 
    1796                         g_free(dialog_msg); 
     1826                        decode_incomingim(gc, uin, msg->msg, msglen, 0, message, BUF_LONG); 
     1827                        strip_linefeed(message); 
     1828                        serv_got_im(gc, uin, message, 0, t, -1); 
     1829                        g_free(message); 
     1830                        g_free(uin); 
    17971831                } break; 
    17981832 
    17991833                case 0x0004: { /* Someone sent you a URL */ 
     
    18731907                        s = g_malloc(BUF_LONG); 
    18741908                        /* Try if we can put it in an ISO8859-1 string first. 
    18751909                           If we can't, fall back to UTF16. */ 
    1876                         if ((ret = do_iconv("UTF-8", "ISO8859-1", message, s, len, BUF_LONG)) >= 0) { 
    1877                                 args.flags |= AIM_IMFLAGS_ISO_8859_1; 
     1910                        if ((ret = do_iconv("UTF-8", set_getstr(&gc->acc->set, "8bit_charset_out"), message, s, len, BUF_LONG)) >= 0) { 
     1911                                args.flags |= AIM_IMFLAGS_LOCAL_8BIT; 
    18781912                                len = ret; 
    18791913                        } else if ((ret = do_iconv("UTF-8", "UNICODEBIG", message, s, len, BUF_LONG)) >= 0) { 
    18801914                                args.flags |= AIM_IMFLAGS_UNICODE; 
     
    23772411        return ret; 
    23782412} 
    23792413 
    2380 static char *oscar_encoding_to_utf8(char *encoding, char *text, int textlen) 
     2414static char *oscar_encoding_to_utf8(struct gaim_connection *gc, char *encoding, char *text, int textlen) 
    23812415{ 
    23822416        char *utf8 = g_new0(char, 8192); 
    23832417 
    23842418        if ((encoding == NULL) || encoding[0] == '\0') { 
    2385                 /*              gaim_debug_info("oscar", "Empty encoding, assuming UTF-8\n");*/ 
     2419                if (set_getbool(&gc->irc->set, "debug")) 
     2420                        serv_got_crap(gc, _("DEBUG: Empty encoding, assuming UTF-8")); 
    23862421        } else if (!g_strcasecmp(encoding, "iso-8859-1")) { 
    23872422                do_iconv("iso-8859-1", "UTF-8", text, utf8, textlen, 8192); 
    23882423        } else if (!g_strcasecmp(encoding, "ISO-8859-1-Windows-3.1-Latin-1")) { 
     
    23902425        } else if (!g_strcasecmp(encoding, "unicode-2-0")) { 
    23912426                do_iconv("UCS-2BE", "UTF-8", text, utf8, textlen, 8192); 
    23922427        } else if (g_strcasecmp(encoding, "us-ascii") && strcmp(encoding, "utf-8")) { 
    2393                 /*              gaim_debug_warning("oscar", "Unrecognized character encoding \"%s\", " 
    2394                   "attempting to convert to UTF-8 anyway\n", encoding);*/ 
     2428                if (set_getbool(&gc->irc->set, "debug")) 
     2429                        serv_got_crap(gc, _("DEBUG: Unrecognized character encoding \"%s\", attempting to convert to UTF-8 anyway"), encoding); 
    23952430                do_iconv(encoding, "UTF-8", text, utf8, textlen, 8192); 
    23962431        } 
    23972432 
     
    24422477                } 
    24432478                 
    24442479                if(text) { 
    2445                         utf8 = oscar_encoding_to_utf8(extracted_encoding, text, text_length); 
     2480                        utf8 = oscar_encoding_to_utf8(gc, extracted_encoding, text, text_length); 
    24462481                        serv_got_crap(gc, "%s\n%s", _("User Info"), utf8); 
    24472482                } else { 
    24482483                        serv_got_crap(gc, _("No user info available.")); 
    24492484                } 
    24502485        } else if(infotype == AIM_GETINFO_AWAYMESSAGE && userinfo->flags & AIM_FLAG_AWAY) { 
    2451                 utf8 = oscar_encoding_to_utf8(extracted_encoding, text, text_length); 
     2486                utf8 = oscar_encoding_to_utf8(gc, extracted_encoding, text, text_length); 
    24522487                serv_got_crap(gc, "%s\n%s", _("Away Message"), utf8); 
    24532488        } 
    24542489 
     
    25412576        /* Message contains high ASCII chars, time for some translation! */ 
    25422577        if (*s) { 
    25432578                s = g_malloc(BUF_LONG); 
    2544                 /* Try if we can put it in an ISO8859-1 string first. 
     2579                /* Try if we can put it in an ISO8859-1 (or something that overrides it) string first. 
    25452580                   If we can't, fall back to UTF16. */ 
    2546                 if ((ret = do_iconv("UTF-8", "ISO8859-1", message, s, len, BUF_LONG)) >= 0) { 
     2581                if ((ret = do_iconv("UTF-8", set_getstr(&gc->acc->set, "8bit_charset_out"), message, s, len, BUF_LONG)) >= 0) { 
    25472582                        flags |= AIM_CHATFLAGS_ISO_8859_1; 
    25482583                        len = ret; 
    25492584                } else if ((ret = do_iconv("UTF-8", "UNICODEBIG", message, s, len, BUF_LONG)) >= 0) { 
  • root_commands.c

    === modified file 'root_commands.c'
     
    203203        } 
    204204} 
    205205 
     206 
     207static void setting_dump( irc_t *irc, char *key, char *value ); 
     208 
    206209static void cmd_account( irc_t *irc, char **cmd ) 
    207210{ 
    208211        account_t *a; 
     
    407410                if( set_name ) /* else 'forgotten' on purpose.. Must show new value after changing */ 
    408411                { 
    409412                        char *s = set_getstr( &a->set, set_name ); 
    410                         if( s ) 
    411                                 irc_usermsg( irc, "%s = `%s'", set_name, s ); 
    412                         else 
    413                                 irc_usermsg( irc, "%s is empty", set_name ); 
     413                        setting_dump(irc, set_name, s); 
    414414                } 
    415415                else 
    416416                { 
    417                         set_t *s = a->set; 
    418                         while( s ) 
    419                         { 
    420                                 if( s->value || s->def ) 
    421                                         irc_usermsg( irc, "%s = `%s'", s->key, s->value?s->value:s->def ); 
    422                                 else 
    423                                         irc_usermsg( irc, "%s is empty", s->key ); 
    424                                 s = s->next; 
     417                        set_t *set = a->set; 
     418                        for (set = a->set; set; set = set->next) { 
     419                                char *value = set->value ? set->value : set->def; 
     420                                setting_dump(irc, set->key, value); 
    425421                        } 
    426422                } 
    427423                 
     
    520516        } 
    521517} 
    522518 
     519// heler for cmd_rename 
     520static user_t* get_mutable_user( irc_t *irc, char *nick ) 
     521{ 
     522        user_t *u = NULL; 
     523        if( g_strcasecmp( nick, irc->nick ) == 0 ) 
     524        { 
     525                irc_usermsg( irc, "Nick `%s' can't be changed", nick ); 
     526        } 
     527        else if( !( u = user_find( irc, nick ) ) ) 
     528        { 
     529                irc_usermsg( irc, "Nick `%s' does not exist", nick ); 
     530        } 
     531        return u; 
     532} 
     533 
    523534static void cmd_rename( irc_t *irc, char **cmd ) 
    524535{ 
    525536        user_t *u; 
    526537         
    527         if( g_strcasecmp( cmd[1], irc->nick ) == 0 ) 
    528         { 
    529                 irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] ); 
    530         } 
     538        if( !( u = get_mutable_user(irc, cmd[1]) )) 
     539                ; 
    531540        else if( user_find( irc, cmd[2] ) && ( nick_cmp( cmd[1], cmd[2] ) != 0 ) ) 
    532541        { 
    533542                irc_usermsg( irc, "Nick `%s' already exists", cmd[2] ); 
     
    535544        else if( !nick_ok( cmd[2] ) ) 
    536545        { 
    537546                irc_usermsg( irc, "Nick `%s' is invalid", cmd[2] ); 
    538         } 
    539         else if( !( u = user_find( irc, cmd[1] ) ) ) 
    540         { 
    541                 irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); 
    542547        } 
    543548        else 
    544549        { 
     
    737742                query_answer( irc, q, 0 ); 
    738743} 
    739744 
     745// cmd_set and cmd_account(set) helper to remove code duplication 
     746static void setting_dump( irc_t *irc, char *key, char *value ) 
     747{ 
     748        if( value ) 
     749                irc_usermsg( irc, "%s = `%s'", key, value ); 
     750        else 
     751                irc_usermsg( irc, "%s is empty", key ); 
     752} 
     753 
    740754static void cmd_set( irc_t *irc, char **cmd ) 
    741755{ 
    742756        if( cmd[1] && cmd[2] ) 
     
    749763        if( cmd[1] ) /* else 'forgotten' on purpose.. Must show new value after changing */ 
    750764        { 
    751765                char *s = set_getstr( &irc->set, cmd[1] ); 
    752                 if( s ) 
    753                         irc_usermsg( irc, "%s = `%s'", cmd[1], s ); 
    754                 else 
    755                         irc_usermsg( irc, "%s is empty", cmd[1] ); 
     766                setting_dump(irc, cmd[1], s); 
    756767        } 
    757768        else 
    758769        { 
    759770                set_t *s = irc->set; 
    760771                while( s ) 
    761772                { 
    762                         if( s->value || s->def ) 
    763                                 irc_usermsg( irc, "%s = `%s'", s->key, s->value?s->value:s->def ); 
    764                         else 
    765                                 irc_usermsg( irc, "%s is empty", s->key ); 
     773                        char *value = s->value ? s->value : s->def; 
     774                        setting_dump(irc, s->key, value); 
    766775                        s = s->next; 
    767776                } 
    768777        } 
  • set.h

    === modified file 'set.h'
     
    2323  Suite 330, Boston, MA  02111-1307  USA 
    2424*/ 
    2525 
     26#ifndef _SET_H 
     27#define _SET_H 
     28 
    2629/* This used to be specific to irc_t structures, but it's more generic now 
    2730   (so it can also be used for account_t structs). It's pretty simple, but 
    2831   so far pretty useful. 
     
    3235   from setting invalid values, you can write an evaluator function for 
    3336   every setting, which can check a new value and block it by returning 
    3437   NULL, or replace it by returning a new value. See struct set.eval. */ 
     38 
     39struct set; 
    3540 
    3641typedef char *(*set_eval) ( struct set *set, char *value ); 
    3742 
     
    5661        set_eval eval; 
    5762        struct set *next; 
    5863} set_t; 
     64 
     65#define SET_NOSAVE              1 
    5966 
    6067/* Should be pretty clear. */ 
    6168set_t *set_add( set_t **head, char *key, char *def, set_eval eval, void *data ); 
     
    8794char *set_eval_to_char( set_t *set, char *value ); 
    8895char *set_eval_ops( set_t *set, char *value ); 
    8996char *set_eval_charset( set_t *set, char *value ); 
     97 
     98#endif 
  • storage_xml.c

    === modified file 'storage_xml.c'
     
    370370 
    371371static gboolean xml_save_nick( gpointer key, gpointer value, gpointer data ); 
    372372 
     373static int settings_save(int fd, int ident, set_t* set_start) 
     374{ 
     375        set_t *set; 
     376        for( set = set_start; set; set = set->next ) 
     377                if( set->value && !(set->flags & SET_NOSAVE) ) // I see no good reason to test for ``set->def`` 
     378                        if( !xml_printf( fd, ident, "<setting name=\"%s\">%s</setting>\n", set->key, set->value ) ) 
     379                                return -1; 
     380        return 0; 
     381} 
     382 
    373383static storage_status_t xml_save( irc_t *irc, int overwrite ) 
    374384{ 
    375385        char path[512], *path2, *pass_buf = NULL; 
    376         set_t *set; 
    377386        account_t *acc; 
    378387        int fd; 
    379388        md5_byte_t pass_md5[21]; 
     
    416425         
    417426        g_free( pass_buf ); 
    418427         
    419         for( set = irc->set; set; set = set->next ) 
    420                 if( set->value && set->def ) 
    421                         if( !xml_printf( fd, 1, "<setting name=\"%s\">%s</setting>\n", set->key, set->value ) ) 
    422                                 goto write_error; 
     428        if ( settings_save(fd, 1, irc->set) < 0) 
     429                goto write_error; 
    423430         
    424431        for( acc = irc->accounts; acc; acc = acc->next ) 
    425432        { 
     
    442449                if( !xml_printf( fd, 0, ">\n" ) ) 
    443450                        goto write_error; 
    444451                 
    445                 for( set = acc->set; set; set = set->next ) 
    446                         if( set->value && set->def && !( set->flags & ACC_SET_NOSAVE ) ) 
    447                                 if( !xml_printf( fd, 2, "<setting name=\"%s\">%s</setting>\n", set->key, set->value ) ) 
    448                                         goto write_error; 
     452                if ( settings_save(fd, 2, acc->set) < 0) 
     453                        goto write_error; 
    449454                 
    450455                /* This probably looks pretty strange. g_hash_table_foreach 
    451456                   is quite a PITA already (but it can't get much better in 
  • tests/Makefile

    === modified file 'tests/Makefile'
     
    1 include ../Makefile.settings 
     1-include ../Makefile.settings 
    22 
    33LFLAGS +=-lcheck 
    44 
     
    77 
    88clean: 
    99        rm -f check *.o 
     10 
     11distclean: clean 
    1012 
    1113main_objs = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o storage_text.o user.o  
    1214