Mercurial > pidgin.yaz
comparison src/protocols/yahoo/yahoochat.c @ 8113:d60272410bd5
[gaim-migrate @ 8817]
Tim 'marv' Ringenbach wrote us a wonderful core/ui split chat room list
thing-a-ma-jig. I've taken the liberty of adding jabber support to it
as well.
committer: Tailor Script <tailor@pidgin.im>
author | Nathan Walp <nwalp@pidgin.im> |
---|---|
date | Thu, 15 Jan 2004 22:20:29 +0000 |
parents | fa6395637e2c |
children | 1f56ea865926 |
comparison
equal
deleted
inserted
replaced
8112:67387ec77301 | 8113:d60272410bd5 |
---|---|
1002 yahoo_chat_invite(gc, gaim_connection_get_display_name(gc), name, | 1002 yahoo_chat_invite(gc, gaim_connection_get_display_name(gc), name, |
1003 gaim_conversation_get_name(c), msg); | 1003 gaim_conversation_get_name(c), msg); |
1004 } | 1004 } |
1005 } | 1005 } |
1006 | 1006 |
1007 | |
1008 struct yahoo_roomlist { | |
1009 int fd; | |
1010 int inpa; | |
1011 guchar *rxqueue; | |
1012 int rxlen; | |
1013 gboolean started; | |
1014 char *path; | |
1015 char *host; | |
1016 GaimRoomlist *list; | |
1017 GaimRoomlistRoom *cat; | |
1018 GaimRoomlistRoom *ucat; | |
1019 GMarkupParseContext *parse; | |
1020 | |
1021 }; | |
1022 | |
1023 static void yahoo_roomlist_destroy(struct yahoo_roomlist *yrl) | |
1024 { | |
1025 if (yrl->inpa) | |
1026 gaim_input_remove(yrl->inpa); | |
1027 if (yrl->rxqueue) | |
1028 g_free(yrl->rxqueue); | |
1029 if (yrl->path) | |
1030 g_free(yrl->path); | |
1031 if (yrl->host) | |
1032 g_free(yrl->host); | |
1033 if (yrl->parse) | |
1034 g_markup_parse_context_free(yrl->parse); | |
1035 } | |
1036 | |
1037 enum yahoo_room_type { | |
1038 yrt_yahoo, | |
1039 yrt_user, | |
1040 }; | |
1041 | |
1042 struct yahoo_chatxml_state { | |
1043 GaimRoomlist *list; | |
1044 struct yahoo_roomlist *yrl; | |
1045 GQueue *q; | |
1046 struct { | |
1047 enum yahoo_room_type type; | |
1048 char *name; | |
1049 char *topic; | |
1050 char *id; | |
1051 int users, voices, webcams; | |
1052 } room; | |
1053 }; | |
1054 | |
1055 struct yahoo_lobby { | |
1056 int count, users, voices, webcams; | |
1057 }; | |
1058 | |
1059 static struct yahoo_chatxml_state *yahoo_chatxml_state_new(GaimRoomlist *list, struct yahoo_roomlist *yrl) | |
1060 { | |
1061 struct yahoo_chatxml_state *s; | |
1062 | |
1063 s = g_new0(struct yahoo_chatxml_state, 1); | |
1064 | |
1065 s->list = list; | |
1066 s->yrl = yrl; | |
1067 s->q = g_queue_new(); | |
1068 | |
1069 return s; | |
1070 } | |
1071 | |
1072 static void yahoo_chatxml_state_destroy(struct yahoo_chatxml_state *s) | |
1073 { | |
1074 g_queue_free(s->q); | |
1075 if (s->room.name) | |
1076 g_free(s->room.name); | |
1077 if (s->room.topic) | |
1078 g_free(s->room.topic); | |
1079 if (s->room.id) | |
1080 g_free(s->room.id); | |
1081 g_free(s); | |
1082 } | |
1083 | |
1084 static void yahoo_chatlist_start_element(GMarkupParseContext *context, const gchar *ename, | |
1085 const gchar **anames, const gchar **avalues, | |
1086 gpointer user_data, GError **error) | |
1087 { | |
1088 struct yahoo_chatxml_state *s = user_data; | |
1089 GaimRoomlist *list = s->list; | |
1090 GaimRoomlistRoom *r; | |
1091 GaimRoomlistRoom *parent; | |
1092 int i; | |
1093 | |
1094 if (!strcmp(ename, "category")) { | |
1095 const gchar *name = NULL, *id = NULL; | |
1096 | |
1097 for (i = 0; anames[i]; i++) { | |
1098 if (!strcmp(anames[i], "id")) | |
1099 id = avalues[i]; | |
1100 if (!strcmp(anames[i], "name")) | |
1101 name = avalues[i]; | |
1102 } | |
1103 if (!name || !id) | |
1104 return; | |
1105 | |
1106 parent = g_queue_peek_head(s->q); | |
1107 r = gaim_roomlist_room_new(GAIM_ROOMLIST_ROOMTYPE_CATAGORY, name, parent); | |
1108 gaim_roomlist_room_add_field(list, r, (gpointer)name); | |
1109 gaim_roomlist_room_add_field(list, r, (gpointer)id); | |
1110 gaim_roomlist_room_add(list, r); | |
1111 g_queue_push_head(s->q, r); | |
1112 } else if (!strcmp(ename, "room")) { | |
1113 s->room.users = s->room.voices = s->room.webcams = 0; | |
1114 | |
1115 for (i = 0; anames[i]; i++) { | |
1116 if (!strcmp(anames[i], "id")) { | |
1117 if (s->room.id) | |
1118 g_free(s->room.id); | |
1119 s->room.id = g_strdup(avalues[i]); | |
1120 } else if (!strcmp(anames[i], "name")) { | |
1121 if (s->room.name) | |
1122 g_free(s->room.name); | |
1123 s->room.name = g_strdup(avalues[i]); | |
1124 } else if (!strcmp(anames[i], "topic")) { | |
1125 if (s->room.topic) | |
1126 g_free(s->room.topic); | |
1127 s->room.topic = g_strdup(avalues[i]); | |
1128 } else if (!strcmp(anames[i], "type")) { | |
1129 if (!strcmp("yahoo", avalues[i])) | |
1130 s->room.type = yrt_yahoo; | |
1131 else | |
1132 s->room.type = yrt_user; | |
1133 } | |
1134 } | |
1135 | |
1136 } else if (!strcmp(ename, "lobby")) { | |
1137 struct yahoo_lobby *lob = g_new0(struct yahoo_lobby, 1); | |
1138 | |
1139 for (i = 0; anames[i]; i++) { | |
1140 if (!strcmp(anames[i], "count")) { | |
1141 lob->count = strtol(avalues[i], NULL, 10); | |
1142 } else if (!strcmp(anames[i], "users")) { | |
1143 s->room.users += lob->users = strtol(avalues[i], NULL, 10); | |
1144 } else if (!strcmp(anames[i], "voices")) { | |
1145 s->room.voices += lob->voices = strtol(avalues[i], NULL, 10); | |
1146 } else if (!strcmp(anames[i], "webcams")) { | |
1147 s->room.webcams += lob->webcams = strtol(avalues[i], NULL, 10); | |
1148 } | |
1149 } | |
1150 | |
1151 g_queue_push_head(s->q, lob); | |
1152 } | |
1153 | |
1154 } | |
1155 | |
1156 static void yahoo_chatlist_end_element(GMarkupParseContext *context, const gchar *ename, | |
1157 gpointer user_data, GError **error) | |
1158 { | |
1159 struct yahoo_chatxml_state *s = user_data; | |
1160 | |
1161 if (!strcmp(ename, "category")) { | |
1162 g_queue_pop_head(s->q); | |
1163 } else if (!strcmp(ename, "room")) { | |
1164 struct yahoo_lobby *lob; | |
1165 GaimRoomlistRoom *r, *l; | |
1166 | |
1167 if (s->room.type == yrt_yahoo) | |
1168 r = gaim_roomlist_room_new(GAIM_ROOMLIST_ROOMTYPE_CATAGORY|GAIM_ROOMLIST_ROOMTYPE_ROOM, | |
1169 s->room.name, s->yrl->cat); | |
1170 else | |
1171 r = gaim_roomlist_room_new(GAIM_ROOMLIST_ROOMTYPE_CATAGORY|GAIM_ROOMLIST_ROOMTYPE_ROOM, | |
1172 s->room.name, s->yrl->ucat); | |
1173 | |
1174 gaim_roomlist_room_add_field(s->list, r, s->room.name); | |
1175 gaim_roomlist_room_add_field(s->list, r, s->room.id); | |
1176 gaim_roomlist_room_add_field(s->list, r, GINT_TO_POINTER(s->room.users)); | |
1177 gaim_roomlist_room_add_field(s->list, r, GINT_TO_POINTER(s->room.voices)); | |
1178 gaim_roomlist_room_add_field(s->list, r, GINT_TO_POINTER(s->room.webcams)); | |
1179 gaim_roomlist_room_add_field(s->list, r, s->room.topic); | |
1180 gaim_roomlist_room_add(s->list, r); | |
1181 | |
1182 while ((lob = g_queue_pop_head(s->q))) { | |
1183 char *name = g_strdup_printf("%s:%d", s->room.name, lob->count); | |
1184 l = gaim_roomlist_room_new(GAIM_ROOMLIST_ROOMTYPE_ROOM, name, r); | |
1185 | |
1186 gaim_roomlist_room_add_field(s->list, l, name); | |
1187 gaim_roomlist_room_add_field(s->list, l, s->room.id); | |
1188 gaim_roomlist_room_add_field(s->list, l, GINT_TO_POINTER(lob->users)); | |
1189 gaim_roomlist_room_add_field(s->list, l, GINT_TO_POINTER(lob->voices)); | |
1190 gaim_roomlist_room_add_field(s->list, l, GINT_TO_POINTER(lob->webcams)); | |
1191 gaim_roomlist_room_add_field(s->list, l, s->room.topic); | |
1192 gaim_roomlist_room_add(s->list, l); | |
1193 | |
1194 g_free(name); | |
1195 g_free(lob); | |
1196 } | |
1197 | |
1198 } | |
1199 | |
1200 } | |
1201 | |
1202 static GMarkupParser parser = { | |
1203 yahoo_chatlist_start_element, | |
1204 yahoo_chatlist_end_element, | |
1205 NULL, | |
1206 NULL, | |
1207 NULL | |
1208 }; | |
1209 | |
1210 static void yahoo_roomlist_cleanup(GaimRoomlist *list, struct yahoo_roomlist *yrl) | |
1211 { | |
1212 gaim_roomlist_set_in_progress(list, FALSE); | |
1213 | |
1214 if (yrl) { | |
1215 list->proto_data = g_list_remove(list->proto_data, yrl); | |
1216 yahoo_roomlist_destroy(yrl); | |
1217 } | |
1218 | |
1219 gaim_roomlist_unref(list); | |
1220 } | |
1221 | |
1222 static void yahoo_roomlist_pending(gpointer data, gint source, GaimInputCondition cond) | |
1223 { | |
1224 struct yahoo_roomlist *yrl = data; | |
1225 GaimRoomlist *list = yrl->list; | |
1226 char buf[1024]; | |
1227 int len; | |
1228 guchar *start; | |
1229 struct yahoo_chatxml_state *s; | |
1230 | |
1231 len = read(yrl->fd, buf, sizeof(buf)); | |
1232 | |
1233 if (len <= 0) { | |
1234 if (yrl->parse) | |
1235 g_markup_parse_context_end_parse(yrl->parse, NULL); | |
1236 yahoo_roomlist_cleanup(list, yrl); | |
1237 return; | |
1238 } | |
1239 | |
1240 | |
1241 yrl->rxqueue = g_realloc(yrl->rxqueue, len + yrl->rxlen); | |
1242 memcpy(yrl->rxqueue + yrl->rxlen, buf, len); | |
1243 yrl->rxlen += len; | |
1244 | |
1245 if (!yrl->started) { | |
1246 yrl->started = TRUE; | |
1247 start = g_strstr_len(yrl->rxqueue, yrl->rxlen, "\r\n\r\n"); | |
1248 if (!start || (start - yrl->rxqueue + 4) >= yrl->rxlen) | |
1249 return; | |
1250 start += 4; | |
1251 } else { | |
1252 start = yrl->rxqueue; | |
1253 } | |
1254 | |
1255 if (yrl->parse == NULL) { | |
1256 s = yahoo_chatxml_state_new(list, yrl); | |
1257 yrl->parse = g_markup_parse_context_new(&parser, 0, s, | |
1258 (GDestroyNotify)yahoo_chatxml_state_destroy); | |
1259 } | |
1260 | |
1261 if (!g_markup_parse_context_parse(yrl->parse, start, (yrl->rxlen - (start - yrl->rxqueue)), NULL)) { | |
1262 | |
1263 yahoo_roomlist_cleanup(list, yrl); | |
1264 return; | |
1265 } | |
1266 | |
1267 yrl->rxlen = 0; | |
1268 } | |
1269 | |
1270 static void yahoo_roomlist_got_connected(gpointer data, gint source, GaimInputCondition cond) | |
1271 { | |
1272 struct yahoo_roomlist *yrl = data; | |
1273 GaimRoomlist *list = yrl->list; | |
1274 char *buf, *cookie; | |
1275 struct yahoo_data *yd = gaim_account_get_connection(list->account)->proto_data; | |
1276 | |
1277 if (source < 0) { | |
1278 gaim_notify_error(gaim_account_get_connection(list->account), NULL, _("Unable to connect"), _("Fetching the room list failed.")); | |
1279 yahoo_roomlist_cleanup(list, yrl); | |
1280 return; | |
1281 } | |
1282 | |
1283 yrl->fd = source; | |
1284 | |
1285 cookie = g_strdup_printf("Y=%s; T=%s", yd->cookie_y, yd->cookie_t); | |
1286 buf = g_strdup_printf("GET /%s HTTP/1.0\r\nHost: %s\r\nCookie: %s\r\n\r\n", yrl->path, yrl->host, cookie); | |
1287 write(yrl->fd, buf, strlen(buf)); | |
1288 g_free(cookie); | |
1289 g_free(buf); | |
1290 yrl->inpa = gaim_input_add(yrl->fd, GAIM_INPUT_READ, yahoo_roomlist_pending, yrl); | |
1291 | |
1292 } | |
1293 | |
1294 GaimRoomlist *yahoo_roomlist_get_list(GaimConnection *gc) | |
1295 { | |
1296 struct yahoo_roomlist *yrl; | |
1297 GaimRoomlist *rl; | |
1298 char *url; | |
1299 GList *fields = NULL; | |
1300 GaimRoomlistField *f; | |
1301 | |
1302 url = g_strdup_printf("%s?chatcat=0", | |
1303 gaim_account_get_string( | |
1304 gaim_connection_get_account(gc), | |
1305 "room_list", YAHOO_ROOMLIST_URL)); | |
1306 | |
1307 yrl = g_new0(struct yahoo_roomlist, 1); | |
1308 rl = gaim_roomlist_new(gaim_connection_get_account(gc)); | |
1309 yrl->list = rl; | |
1310 | |
1311 gaim_url_parse(url, &(yrl->host), NULL, &(yrl->path)); | |
1312 g_free(url); | |
1313 | |
1314 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_STRING, "", "room", TRUE); | |
1315 fields = g_list_append(fields, f); | |
1316 | |
1317 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_STRING, "", "id", TRUE); | |
1318 fields = g_list_append(fields, f); | |
1319 | |
1320 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_INT, _("Users"), "users", FALSE); | |
1321 fields = g_list_append(fields, f); | |
1322 | |
1323 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_INT, _("Voices"), "voices", FALSE); | |
1324 fields = g_list_append(fields, f); | |
1325 | |
1326 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_INT, _("Webcams"), "webcams", FALSE); | |
1327 fields = g_list_append(fields, f); | |
1328 | |
1329 f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_STRING, _("Topic"), "topic", FALSE); | |
1330 fields = g_list_append(fields, f); | |
1331 | |
1332 gaim_roomlist_set_fields(rl, fields); | |
1333 | |
1334 if (gaim_proxy_connect(gaim_connection_get_account(gc), | |
1335 yrl->host, 80, yahoo_roomlist_got_connected, yrl) != 0) | |
1336 { | |
1337 gaim_notify_error(gc, NULL, _("Connection problem"), _("Unable to fetch room list.")); | |
1338 yahoo_roomlist_cleanup(rl, yrl); | |
1339 return NULL; | |
1340 } | |
1341 | |
1342 rl->proto_data = g_list_append(rl->proto_data, yrl); | |
1343 | |
1344 gaim_roomlist_set_in_progress(rl, TRUE); | |
1345 return rl; | |
1346 } | |
1347 | |
1348 void yahoo_roomlist_cancel(GaimRoomlist *list) | |
1349 { | |
1350 GList *l, *k; | |
1351 | |
1352 k = l = list->proto_data; | |
1353 list->proto_data = NULL; | |
1354 | |
1355 gaim_roomlist_set_in_progress(list, FALSE); | |
1356 | |
1357 for (; l; l = l->next) { | |
1358 yahoo_roomlist_destroy(l->data); | |
1359 gaim_roomlist_unref(l->data); | |
1360 } | |
1361 g_list_free(k); | |
1362 } | |
1363 | |
1364 void yahoo_roomlist_expand_catagory(GaimRoomlist *list, GaimRoomlistRoom *catagory) | |
1365 { | |
1366 struct yahoo_roomlist *yrl; | |
1367 char *url; | |
1368 char *id; | |
1369 | |
1370 if (catagory->type != GAIM_ROOMLIST_ROOMTYPE_CATAGORY) | |
1371 return; | |
1372 | |
1373 if (!(id = g_list_nth_data(catagory->fields, 1))) { | |
1374 gaim_roomlist_set_in_progress(list, FALSE); | |
1375 return; | |
1376 } | |
1377 | |
1378 url = g_strdup_printf("%s?chatroom_%s=0", | |
1379 gaim_account_get_string( | |
1380 list->account, | |
1381 "room_list", YAHOO_ROOMLIST_URL), id); | |
1382 | |
1383 yrl = g_new0(struct yahoo_roomlist, 1); | |
1384 yrl->list = list; | |
1385 yrl->cat = catagory; | |
1386 list->proto_data = g_list_append(list->proto_data, yrl); | |
1387 | |
1388 gaim_url_parse(url, &(yrl->host), NULL, &(yrl->path)); | |
1389 g_free(url); | |
1390 | |
1391 yrl->ucat = gaim_roomlist_room_new(GAIM_ROOMLIST_ROOMTYPE_CATAGORY, _("User Rooms"), yrl->cat); | |
1392 gaim_roomlist_room_add(list, yrl->ucat); | |
1393 | |
1394 if (gaim_proxy_connect(list->account, | |
1395 yrl->host, 80, yahoo_roomlist_got_connected, yrl) != 0) | |
1396 { | |
1397 gaim_notify_error(gaim_account_get_connection(list->account), | |
1398 NULL, _("Connection problem"), _("Unable to fetch room list.")); | |
1399 yahoo_roomlist_cleanup(list, yrl); | |
1400 return; | |
1401 } | |
1402 | |
1403 gaim_roomlist_set_in_progress(list, TRUE); | |
1404 gaim_roomlist_ref(list); | |
1405 } | |
1406 |