Commit | Line | Data |
---|---|---|
0af3c916 | 1 | /* |
2 | * Dolda Connect - Modular multiuser Direct Connect-style client | |
302a2600 | 3 | * Copyright (C) 2005 Fredrik Tolf <fredrik@dolda2000.com> |
0af3c916 | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License as published by | |
7 | * the Free Software Foundation; either version 2 of the License, or | |
8 | * (at your option) any later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with this program; if not, write to the Free Software | |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | */ | |
ccea96e5 | 19 | |
ee5d122f | 20 | #ifdef HAVE_CONFIG_H |
21 | #include <config.h> | |
22 | #endif | |
23 | #include <string.h> | |
24 | #include <doldaconnect/uilib.h> | |
25 | #include <doldaconnect/uimisc.h> | |
26 | #include <doldaconnect/utils.h> | |
ee5d122f | 27 | #include <plugin.h> |
28 | #include <version.h> | |
29 | #include <accountopt.h> | |
30 | #include <roomlist.h> | |
31 | #include <util.h> | |
32 | #include <errno.h> | |
33 | ||
34 | struct conndata { | |
35 | int fd; | |
36 | int readhdl, writehdl; | |
34ec1e2f FT |
37 | G/PCConnection *gc; |
38 | G/PCRoomlist *roomlist; | |
ee5d122f | 39 | }; |
40 | ||
41 | static struct conndata *inuse = NULL; | |
34ec1e2f | 42 | static G/PCPlugin *me; |
ee5d122f | 43 | |
34ec1e2f | 44 | static void dcfdcb(struct conndata *data, int fd, G/PCInputCondition condition); |
ee5d122f | 45 | |
46 | static void updatewrite(struct conndata *data) | |
47 | { | |
48 | if(dc_wantwrite()) { | |
49 | if(data->writehdl == -1) | |
34ec1e2f | 50 | data->writehdl = G/P_input_add(data->fd, G/PU_INPUT_WRITE, (void (*)(void *, int, G/PCInputCondition))dcfdcb, data); |
ee5d122f | 51 | } else { |
52 | if(data->writehdl != -1) { | |
34ec1e2f | 53 | G/P_input_remove(data->writehdl); |
ee5d122f | 54 | data->writehdl = -1; |
55 | } | |
56 | } | |
57 | } | |
58 | ||
59 | static void disconnected(struct conndata *data) | |
60 | { | |
61 | if(inuse == data) | |
62 | inuse = NULL; | |
63 | if(data->readhdl != -1) { | |
34ec1e2f | 64 | G/P_input_remove(data->readhdl); |
ee5d122f | 65 | data->readhdl = -1; |
66 | } | |
67 | if(data->writehdl != -1) { | |
34ec1e2f | 68 | G/P_input_remove(data->writehdl); |
ee5d122f | 69 | data->writehdl = -1; |
70 | } | |
71 | data->fd = -1; | |
72 | } | |
73 | ||
74 | static int loginconv(int type, wchar_t *text, char **resp, struct conndata *data) | |
75 | { | |
76 | switch(type) { | |
77 | case DC_LOGIN_CONV_NOECHO: | |
78 | if(data->gc->account->password == NULL) { | |
79 | updatewrite(data); | |
80 | return(1); | |
81 | } else { | |
82 | *resp = sstrdup(data->gc->account->password); | |
83 | updatewrite(data); | |
84 | return(0); | |
85 | } | |
86 | default: | |
87 | updatewrite(data); | |
88 | return(1); | |
89 | } | |
90 | } | |
91 | ||
34ec1e2f | 92 | static gboolean gi_chatjoincb(G/PCConversation *conv, const char *user, G/PCConvChatBuddyFlags flags, void *uudata) |
649eeeb6 | 93 | { |
34ec1e2f | 94 | G/PCConnection *c; |
649eeeb6 | 95 | |
34ec1e2f | 96 | if((c = G/P_conversation_get_gc(conv)) == NULL) |
649eeeb6 | 97 | return(FALSE); |
98 | if(c->prpl == me) | |
99 | return(TRUE); | |
100 | return(FALSE); | |
101 | } | |
102 | ||
34ec1e2f | 103 | static gboolean gi_chatleavecb(G/PCConversation *conv, const char *user, const char *reason, void *uudata) |
649eeeb6 | 104 | { |
34ec1e2f | 105 | G/PCConnection *c; |
649eeeb6 | 106 | |
34ec1e2f | 107 | if((c = G/P_conversation_get_gc(conv)) == NULL) |
649eeeb6 | 108 | return(FALSE); |
109 | if(c->prpl == me) | |
110 | return(TRUE); | |
111 | return(FALSE); | |
112 | } | |
113 | ||
ccb54a17 | 114 | static void regsigs(void) |
115 | { | |
34ec1e2f | 116 | static G/PCPlugin *regged = NULL; |
ccb54a17 | 117 | |
118 | if(regged != me) { | |
34ec1e2f FT |
119 | G/P_signal_connect(G/P_conversations_get_handle(), "chat-buddy-joining", me, G/PU_CALLBACK(gi_chatjoincb), NULL); |
120 | G/P_signal_connect(G/P_conversations_get_handle(), "chat-buddy-leaving", me, G/PU_CALLBACK(gi_chatleavecb), NULL); | |
ccb54a17 | 121 | regged = me; |
122 | } | |
123 | } | |
124 | ||
ee5d122f | 125 | static void newpeercb(struct dc_fnetpeer *peer) |
126 | { | |
127 | struct conndata *data; | |
34ec1e2f | 128 | G/PCConversation *conv; |
dc53e482 | 129 | char *buf; |
ee5d122f | 130 | |
131 | data = peer->fn->udata; | |
34ec1e2f | 132 | if((conv = G/P_find_chat(data->gc, peer->fn->id)) != NULL) { |
c17c238e | 133 | buf = sprintf2("%s", icswcstombs(peer->nick, "UTF-8", NULL)); |
34ec1e2f | 134 | G/P_conv_chat_add_user(G/PU_CONV_CHAT(conv), buf, NULL, G/PU_CBFLAGS_NONE, TRUE); |
dc53e482 | 135 | free(buf); |
ee5d122f | 136 | } |
137 | } | |
138 | ||
139 | static void delpeercb(struct dc_fnetpeer *peer) | |
140 | { | |
141 | struct conndata *data; | |
34ec1e2f | 142 | G/PCConversation *conv; |
dc53e482 | 143 | char *buf; |
ee5d122f | 144 | |
145 | data = peer->fn->udata; | |
34ec1e2f | 146 | if((conv = G/P_find_chat(data->gc, peer->fn->id)) != NULL) { |
c17c238e | 147 | buf = sprintf2("%s", icswcstombs(peer->nick, "UTF-8", NULL)); |
34ec1e2f | 148 | G/P_conv_chat_remove_user(G/PU_CONV_CHAT(conv), buf, NULL); |
dc53e482 | 149 | free(buf); |
ee5d122f | 150 | } |
151 | } | |
152 | ||
153 | static void chpeercb(struct dc_fnetpeer *peer) | |
154 | { | |
155 | } | |
156 | ||
157 | static void fillpeerlist(struct dc_fnetnode *fn, int resp, struct conndata *data) | |
158 | { | |
159 | } | |
160 | ||
161 | static void getfnlistcb(int resp, struct conndata *data) | |
162 | { | |
163 | struct dc_fnetnode *fn; | |
164 | ||
165 | for(fn = dc_fnetnodes; fn != NULL; fn = fn->next) | |
166 | { | |
167 | dc_getpeerlistasync(fn, (void (*)(struct dc_fnetnode *, int, void *))fillpeerlist, data); | |
168 | fn->udata = data; | |
169 | fn->newpeercb = newpeercb; | |
170 | fn->delpeercb = delpeercb; | |
171 | fn->chpeercb = chpeercb; | |
172 | } | |
173 | } | |
174 | ||
175 | static void logincb(int err, wchar_t *reason, struct conndata *data) | |
176 | { | |
177 | if(err != DC_LOGIN_ERR_SUCCESS) { | |
178 | dc_disconnect(); | |
179 | disconnected(data); | |
34ec1e2f | 180 | G/P_connection_error(data->gc, "Invalid login"); |
ee5d122f | 181 | return; |
182 | } | |
34ec1e2f | 183 | G/P_connection_set_state(data->gc, G/PU_CONNECTED); |
ee5d122f | 184 | dc_queuecmd(NULL, NULL, L"notify", L"fn:chat", L"on", L"fn:act", L"on", L"fn:peer", L"on", NULL); |
185 | dc_getfnlistasync((void (*)(int, void *))getfnlistcb, data); | |
186 | } | |
187 | ||
34ec1e2f | 188 | static void dcfdcb(struct conndata *data, int fd, G/PCInputCondition condition) |
ee5d122f | 189 | { |
190 | struct dc_response *resp; | |
191 | struct dc_intresp *ires; | |
192 | struct dc_fnetnode *fn; | |
34ec1e2f | 193 | G/PCConversation *conv; |
ee5d122f | 194 | char *peer, *msg; |
195 | ||
34ec1e2f | 196 | if(((condition & G/PU_INPUT_READ) && dc_handleread()) || ((condition & G/PU_INPUT_WRITE) && dc_handlewrite())) { |
ee5d122f | 197 | disconnected(data); |
34ec1e2f | 198 | G/P_connection_error(data->gc, "Server has disconnected"); |
ee5d122f | 199 | return; |
200 | } | |
201 | while((resp = dc_getresp()) != NULL) { | |
202 | if(!wcscmp(resp->cmdname, L".connect")) { | |
5e1e52f1 | 203 | if(resp->code != 201) { |
ee5d122f | 204 | dc_disconnect(); |
205 | disconnected(data); | |
34ec1e2f | 206 | G/P_connection_error(data->gc, "Server refused connection"); |
ee5d122f | 207 | return; |
5e1e52f1 | 208 | } else if(dc_checkprotocol(resp, DC_LATEST)) { |
209 | dc_disconnect(); | |
210 | disconnected(data); | |
34ec1e2f | 211 | G/P_connection_error(data->gc, "Server protocol revision mismatch"); |
5e1e52f1 | 212 | return; |
213 | } else { | |
34ec1e2f | 214 | G/P_connection_update_progress(data->gc, "Authenticating", 2, 3); |
5e1e52f1 | 215 | dc_loginasync(NULL, 1, (int (*)(int, wchar_t *, char **, void *))loginconv, (void (*)(int, wchar_t *, void *))logincb, data); |
ee5d122f | 216 | } |
217 | } else if(!wcscmp(resp->cmdname, L".notify")) { | |
218 | dc_uimisc_handlenotify(resp); | |
219 | switch(resp->code) { | |
220 | case 600: | |
221 | if((ires = dc_interpret(resp)) != NULL) | |
222 | { | |
223 | if((fn = dc_findfnetnode(ires->argv[0].val.num)) != NULL) | |
224 | { | |
225 | if(ires->argv[1].val.num) | |
226 | { | |
227 | /* XXX: Handle different rooms */ | |
34ec1e2f | 228 | if((conv = G/P_find_chat(data->gc, fn->id)) != NULL) |
ee5d122f | 229 | { |
230 | peer = icwcstombs(ires->argv[3].val.str, "UTF-8"); | |
d5e00af4 | 231 | msg = g_markup_escape_text(icswcstombs(ires->argv[4].val.str, "UTF-8", NULL), -1); |
34ec1e2f | 232 | serv_got_chat_in(data->gc, G/P_conv_chat_get_id(G/PU_CONV_CHAT(conv)), peer, 0, msg, time(NULL)); |
d5e00af4 | 233 | g_free(msg); |
ee5d122f | 234 | free(peer); |
235 | } | |
236 | } else { | |
dc53e482 | 237 | peer = sprintf2("%i:%s", fn->id, icswcstombs(ires->argv[3].val.str, "UTF-8", NULL)); |
d5e00af4 | 238 | msg = g_markup_escape_text(icswcstombs(ires->argv[4].val.str, "UTF-8", NULL), -1); |
34ec1e2f | 239 | if(!G/P_account_get_bool(data->gc->account, "represspm", FALSE) || (G/P_find_conversation_with_account(G/PU_CONV_TYPE_IM, peer, data->gc->account) != NULL)) |
ee5d122f | 240 | serv_got_im(data->gc, peer, msg, 0, time(NULL)); |
d5e00af4 | 241 | g_free(msg); |
ee5d122f | 242 | free(peer); |
243 | } | |
244 | } | |
245 | dc_freeires(ires); | |
246 | } | |
247 | break; | |
248 | case 601: | |
249 | case 602: | |
250 | case 603: | |
dc53e482 | 251 | break; |
ee5d122f | 252 | case 604: |
253 | if((ires = dc_interpret(resp)) != NULL) | |
254 | { | |
255 | if((fn = dc_findfnetnode(ires->argv[0].val.num)) != NULL) | |
256 | { | |
257 | fn->udata = data; | |
258 | fn->newpeercb = newpeercb; | |
259 | fn->delpeercb = delpeercb; | |
260 | fn->chpeercb = chpeercb; | |
261 | } | |
262 | dc_freeires(ires); | |
263 | } | |
dc53e482 | 264 | break; |
ee5d122f | 265 | case 605: |
266 | break; | |
267 | } | |
268 | } | |
17221b02 | 269 | dc_freeresp(resp); |
ee5d122f | 270 | } |
271 | updatewrite(data); | |
272 | } | |
273 | ||
34ec1e2f | 274 | static int gi_sendchat(G/PCConnection *gc, int id, const char *what, G/PCMessageFlags flags) |
ee5d122f | 275 | { |
276 | struct conndata *data; | |
277 | struct dc_fnetnode *fn; | |
278 | wchar_t *wwhat; | |
279 | ||
280 | data = gc->proto_data; | |
281 | if((fn = dc_findfnetnode(id)) == NULL) | |
282 | return(-EINVAL); | |
283 | /* XXX: Handle chat rooms */ | |
284 | if((wwhat = icmbstowcs((char *)what, "UTF-8")) == NULL) | |
285 | return(-errno); | |
0931eb36 | 286 | dc_queuecmd(NULL, NULL, L"sendchat", L"%i", fn->id, L"1", L"", L"%ls", wwhat, NULL); |
ee5d122f | 287 | free(wwhat); |
288 | updatewrite(data); | |
289 | return(0); | |
290 | } | |
291 | ||
34ec1e2f | 292 | static int gi_sendim(G/PCConnection *gc, const char *who, const char *what, G/PCMessageFlags flags) |
ee5d122f | 293 | { |
294 | struct conndata *data; | |
dc53e482 | 295 | struct dc_fnetnode *fn; |
296 | struct dc_fnetpeer *peer; | |
297 | wchar_t *wwho, *wwhat, *p; | |
298 | int en, id; | |
ee5d122f | 299 | |
300 | data = gc->proto_data; | |
301 | if((wwho = icmbstowcs((char *)who, "UTF-8")) == NULL) | |
302 | return(-errno); | |
dc53e482 | 303 | if((p = wcschr(wwho, L':')) == NULL) { |
304 | free(wwho); | |
305 | return(-ESRCH); | |
306 | } | |
307 | *(p++) = L'\0'; | |
308 | id = wcstol(wwho, NULL, 10); | |
309 | if((fn = dc_findfnetnode(id)) == NULL) { | |
310 | free(wwho); | |
311 | return(-ESRCH); | |
ee5d122f | 312 | } |
dc53e482 | 313 | for(peer = fn->peers; peer != NULL; peer = peer->next) { |
314 | if(!wcscmp(peer->nick, p)) | |
315 | break; | |
316 | } | |
317 | if(peer == NULL) { | |
ee5d122f | 318 | free(wwho); |
319 | return(-ESRCH); | |
320 | } | |
321 | if((wwhat = icmbstowcs((char *)what, "UTF-8")) == NULL) { | |
322 | en = errno; | |
323 | free(wwho); | |
324 | return(-en); | |
325 | } | |
0931eb36 | 326 | dc_queuecmd(NULL, NULL, L"sendchat", L"%i", fn->id, L"0", L"%ls", peer->nick, L"%ls", wwhat, NULL); |
ee5d122f | 327 | free(wwho); |
328 | free(wwhat); | |
329 | updatewrite(data); | |
330 | return(1); | |
331 | } | |
332 | ||
34ec1e2f | 333 | static const char *gi_listicon(G/PCAccount *a, G/PCBuddy *b) |
ee5d122f | 334 | { |
335 | return("dolcon"); | |
336 | } | |
337 | ||
34ec1e2f | 338 | static char *gi_statustext(G/PCBuddy *b) |
7f6ee5df | 339 | { |
34ec1e2f | 340 | G/PCPresence *p; |
7f6ee5df | 341 | |
34ec1e2f FT |
342 | p = G/P_buddy_get_presence(b); |
343 | if (G/P_presence_is_online(p) && !G/P_presence_is_available(p)) | |
7f6ee5df | 344 | return(g_strdup("Away")); |
345 | return(NULL); | |
346 | } | |
347 | ||
34ec1e2f | 348 | static void gi_tiptext(G/PCBuddy *b, G/PCNotifyUserInfo *inf, gboolean full) |
7f6ee5df | 349 | { |
350 | /* Nothing for now */ | |
351 | } | |
352 | ||
34ec1e2f | 353 | static GList *gi_statustypes(G/PCAccount *act) |
7f6ee5df | 354 | { |
355 | GList *ret; | |
356 | ||
357 | ret = NULL; | |
34ec1e2f FT |
358 | ret = g_list_append(ret, G/P_status_type_new(G/PU_STATUS_AVAILABLE, "avail", NULL, TRUE)); |
359 | ret = g_list_append(ret, G/P_status_type_new(G/PU_STATUS_AWAY, "away", NULL, TRUE)); /* Coming up in ADC */ | |
360 | ret = g_list_append(ret, G/P_status_type_new(G/PU_STATUS_OFFLINE, "offline", NULL, TRUE)); | |
7f6ee5df | 361 | return(ret); |
362 | } | |
363 | ||
ee5d122f | 364 | static struct conndata *newconndata(void) |
365 | { | |
366 | struct conndata *new; | |
367 | ||
368 | new = smalloc(sizeof(*new)); | |
369 | memset(new, 0, sizeof(*new)); | |
370 | new->fd = -1; | |
371 | new->readhdl = new->writehdl = -1; | |
372 | return(new); | |
373 | } | |
374 | ||
375 | static void freeconndata(struct conndata *data) | |
376 | { | |
377 | if(data->roomlist != NULL) | |
34ec1e2f | 378 | G/P_roomlist_unref(data->roomlist); |
ee5d122f | 379 | if(inuse == data) |
380 | inuse = NULL; | |
381 | if(data->readhdl != -1) | |
34ec1e2f | 382 | G/P_input_remove(data->readhdl); |
ee5d122f | 383 | if(data->writehdl != -1) |
34ec1e2f | 384 | G/P_input_remove(data->writehdl); |
ee5d122f | 385 | if(data->fd >= 0) |
386 | dc_disconnect(); | |
387 | free(data); | |
388 | } | |
389 | ||
34ec1e2f | 390 | static void gi_login(G/PCAccount *act) |
ee5d122f | 391 | { |
34ec1e2f | 392 | G/PCConnection *gc; |
ee5d122f | 393 | struct conndata *data; |
394 | ||
34ec1e2f | 395 | gc = G/P_account_get_connection(act); |
ee5d122f | 396 | gc->proto_data = data = newconndata(); |
397 | data->gc = gc; | |
398 | if(inuse != NULL) { | |
34ec1e2f | 399 | G/P_connection_error(gc, "Dolda Connect library already in use"); |
ee5d122f | 400 | return; |
401 | } | |
34ec1e2f FT |
402 | G/P_connection_update_progress(gc, "Connecting", 1, 3); |
403 | if((data->fd = dc_connect((char *)G/P_account_get_string(act, "server", "localhost"))) < 0) | |
ee5d122f | 404 | { |
34ec1e2f | 405 | G/P_connection_error(gc, "Could not connect to server"); |
ee5d122f | 406 | return; |
407 | } | |
34ec1e2f | 408 | data->readhdl = G/P_input_add(data->fd, G/PU_INPUT_READ, (void (*)(void *, int, G/PCInputCondition))dcfdcb, data); |
ee5d122f | 409 | updatewrite(data); |
410 | inuse = data; | |
411 | } | |
412 | ||
34ec1e2f | 413 | static void gi_close(G/PCConnection *gc) |
ee5d122f | 414 | { |
415 | struct conndata *data; | |
416 | ||
417 | data = gc->proto_data; | |
418 | freeconndata(data); | |
419 | } | |
420 | ||
34ec1e2f | 421 | static G/PCRoomlist *gi_getlist(G/PCConnection *gc) |
ee5d122f | 422 | { |
423 | struct conndata *data; | |
424 | GList *fields; | |
34ec1e2f FT |
425 | G/PCRoomlist *rl; |
426 | G/PCRoomlistField *f; | |
427 | G/PCRoomlistRoom *r; | |
ee5d122f | 428 | struct dc_fnetnode *fn; |
429 | ||
430 | data = gc->proto_data; | |
431 | if(data->roomlist != NULL) | |
34ec1e2f FT |
432 | G/P_roomlist_unref(data->roomlist); |
433 | data->roomlist = rl = G/P_roomlist_new(G/P_connection_get_account(gc)); | |
ee5d122f | 434 | fields = NULL; |
34ec1e2f | 435 | f = G/P_roomlist_field_new(G/PU_ROOMLIST_FIELD_INT, "", "id", TRUE); |
ee5d122f | 436 | fields = g_list_append(fields, f); |
34ec1e2f | 437 | f = G/P_roomlist_field_new(G/PU_ROOMLIST_FIELD_INT, "Users", "users", FALSE); |
ee5d122f | 438 | fields = g_list_append(fields, f); |
34ec1e2f | 439 | G/P_roomlist_set_fields(rl, fields); |
ee5d122f | 440 | for(fn = dc_fnetnodes; fn != NULL; fn = fn->next) { |
441 | if(fn->state != DC_FNN_STATE_EST) | |
442 | continue; | |
34ec1e2f FT |
443 | r = G/P_roomlist_room_new(G/PU_ROOMLIST_ROOMTYPE_ROOM, icswcstombs(fn->name, "UTF-8", NULL), NULL); |
444 | G/P_roomlist_room_add_field(rl, r, GINT_TO_POINTER(fn->id)); | |
445 | G/P_roomlist_room_add_field(rl, r, GINT_TO_POINTER(fn->numusers)); | |
446 | G/P_roomlist_room_add(rl, r); | |
ee5d122f | 447 | } |
34ec1e2f | 448 | G/P_roomlist_set_in_progress(rl, FALSE); |
ee5d122f | 449 | return(rl); |
450 | } | |
451 | ||
34ec1e2f | 452 | static void gi_cancelgetlist(G/PCRoomlist *rl) |
ee5d122f | 453 | { |
34ec1e2f | 454 | G/PCConnection *gc; |
ee5d122f | 455 | struct conndata *data; |
456 | ||
34ec1e2f | 457 | if((gc = G/P_account_get_connection(rl->account)) == NULL) |
ee5d122f | 458 | return; |
459 | data = gc->proto_data; | |
34ec1e2f | 460 | G/P_roomlist_set_in_progress(rl, FALSE); |
ee5d122f | 461 | if(data->roomlist == rl) { |
462 | data->roomlist = NULL; | |
34ec1e2f | 463 | G/P_roomlist_unref(rl); |
ee5d122f | 464 | } |
465 | } | |
466 | ||
34ec1e2f | 467 | static void gi_joinchat(G/PCConnection *gc, GHashTable *chatdata) |
ee5d122f | 468 | { |
469 | struct conndata *data; | |
470 | struct dc_fnetnode *fn; | |
34ec1e2f | 471 | G/PCConversation *conv; |
dc53e482 | 472 | struct dc_fnetpeer *peer; |
473 | char *buf; | |
7f6ee5df | 474 | GList *ul, *fl, *c; |
ee5d122f | 475 | |
ccb54a17 | 476 | regsigs(); |
ee5d122f | 477 | data = gc->proto_data; |
478 | if((fn = dc_findfnetnode(GPOINTER_TO_INT(g_hash_table_lookup(chatdata, "id")))) == NULL) | |
479 | return; | |
34ec1e2f | 480 | if(G/P_find_chat(gc, fn->id) != NULL) |
ee5d122f | 481 | return; |
dc53e482 | 482 | conv = serv_got_joined_chat(data->gc, fn->id, icswcstombs(fn->name, "UTF-8", NULL)); |
7f6ee5df | 483 | ul = fl = NULL; |
dc53e482 | 484 | for(peer = fn->peers; peer != NULL; peer = peer->next) { |
d5e00af4 | 485 | buf = icwcstombs(peer->nick, "UTF-8"); |
7f6ee5df | 486 | ul = g_list_append(ul, buf); |
487 | fl = g_list_append(fl, GINT_TO_POINTER(0)); | |
dc53e482 | 488 | } |
34ec1e2f | 489 | G/P_conv_chat_add_users(G/PU_CONV_CHAT(conv), ul, NULL, fl, FALSE); |
7f6ee5df | 490 | for(c = ul; c != NULL; c = c->next) |
491 | free(c->data); | |
492 | g_list_free(ul); | |
493 | g_list_free(fl); | |
ee5d122f | 494 | } |
495 | ||
34ec1e2f | 496 | static char *gi_cbname(G/PCConnection *gc, int id, const char *who) |
d5e00af4 | 497 | { |
498 | return(g_strdup_printf("%i:%s", id, who)); | |
499 | } | |
500 | ||
34ec1e2f | 501 | static G/PCPluginProtocolInfo protinfo = { |
ee5d122f | 502 | .options = OPT_PROTO_PASSWORD_OPTIONAL, |
503 | .icon_spec = NO_BUDDY_ICONS, | |
504 | .list_icon = gi_listicon, | |
7f6ee5df | 505 | .status_text = gi_statustext, |
506 | .tooltip_text = gi_tiptext, | |
507 | .status_types = gi_statustypes, | |
ee5d122f | 508 | .login = gi_login, |
509 | .close = gi_close, | |
510 | .roomlist_get_list = gi_getlist, | |
511 | .roomlist_cancel = gi_cancelgetlist, | |
512 | .join_chat = gi_joinchat, | |
513 | .chat_send = gi_sendchat, | |
514 | .send_im = gi_sendim, | |
d5e00af4 | 515 | .get_cb_real_name = gi_cbname, |
ee5d122f | 516 | }; |
517 | ||
34ec1e2f FT |
518 | static G/PCPluginInfo info = { |
519 | .magic = G/PU_PLUGIN_MAGIC, | |
520 | .major_version = G/PU_MAJOR_VERSION, | |
521 | .minor_version = G/PU_MINOR_VERSION, | |
522 | .type = G/PU_PLUGIN_PROTOCOL, | |
523 | .priority = G/PU_PRIORITY_DEFAULT, | |
ee5d122f | 524 | .id = "prpl-dolcon", |
525 | .name = "Dolda Connect", | |
526 | .version = VERSION, | |
527 | .summary = "Dolda Connect chat plugin", | |
34ec1e2f | 528 | .description = "Allows G/PC to be used as a chat user interface for the Dolda Connect daemon", |
ee5d122f | 529 | .author = "Fredrik Tolf <fredrik@dolda2000.com>", |
530 | .homepage = "http://www.dolda2000.com/~fredrik/doldaconnect/", | |
531 | .extra_info = &protinfo | |
532 | }; | |
533 | ||
34ec1e2f | 534 | static void init(G/PCPlugin *pl) |
ee5d122f | 535 | { |
34ec1e2f | 536 | G/PCAccountOption *opt; |
ee5d122f | 537 | |
538 | dc_init(); | |
34ec1e2f | 539 | opt = G/P_account_option_string_new("Server", "server", ""); |
ee5d122f | 540 | protinfo.protocol_options = g_list_append(protinfo.protocol_options, opt); |
34ec1e2f | 541 | opt = G/P_account_option_bool_new("Do not pop up private messages automatically", "represspm", FALSE); |
ee5d122f | 542 | protinfo.protocol_options = g_list_append(protinfo.protocol_options, opt); |
649eeeb6 | 543 | me = pl; |
ee5d122f | 544 | } |
545 | ||
34ec1e2f | 546 | G/PU_INIT_PLUGIN(dolcon, init, info); |