Ticket #53: 8bit-charset.diff

File 8bit-charset.diff, 24.6 KB (added by darkk, at 2007-02-16T15:31:22Z)

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