Mercurial > pidgin
comparison src/protocols/qq/utils.c @ 14021:ef8490f9e823
[gaim-migrate @ 16618]
Replaced all C++-style comments with C-style ones.
Cleaned up some comments and implemented a more consistent formatting scheme.
committer: Tailor Script <tailor@pidgin.im>
| author | Mark Huetsch <markhuetsch> |
|---|---|
| date | Wed, 02 Aug 2006 15:35:36 +0000 |
| parents | 39d6d4128599 |
| children | 8294485b79db |
comparison
equal
deleted
inserted
replaced
| 14020:13e7ba964993 | 14021:ef8490f9e823 |
|---|---|
| 18 * You should have received a copy of the GNU General Public License | 18 * You should have received a copy of the GNU General Public License |
| 19 * along with this program; if not, write to the Free Software | 19 * along with this program; if not, write to the Free Software |
| 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 21 */ | 21 */ |
| 22 | 22 |
| 23 #include "stdlib.h" // strtol | 23 #include "stdlib.h" |
| 24 #include "limits.h" | 24 #include "limits.h" |
| 25 #include "string.h" // strlen | 25 #include "string.h" |
| 26 | 26 |
| 27 #ifdef _WIN32 | 27 #ifdef _WIN32 |
| 28 #include "win32dep.h" | 28 #include "win32dep.h" |
| 29 #endif | 29 #endif |
| 30 | 30 |
| 31 #include "debug.h" // gaim_debug | 31 #include "char_conv.h" |
| 32 #include "debug.h" | |
| 33 #include "prefs.h" | |
| 32 #include "utils.h" | 34 #include "utils.h" |
| 33 #include "char_conv.h" // qq_to_utf8 | |
| 34 #include "prefs.h" // gaim_prefs_get_string | |
| 35 | 35 |
| 36 #define QQ_NAME_FORMAT "qq-%d" | 36 #define QQ_NAME_FORMAT "qq-%d" |
| 37 | 37 |
| 38 #ifndef g_str_has_prefix | 38 #ifndef g_str_has_prefix |
| 39 gint g_str_has_prefix(const gchar *str, const gchar *prefix) | 39 gint g_str_has_prefix(const gchar *str, const gchar *prefix) |
| 41 gint len = strlen(prefix); | 41 gint len = strlen(prefix); |
| 42 return !strncmp(str, prefix, len); | 42 return !strncmp(str, prefix, len); |
| 43 } | 43 } |
| 44 #endif | 44 #endif |
| 45 | 45 |
| 46 /*****************************************************************************/ | 46 gchar *get_name_by_index_str(gchar **array, const gchar *index_str, gint amount) |
| 47 gchar *get_name_by_index_str(gchar **array, const gchar *index_str, gint amount) { | 47 { |
| 48 gint index; | 48 gint index; |
| 49 | 49 |
| 50 index = atoi(index_str); | 50 index = atoi(index_str); |
| 51 if (index < 0 || index >= amount) | 51 if (index < 0 || index >= amount) |
| 52 index = 0; | 52 index = 0; |
| 53 | 53 |
| 54 return array[index]; | 54 return array[index]; |
| 55 } // get_name_by_index_str | 55 } |
| 56 | 56 |
| 57 /*****************************************************************************/ | 57 gchar *get_index_str_by_name(gchar **array, const gchar *name, gint amount) |
| 58 gchar *get_index_str_by_name(gchar **array, const gchar *name, gint amount) { | 58 { |
| 59 gint index; | 59 gint index; |
| 60 | 60 |
| 61 for (index = 0; index <= amount; index++) | 61 for (index = 0; index <= amount; index++) |
| 62 if (g_ascii_strcasecmp(array[index], name) == 0) | 62 if (g_ascii_strcasecmp(array[index], name) == 0) |
| 63 break; | 63 break; |
| 64 | 64 |
| 65 if (index >= amount) | 65 if (index >= amount) |
| 66 index = 0; // meaning no match | 66 index = 0; /* meaning no match */ |
| 67 return g_strdup_printf("%d", index); | 67 return g_strdup_printf("%d", index); |
| 68 } // get_index_str_by_name | 68 } |
| 69 | 69 |
| 70 /*****************************************************************************/ | |
| 71 gint qq_string_to_dec_value(const gchar *str) | 70 gint qq_string_to_dec_value(const gchar *str) |
| 72 { | 71 { |
| 73 g_return_val_if_fail(str != NULL, 0); | 72 g_return_val_if_fail(str != NULL, 0); |
| 74 return strtol(str, NULL, 10); | 73 return strtol(str, NULL, 10); |
| 75 } // _qq_string_to_dec_value | 74 } |
| 76 | 75 |
| 77 /*****************************************************************************/ | 76 /* split the given data(len) with delimit, |
| 78 // split the given data(len) with delimit, | 77 * check the number of field matches the expected_fields (<=0 means all) |
| 79 // check the number of field matches the expected_fields (<=0 means all) | 78 * return gchar* array (needs to be freed by g_strfreev later), or NULL */ |
| 80 // return gchar* array (needs to be freed by g_strfreev later), or NULL | 79 gchar **split_data(guint8 *data, gint len, const gchar *delimit, gint expected_fields) |
| 81 gchar **split_data(guint8 *data, gint len, const gchar *delimit, gint expected_fields) { | 80 { |
| 82 | |
| 83 guint8 *input; | 81 guint8 *input; |
| 84 gchar **segments; | 82 gchar **segments; |
| 85 gint i, j; | 83 gint i, j; |
| 86 | 84 |
| 87 g_return_val_if_fail(data != NULL && len != 0 && delimit != 0, NULL); | 85 g_return_val_if_fail(data != NULL && len != 0 && delimit != 0, NULL); |
| 88 | 86 |
| 89 // as the last field would be string, but data is not ended with 0x00 | 87 /* as the last field would be string, but data is not ended with 0x00 |
| 90 // we have to duplicate the data and append a 0x00 at the end | 88 * we have to duplicate the data and append a 0x00 at the end */ |
| 91 input = g_newa(guint8, len + 1); | 89 input = g_newa(guint8, len + 1); |
| 92 g_memmove(input, data, len); | 90 g_memmove(input, data, len); |
| 93 input[len] = 0x00; | 91 input[len] = 0x00; |
| 94 | 92 |
| 95 segments = g_strsplit((gchar *) input, delimit, 0); | 93 segments = g_strsplit((gchar *) input, delimit, 0); |
| 96 if (expected_fields <= 0) | 94 if (expected_fields <= 0) |
| 97 return segments; | 95 return segments; |
| 98 | 96 |
| 99 for (i = 0; segments[i] != NULL; i++) {; | 97 for (i = 0; segments[i] != NULL; i++) {; |
| 100 } | 98 } |
| 101 if (i < expected_fields) { // not enough fields | 99 if (i < expected_fields) { /* not enough fields */ |
| 102 gaim_debug(GAIM_DEBUG_ERROR, "QQ", | 100 gaim_debug(GAIM_DEBUG_ERROR, "QQ", |
| 103 "Invalid data, expect %d fields, found only %d, discard\n", expected_fields, i); | 101 "Invalid data, expect %d fields, found only %d, discard\n", expected_fields, i); |
| 104 g_strfreev(segments); | 102 g_strfreev(segments); |
| 105 return NULL; | 103 return NULL; |
| 106 } else if (i > expected_fields) { // more fields, OK | 104 } else if (i > expected_fields) { /* more fields, OK */ |
| 107 gaim_debug(GAIM_DEBUG_WARNING, "QQ", | 105 gaim_debug(GAIM_DEBUG_WARNING, "QQ", |
| 108 "Dangerous data, expect %d fields, found %d, return all\n", expected_fields, i); | 106 "Dangerous data, expect %d fields, found %d, return all\n", expected_fields, i); |
| 109 // free up those not used | 107 /* free up those not used */ |
| 110 for (j = expected_fields; j < i; j++) { | 108 for (j = expected_fields; j < i; j++) { |
| 111 gaim_debug(GAIM_DEBUG_WARNING, "QQ", "field[%d] is %s\n", j, segments[j]); | 109 gaim_debug(GAIM_DEBUG_WARNING, "QQ", "field[%d] is %s\n", j, segments[j]); |
| 112 g_free(segments[j]); | 110 g_free(segments[j]); |
| 113 } | 111 } |
| 114 | 112 |
| 116 } | 114 } |
| 117 | 115 |
| 118 return segments; | 116 return segments; |
| 119 } | 117 } |
| 120 | 118 |
| 121 /*****************************************************************************/ | 119 /* given a four-byte ip data, convert it into a human readable ip string |
| 122 // given a four-byte ip data, convert it into a human readable ip string | 120 * the return needs to be freed */ |
| 123 // the return needs to be freed | |
| 124 gchar *gen_ip_str(guint8 *ip) | 121 gchar *gen_ip_str(guint8 *ip) |
| 125 { | 122 { |
| 126 gchar *ret; | 123 gchar *ret; |
| 127 if (ip == NULL || ip[0] == 0) { | 124 if (ip == NULL || ip[0] == 0) { |
| 128 ret = g_new(gchar, 1); | 125 ret = g_new(gchar, 1); |
| 129 *ret = '\0'; | 126 *ret = '\0'; |
| 130 return ret; | 127 return ret; |
| 131 } else | 128 } else { |
| 132 return g_strdup_printf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); | 129 return g_strdup_printf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); |
| 130 } | |
| 133 } | 131 } |
| 134 | 132 |
| 135 guint8 *str_ip_gen(gchar *str) { | 133 guint8 *str_ip_gen(gchar *str) { |
| 136 guint8 *ip = g_new(guint8, 4); | 134 guint8 *ip = g_new(guint8, 4); |
| 137 int a, b, c, d; | 135 int a, b, c, d; |
| 141 ip[2] = c; | 139 ip[2] = c; |
| 142 ip[3] = d; | 140 ip[3] = d; |
| 143 return ip; | 141 return ip; |
| 144 } | 142 } |
| 145 | 143 |
| 146 /*****************************************************************************/ | 144 /* return the QQ icon file name |
| 147 // return the QQ icon file name | 145 * the return needs to be freed */ |
| 148 // the return needs to be freed | |
| 149 gchar *get_icon_name(gint set, gint suffix) | 146 gchar *get_icon_name(gint set, gint suffix) |
| 150 { | 147 { |
| 151 return g_strdup_printf("qq_%d-%d", set, suffix); | 148 return g_strdup_printf("qq_%d-%d", set, suffix); |
| 152 } // get_icon_name | 149 } |
| 153 | 150 |
| 154 /*****************************************************************************/ | 151 /* convert a QQ UID to a unique name of GAIM |
| 155 // convert a QQ UID to a unique name of GAIM | 152 * the return needs to be freed */ |
| 156 // the return needs to be freed | |
| 157 gchar *uid_to_gaim_name(guint32 uid) | 153 gchar *uid_to_gaim_name(guint32 uid) |
| 158 { | 154 { |
| 159 return g_strdup_printf(QQ_NAME_FORMAT, uid); | 155 return g_strdup_printf(QQ_NAME_FORMAT, uid); |
| 160 } // uid_to_gaim_name | 156 } |
| 161 | 157 |
| 162 /*****************************************************************************/ | 158 /* convert GAIM name to original QQ UID */ |
| 163 // convert GAIM name to original QQ UID | |
| 164 guint32 gaim_name_to_uid(const gchar *name) | 159 guint32 gaim_name_to_uid(const gchar *name) |
| 165 { | 160 { |
| 166 gchar *p; | 161 gchar *p; |
| 167 | 162 |
| 168 g_return_val_if_fail(g_str_has_prefix(name, QQ_NAME_PREFIX), 0); | 163 g_return_val_if_fail(g_str_has_prefix(name, QQ_NAME_PREFIX), 0); |
| 169 | 164 |
| 170 p = g_strrstr(name, QQ_NAME_PREFIX); | 165 p = g_strrstr(name, QQ_NAME_PREFIX); |
| 171 // atoi is not thread-safe and also not async-cancel safe | |
| 172 // atoi is deprecated by strtol() and should not be used in new code | |
| 173 return (p == NULL) ? 0 : strtol(p + strlen(QQ_NAME_PREFIX), NULL, 10); | 166 return (p == NULL) ? 0 : strtol(p + strlen(QQ_NAME_PREFIX), NULL, 10); |
| 174 } | 167 } |
| 175 | 168 |
| 176 /*****************************************************************************/ | 169 /* try to dump the data as GBK */ |
| 177 // try to dump the data as GBK | |
| 178 void try_dump_as_gbk(guint8 *data, gint len) | 170 void try_dump_as_gbk(guint8 *data, gint len) |
| 179 { | 171 { |
| 180 gint i; | 172 gint i; |
| 181 guint8 *incoming; | 173 guint8 *incoming; |
| 182 gchar *msg_utf8; | 174 gchar *msg_utf8; |
| 183 | 175 |
| 184 incoming = g_newa(guint8, len + 1); | 176 incoming = g_newa(guint8, len + 1); |
| 185 g_memmove(incoming, data, len); | 177 g_memmove(incoming, data, len); |
| 186 incoming[len] = 0x00; | 178 incoming[len] = 0x00; |
| 187 // GBK code: | 179 /* GBK code: |
| 188 // Single-byte ASCII: 0x21-0x7E | 180 * Single-byte ASCII: 0x21-0x7E |
| 189 // GBK first byte range: 0x81-0xFE | 181 * GBK first byte range: 0x81-0xFE |
| 190 // GBK second byte range: 0x40-0x7E and 0x80-0xFE | 182 * GBK second byte range: 0x40-0x7E and 0x80-0xFE */ |
| 191 for (i = 0; i < len; i++) | 183 for (i = 0; i < len; i++) |
| 192 if (incoming[i] >= 0x81) | 184 if (incoming[i] >= 0x81) |
| 193 break; | 185 break; |
| 194 | 186 |
| 195 msg_utf8 = i < len ? qq_to_utf8((gchar *) &incoming[i], QQ_CHARSET_DEFAULT) : NULL; | 187 msg_utf8 = i < len ? qq_to_utf8((gchar *) &incoming[i], QQ_CHARSET_DEFAULT) : NULL; |
| 196 | 188 |
| 197 if (msg_utf8 != NULL) { | 189 if (msg_utf8 != NULL) { |
| 198 gaim_debug(GAIM_DEBUG_WARNING, "QQ", "Try extract GB msg: %s\n", msg_utf8); | 190 gaim_debug(GAIM_DEBUG_WARNING, "QQ", "Try extract GB msg: %s\n", msg_utf8); |
| 199 g_free(msg_utf8); | 191 g_free(msg_utf8); |
| 200 } // msg_utf8 != NULL | 192 } |
| 201 } // try_dump_gbk | 193 } |
| 202 | 194 |
| 203 /*****************************************************************************/ | 195 /* strips whitespace */ |
| 204 // strips whitespace | |
| 205 static gchar *strstrip(const gchar *buffer) | 196 static gchar *strstrip(const gchar *buffer) |
| 206 { | 197 { |
| 207 GString *stripped; | 198 GString *stripped; |
| 208 gchar *ret; | 199 gchar *ret; |
| 209 int i; | 200 int i; |
| 218 g_string_free(stripped, FALSE); | 209 g_string_free(stripped, FALSE); |
| 219 | 210 |
| 220 return ret; | 211 return ret; |
| 221 } | 212 } |
| 222 | 213 |
| 223 /*****************************************************************************/ | 214 /* Dumps an ASCII hex string to a string of bytes. The return should be freed later. |
| 224 // Dumps an ASCII hex string to a string of bytes. The return should be freed later. | 215 * Returns NULL if a string with an odd number of nibbles is passed in or if buffer |
| 225 // Returns NULL if a string with an odd number of nibbles is passed in or if buffer | 216 * isn't a valid hex string */ |
| 226 // isn't a valid hex string | |
| 227 guint8 *hex_str_to_bytes(const gchar *buffer) | 217 guint8 *hex_str_to_bytes(const gchar *buffer) |
| 228 { | 218 { |
| 229 gchar *hex_str, *hex_buffer, *cursor, tmp; | 219 gchar *hex_str, *hex_buffer, *cursor, tmp; |
| 230 guint8 *bytes, nibble1, nibble2; | 220 guint8 *bytes, nibble1, nibble2; |
| 231 gint index, len; | 221 gint index, len; |
| 266 len = strlen(hex_str) / 2; | 256 len = strlen(hex_str) / 2; |
| 267 g_free(hex_str); | 257 g_free(hex_str); |
| 268 return g_memdup(bytes, len); | 258 return g_memdup(bytes, len); |
| 269 } | 259 } |
| 270 | 260 |
| 271 // Dumps a chunk of raw data into an ASCII hex string. The return should be freed later. | 261 /* Dumps a chunk of raw data into an ASCII hex string. The return should be freed later. */ |
| 272 gchar *hex_dump_to_str(const guint8 *buffer, gint bytes) | 262 gchar *hex_dump_to_str(const guint8 *buffer, gint bytes) |
| 273 { | 263 { |
| 274 GString *str; | 264 GString *str; |
| 275 gchar *ret; | 265 gchar *ret; |
| 276 gint i, j, ch; | 266 gint i, j, ch; |
| 277 | 267 |
| 278 str = g_string_new(""); | 268 str = g_string_new(""); |
| 279 for (i = 0; i < bytes; i += 16) { | 269 for (i = 0; i < bytes; i += 16) { |
| 280 // length label | 270 /* length label */ |
| 281 g_string_append_printf(str, "%04d: ", i); | 271 g_string_append_printf(str, "%04d: ", i); |
| 282 | 272 |
| 283 // dump hex value | 273 /* dump hex value */ |
| 284 for (j = 0; j < 16; j++) | 274 for (j = 0; j < 16; j++) |
| 285 if ((i + j) < bytes) | 275 if ((i + j) < bytes) |
| 286 g_string_append_printf(str, " %02X", buffer[i + j]); | 276 g_string_append_printf(str, " %02X", buffer[i + j]); |
| 287 else | 277 else |
| 288 g_string_append(str, " "); | 278 g_string_append(str, " "); |
| 289 g_string_append(str, " "); | 279 g_string_append(str, " "); |
| 290 | 280 |
| 291 // dump ascii value | 281 /* dump ascii value */ |
| 292 for (j = 0; j < 16 && (i + j) < bytes; j++) { | 282 for (j = 0; j < 16 && (i + j) < bytes; j++) { |
| 293 ch = buffer[i + j] & 127; | 283 ch = buffer[i + j] & 127; |
| 294 if (ch < ' ' || ch == 127) | 284 if (ch < ' ' || ch == 127) |
| 295 g_string_append_c(str, '.'); | 285 g_string_append_c(str, '.'); |
| 296 else | 286 else |
| 298 } | 288 } |
| 299 g_string_append_c(str, '\n'); | 289 g_string_append_c(str, '\n'); |
| 300 } | 290 } |
| 301 | 291 |
| 302 ret = str->str; | 292 ret = str->str; |
| 303 // GString can be freed without freeing it character data | 293 /* GString can be freed without freeing it character data */ |
| 304 g_string_free(str, FALSE); | 294 g_string_free(str, FALSE); |
| 305 | 295 |
| 306 return ret; | 296 return ret; |
| 307 } | 297 } |
