Ticket #53: 8bit-charset.diff
File 8bit-charset.diff, 24.6 KB (added by , at 2007-02-16T15:31:22Z) |
---|
-
.bzrignore
=== modified file '.bzrignore'
12 12 bitlbee.pc 13 13 .gdb_history 14 14 tests/check 15 description-pak 16 *.tgz 15 17 *.gcda 16 18 *.gcov 17 19 *.gcno -
Makefile
=== modified file 'Makefile'
42 42 $(MAKE) -C tests clean 43 43 44 44 distclean: clean $(subdirs) 45 $(MAKE) -C tests distclean 45 46 rm -f Makefile.settings config.h bitlbee.pc 46 47 find . -name 'DEADJOE' -o -name '*.orig' -o -name '*.rej' -o -name '*~' -exec rm -f {} \; 47 $(MAKE) -C test distclean48 48 49 49 check: all 50 50 $(MAKE) -C tests … … 110 110 endif 111 111 112 112 encode: 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) 114 114 115 115 decode: encode 116 116 cp encode decode -
account.c
=== modified file 'account.c'
49 49 a->irc = irc; 50 50 51 51 s = set_add( &a->set, "auto_connect", "true", set_eval_account, a ); 52 s->flags |= ACC_SET_NOSAVE;52 s->flags |= SET_NOSAVE; 53 53 54 54 s = set_add( &a->set, "auto_reconnect", "true", set_eval_bool, a ); 55 55 56 56 s = set_add( &a->set, "password", NULL, set_eval_account, a ); 57 s->flags |= ACC_SET_NOSAVE;57 s->flags |= SET_NOSAVE; 58 58 59 59 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; 61 61 set_setstr( &a->set, "username", user ); 62 62 63 63 a->nicks = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, g_free ); -
account.h
=== modified file 'account.h'
52 52 53 53 char *set_eval_account( set_t *set, char *value ); 54 54 55 #define ACC_SET_NOSAVE 156 55 #define ACC_SET_OFFLINE_ONLY 2 57 56 #define ACC_SET_ONLINE_ONLY 4 58 57 -
bitlbee.h
=== modified file 'bitlbee.h'
117 117 118 118 extern char *CONF_FILE; 119 119 120 #include "set.h" 120 121 #include "irc.h" 121 122 #include "storage.h" 122 #include "set.h"123 123 #include "nogaim.h" 124 124 #include "commands.h" 125 125 #include "account.h" -
configure
=== modified file 'configure'
140 140 fi 141 141 142 142 if [ "$debug" = "1" ]; then 143 echo 'CFLAGS=-g ' >> Makefile.settings143 echo 'CFLAGS=-g -Wall -Werror' >> Makefile.settings 144 144 echo 'DEBUG=1' >> Makefile.settings 145 145 echo '#define DEBUG' >> config.h 146 146 else -
doc/user-guide/commands.xml
=== modified file 'doc/user-guide/commands.xml'
620 620 </description> 621 621 </bitlbee-setting> 622 622 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 623 651 <bitlbee-setting name="web_aware" type="string" scope="account"> 624 652 <default>false</default> 625 653 -
log.c
=== modified file 'log.c'
26 26 #define BITLBEE_CORE 27 27 #include "bitlbee.h" 28 28 #include <syslog.h> 29 #include <assert.h> 29 30 30 31 static log_t logoutput; 31 32 … … 47 48 return; 48 49 } 49 50 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 */51 void log_link(loglvl_t level, logoutput_t output) { 52 log_somewhere_f log_func; 52 53 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; 62 60 } 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; 72 70 } 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 DEBUG84 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 #endif95 return;96 97 71 } 98 72 99 void log_message( int level, char *message, ... ) {73 void log_message(loglvl_t level, char *message, ... ) { 100 74 101 75 va_list ap; 102 76 char *msgstring; -
log.h
=== modified file 'log.h'
42 42 LOGOUTPUT_CONSOLE, 43 43 } logoutput_t; 44 44 45 typedef void (*log_somewhere_f)(int level, char *logmessage); 45 46 typedef 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; 49 50 #ifdef DEBUG 50 void (*debug)(int level, char *logmessage);51 log_somewhere_f debug; 51 52 #endif 52 53 } log_t; 53 54 54 55 void log_init(void); 55 void log_link( int level, int output);56 void log_message( int level, char *message, ...) G_GNUC_PRINTF( 2, 3 );56 void log_link(loglvl_t level, logoutput_t output); 57 void log_message(loglvl_t level, char *message, ...) G_GNUC_PRINTF( 2, 3 ); 57 58 void log_error(char *functionname); 58 59 59 60 #endif -
protocols/jabber/jabber.c
=== modified file 'protocols/jabber/jabber.c'
1506 1506 s->flags |= ACC_SET_OFFLINE_ONLY; 1507 1507 1508 1508 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; 1510 1510 1511 1511 s = set_add( &acc->set, "ssl", "false", set_eval_bool, acc ); 1512 1512 s->flags |= ACC_SET_OFFLINE_ONLY; -
protocols/msn/msn.c
=== modified file 'protocols/msn/msn.c'
33 33 set_t *s; 34 34 35 35 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; 37 37 } 38 38 39 39 static void msn_login( account_t *acc ) -
protocols/oscar/im.c
=== modified file 'protocols/oscar/im.c'
114 114 * made up of UNICODE duples. If you set 115 115 * this, you'd better be damn sure you know 116 116 * 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 * 120 121 * Generally, you should use the lowest encoding possible to send 121 122 * your message. If you only use basic punctuation and the generic 122 123 * Latin alphabet, use ASCII7 (no flags). If you happen to use non-ASCII7 … … 278 279 } else { 279 280 if (args->flags & AIM_IMFLAGS_UNICODE) 280 281 aimbs_put16(&fr->data, 0x0002); 281 else if (args->flags & AIM_IMFLAGS_ ISO_8859_1)282 else if (args->flags & AIM_IMFLAGS_LOCAL_8BIT) 282 283 aimbs_put16(&fr->data, 0x0003); 283 284 else 284 285 aimbs_put16(&fr->data, 0x0000); … … 1213 1214 else if (args->charset == 0x0002) 1214 1215 args->icbmflags |= AIM_IMFLAGS_UNICODE; 1215 1216 else if (args->charset == 0x0003) 1216 args->icbmflags |= AIM_IMFLAGS_ ISO_8859_1;1217 args->icbmflags |= AIM_IMFLAGS_LOCAL_8BIT; 1217 1218 else if (args->charset == 0xffff) 1218 1219 ; /* no encoding (yeep!) */ 1219 1220 … … 1677 1678 1678 1679 args.uin = aimbs_getle32(&meat); 1679 1680 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); 1681 1683 1682 1684 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 1683 1685 ret = userfunc(sess, rx, channel, userinfo, &args); -
protocols/oscar/im.h
=== modified file 'protocols/oscar/im.h'
19 19 #define AIM_IMFLAGS_AWAY 0x0001 /* mark as an autoreply */ 20 20 #define AIM_IMFLAGS_ACK 0x0002 /* request a receipt notice */ 21 21 #define AIM_IMFLAGS_UNICODE 0x0004 22 #define AIM_IMFLAGS_ ISO_8859_10x000822 #define AIM_IMFLAGS_LOCAL_8BIT 0x0008 23 23 #define AIM_IMFLAGS_BUDDYREQ 0x0010 /* buddy icon requested */ 24 24 #define AIM_IMFLAGS_HASICON 0x0020 /* already has icon */ 25 25 #define AIM_IMFLAGS_SUBENC_MACINTOSH 0x0040 /* damn that Steve Jobs! */ … … 180 180 guint32 uin; /* Of the sender of the ICBM */ 181 181 guint16 type; 182 182 char *msg; /* Reason for auth request, deny, or accept */ 183 size_t msglen; 183 184 }; 184 185 185 186 int aim_send_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args); -
protocols/oscar/oscar.c
=== modified file 'protocols/oscar/oscar.c'
360 360 set_t *s; 361 361 362 362 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 ); 364 367 365 368 if (isdigit(acc->user[0])) { 366 369 s = set_add( &acc->set, "web_aware", "false", set_eval_bool, acc ); … … 1057 1060 return 1; 1058 1061 } 1059 1062 1063 static 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 */ 1077 static 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 1060 1120 static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args) { 1061 1121 char *tmp = g_malloc(BUF_LONG + 1); 1062 1122 struct gaim_connection *gc = sess->aux_data; … … 1064 1124 1065 1125 if (args->icbmflags & AIM_IMFLAGS_AWAY) 1066 1126 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); 1098 1129 1099 1130 strip_linefeed(tmp); 1100 1131 serv_got_im(gc, userinfo->sn, tmp, flags, time(NULL), -1); … … 1192 1223 case 0x0001: { /* An almost-normal instant message. Mac ICQ sends this. It's peculiar. */ 1193 1224 char *uin, *message; 1194 1225 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); 1196 1228 strip_linefeed(message); 1197 1229 serv_got_im(gc, uin, message, 0, time(NULL), -1); 1198 1230 g_free(uin); … … 1787 1819 1788 1820 switch (msg->type) { 1789 1821 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); 1792 1825 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); 1797 1831 } break; 1798 1832 1799 1833 case 0x0004: { /* Someone sent you a URL */ … … 1873 1907 s = g_malloc(BUF_LONG); 1874 1908 /* Try if we can put it in an ISO8859-1 string first. 1875 1909 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; 1878 1912 len = ret; 1879 1913 } else if ((ret = do_iconv("UTF-8", "UNICODEBIG", message, s, len, BUF_LONG)) >= 0) { 1880 1914 args.flags |= AIM_IMFLAGS_UNICODE; … … 2377 2411 return ret; 2378 2412 } 2379 2413 2380 static char *oscar_encoding_to_utf8( char *encoding, char *text, int textlen)2414 static char *oscar_encoding_to_utf8(struct gaim_connection *gc, char *encoding, char *text, int textlen) 2381 2415 { 2382 2416 char *utf8 = g_new0(char, 8192); 2383 2417 2384 2418 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")); 2386 2421 } else if (!g_strcasecmp(encoding, "iso-8859-1")) { 2387 2422 do_iconv("iso-8859-1", "UTF-8", text, utf8, textlen, 8192); 2388 2423 } else if (!g_strcasecmp(encoding, "ISO-8859-1-Windows-3.1-Latin-1")) { … … 2390 2425 } else if (!g_strcasecmp(encoding, "unicode-2-0")) { 2391 2426 do_iconv("UCS-2BE", "UTF-8", text, utf8, textlen, 8192); 2392 2427 } 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); 2395 2430 do_iconv(encoding, "UTF-8", text, utf8, textlen, 8192); 2396 2431 } 2397 2432 … … 2442 2477 } 2443 2478 2444 2479 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); 2446 2481 serv_got_crap(gc, "%s\n%s", _("User Info"), utf8); 2447 2482 } else { 2448 2483 serv_got_crap(gc, _("No user info available.")); 2449 2484 } 2450 2485 } 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); 2452 2487 serv_got_crap(gc, "%s\n%s", _("Away Message"), utf8); 2453 2488 } 2454 2489 … … 2541 2576 /* Message contains high ASCII chars, time for some translation! */ 2542 2577 if (*s) { 2543 2578 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. 2545 2580 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) { 2547 2582 flags |= AIM_CHATFLAGS_ISO_8859_1; 2548 2583 len = ret; 2549 2584 } else if ((ret = do_iconv("UTF-8", "UNICODEBIG", message, s, len, BUF_LONG)) >= 0) { -
root_commands.c
=== modified file 'root_commands.c'
203 203 } 204 204 } 205 205 206 207 static void setting_dump( irc_t *irc, char *key, char *value ); 208 206 209 static void cmd_account( irc_t *irc, char **cmd ) 207 210 { 208 211 account_t *a; … … 407 410 if( set_name ) /* else 'forgotten' on purpose.. Must show new value after changing */ 408 411 { 409 412 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); 414 414 } 415 415 else 416 416 { 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); 425 421 } 426 422 } 427 423 … … 520 516 } 521 517 } 522 518 519 // heler for cmd_rename 520 static 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 523 534 static void cmd_rename( irc_t *irc, char **cmd ) 524 535 { 525 536 user_t *u; 526 537 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 ; 531 540 else if( user_find( irc, cmd[2] ) && ( nick_cmp( cmd[1], cmd[2] ) != 0 ) ) 532 541 { 533 542 irc_usermsg( irc, "Nick `%s' already exists", cmd[2] ); … … 535 544 else if( !nick_ok( cmd[2] ) ) 536 545 { 537 546 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] );542 547 } 543 548 else 544 549 { … … 737 742 query_answer( irc, q, 0 ); 738 743 } 739 744 745 // cmd_set and cmd_account(set) helper to remove code duplication 746 static 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 740 754 static void cmd_set( irc_t *irc, char **cmd ) 741 755 { 742 756 if( cmd[1] && cmd[2] ) … … 749 763 if( cmd[1] ) /* else 'forgotten' on purpose.. Must show new value after changing */ 750 764 { 751 765 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); 756 767 } 757 768 else 758 769 { 759 770 set_t *s = irc->set; 760 771 while( s ) 761 772 { 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); 766 775 s = s->next; 767 776 } 768 777 } -
set.h
=== modified file 'set.h'
23 23 Suite 330, Boston, MA 02111-1307 USA 24 24 */ 25 25 26 #ifndef _SET_H 27 #define _SET_H 28 26 29 /* This used to be specific to irc_t structures, but it's more generic now 27 30 (so it can also be used for account_t structs). It's pretty simple, but 28 31 so far pretty useful. … … 32 35 from setting invalid values, you can write an evaluator function for 33 36 every setting, which can check a new value and block it by returning 34 37 NULL, or replace it by returning a new value. See struct set.eval. */ 38 39 struct set; 35 40 36 41 typedef char *(*set_eval) ( struct set *set, char *value ); 37 42 … … 56 61 set_eval eval; 57 62 struct set *next; 58 63 } set_t; 64 65 #define SET_NOSAVE 1 59 66 60 67 /* Should be pretty clear. */ 61 68 set_t *set_add( set_t **head, char *key, char *def, set_eval eval, void *data ); … … 87 94 char *set_eval_to_char( set_t *set, char *value ); 88 95 char *set_eval_ops( set_t *set, char *value ); 89 96 char *set_eval_charset( set_t *set, char *value ); 97 98 #endif -
storage_xml.c
=== modified file 'storage_xml.c'
370 370 371 371 static gboolean xml_save_nick( gpointer key, gpointer value, gpointer data ); 372 372 373 static 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 373 383 static storage_status_t xml_save( irc_t *irc, int overwrite ) 374 384 { 375 385 char path[512], *path2, *pass_buf = NULL; 376 set_t *set;377 386 account_t *acc; 378 387 int fd; 379 388 md5_byte_t pass_md5[21]; … … 416 425 417 426 g_free( pass_buf ); 418 427 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; 423 430 424 431 for( acc = irc->accounts; acc; acc = acc->next ) 425 432 { … … 442 449 if( !xml_printf( fd, 0, ">\n" ) ) 443 450 goto write_error; 444 451 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; 449 454 450 455 /* This probably looks pretty strange. g_hash_table_foreach 451 456 is quite a PITA already (but it can't get much better in -
tests/Makefile
=== modified file 'tests/Makefile'
1 include ../Makefile.settings1 -include ../Makefile.settings 2 2 3 3 LFLAGS +=-lcheck 4 4 … … 7 7 8 8 clean: 9 9 rm -f check *.o 10 11 distclean: clean 10 12 11 13 main_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 12 14