1152
|
1 #include <gtk/gtk.h>
|
|
2 #include "icq.h" /* well, we're doing ICQ, right? */
|
|
3 #include "multi.h" /* needed for gaim_connection */
|
|
4 #include "prpl.h" /* needed for prpl */
|
|
5 #include "gaim.h" /* needed for every other damn thing */
|
|
6
|
|
7 struct icq_data {
|
|
8 ICQLINK *link;
|
|
9 int cur_status;
|
|
10 int tcp_timer;
|
|
11 int ack_timer;
|
|
12 };
|
|
13
|
|
14 static struct gaim_connection *find_gaim_conn_by_icq_link(ICQLINK *link) {
|
|
15 GSList *c = connections;
|
|
16 struct gaim_connection *gc = NULL;
|
|
17 struct icq_data *id;
|
|
18
|
|
19 while (c) {
|
|
20 gc = (struct gaim_connection *)c->data;
|
|
21 if (gc->protocol == PROTO_ICQ) {
|
|
22 id = (struct icq_data *)gc->proto_data;
|
|
23 if (id->link == link)
|
|
24 break;
|
|
25 }
|
|
26 gc = NULL;
|
|
27 c = c->next;
|
|
28 }
|
|
29
|
|
30 return gc;
|
|
31 }
|
|
32
|
|
33 static char *icq_name() {
|
|
34 return "ICQ";
|
|
35 }
|
|
36
|
|
37 static void icq_do_log(ICQLINK *link, time_t time, unsigned char level, const char *log) {
|
|
38 debug_printf("ICQ debug %d: %s", level, log);
|
|
39 }
|
|
40
|
|
41 static gint icq_tcp_timer(ICQLINK *link) {
|
|
42 icq_TCPMain(link);
|
|
43 return TRUE;
|
|
44 }
|
|
45
|
|
46 static void icq_callback(gpointer data, gint source, GdkInputCondition condition) {
|
|
47 struct gaim_connection *gc = (struct gaim_connection *)data;
|
|
48 struct icq_data *id = (struct icq_data *)gc->proto_data;
|
|
49 debug_printf("ICQ Callback handler\n");
|
|
50
|
|
51 icq_HandleServerResponse(id->link);
|
|
52 }
|
|
53
|
|
54 static void icq_online(ICQLINK *link) {
|
|
55 struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
|
|
56 struct icq_data *id = (struct icq_data *)gc->proto_data;
|
|
57 debug_printf("%s is now online.\n", gc->username);
|
|
58 account_online(gc);
|
|
59 serv_finish_login(gc);
|
|
60
|
|
61 if (bud_list_cache_exists(gc))
|
|
62 do_import(NULL, gc);
|
|
63
|
|
64 icq_ChangeStatus(id->link, STATUS_ONLINE);
|
|
65 }
|
|
66
|
|
67 static void icq_logged_off(ICQLINK *link) {
|
|
68 struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
|
|
69 struct icq_data *id = (struct icq_data *)gc->proto_data;
|
|
70 int icqSocket;
|
|
71
|
|
72 gtk_timeout_remove(id->tcp_timer);
|
|
73 gdk_input_remove(gc->inpa);
|
|
74
|
|
75 if (icq_Connect(link, "icq.mirabilis.com", 4000) < 1) {
|
|
76 hide_login_progress(gc, "Unable to connect");
|
|
77 g_free(id);
|
|
78 signoff(gc);
|
|
79 return;
|
|
80 }
|
|
81
|
|
82 icqSocket = icq_GetSok(link);
|
|
83 gc->inpa = gdk_input_add(icqSocket, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, icq_callback, gc);
|
|
84
|
|
85 icq_Login(link, STATUS_ONLINE);
|
|
86 id->cur_status = STATUS_ONLINE;
|
|
87
|
|
88 id->tcp_timer = gtk_timeout_add(100, (GtkFunction)icq_tcp_timer, link);
|
|
89 }
|
|
90
|
|
91 static void icq_msg_incoming(ICQLINK *link, unsigned long uin, unsigned char hour, unsigned char minute,
|
|
92 unsigned char day, unsigned char month, unsigned short year, const char *data) {
|
|
93 struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
|
|
94 char buf[256], *tmp = g_strdup(data);
|
|
95 g_snprintf(buf, sizeof buf, "%lu", uin);
|
|
96 serv_got_im(gc, buf, tmp, 0);
|
|
97 g_free(tmp);
|
|
98 }
|
|
99
|
|
100 static void icq_user_online(ICQLINK *link, unsigned long uin, unsigned long status,
|
|
101 unsigned long ip, unsigned short port, unsigned long real_ip,
|
|
102 unsigned char tcp_flags) {
|
|
103 struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
|
|
104 char buf[256]; g_snprintf(buf, sizeof buf, "%lu", uin);
|
|
105 serv_got_update(gc, buf, 1, 0, 0, 0, (status==STATUS_ONLINE) ? UC_NORMAL : UC_UNAVAILABLE, 0);
|
|
106 }
|
|
107
|
|
108 static void icq_user_offline(ICQLINK *link, unsigned long uin) {
|
|
109 struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
|
|
110 char buf[256]; g_snprintf(buf, sizeof buf, "%lu", uin);
|
|
111 serv_got_update(gc, buf, 0, 0, 0, 0, 0, 0);
|
|
112 }
|
|
113
|
|
114 static void icq_user_status(ICQLINK *link, unsigned long uin, unsigned long status) {
|
|
115 struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
|
|
116 char buf[256]; g_snprintf(buf, sizeof buf, "%lu", uin);
|
|
117 serv_got_update(gc, buf, 1, 0, 0, 0, (status==STATUS_ONLINE) ? UC_NORMAL : UC_UNAVAILABLE, 0);
|
|
118 }
|
|
119
|
|
120 static gint icq_set_timeout_cb(struct icq_data *id) {
|
|
121 icq_HandleTimeout(id->link);
|
|
122 id->ack_timer = -1;
|
|
123 return FALSE;
|
|
124 }
|
|
125
|
|
126 static void icq_set_timeout(ICQLINK *link, long interval) {
|
|
127 struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
|
|
128 struct icq_data *id = (struct icq_data *)gc->proto_data;
|
|
129
|
|
130 debug_printf("icq_SetTimeout: %ld\n", interval);
|
|
131 if (interval > 0 && id->ack_timer < 1)
|
|
132 id->ack_timer = gtk_timeout_add(interval * 1000, (GtkFunction)icq_set_timeout_cb, id);
|
|
133 else if (id->ack_timer > 0) {
|
|
134 gtk_timeout_remove(id->ack_timer);
|
|
135 id->ack_timer = -1;
|
|
136 }
|
|
137 }
|
|
138
|
|
139 static void icq_url_incoming(struct icq_link *link, unsigned long uin, unsigned char hour,
|
|
140 unsigned char minute, unsigned char day, unsigned char month,
|
|
141 unsigned short year, const char *url, const char *descr) {
|
|
142 struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
|
|
143 int len = strlen(url) + strlen(descr) + 25; /* 25 is straight out of my ass */
|
|
144 char *msg = g_malloc(len), buf[256];
|
|
145 g_snprintf(msg, len, "<A HREF=\"%s\">%s</A>", url, descr);
|
|
146 g_snprintf(buf, 256, "%lu", uin);
|
|
147 serv_got_im(gc, buf, msg, 0);
|
|
148 g_free(msg);
|
|
149 }
|
|
150
|
|
151 static void icq_wrong_passwd(struct icq_link *link) {
|
|
152 struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
|
|
153 hide_login_progress(gc, "Invalid password.");
|
|
154 signoff(gc);
|
|
155 }
|
|
156
|
|
157 static void icq_invalid_uin(struct icq_link *link) {
|
|
158 struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
|
|
159 hide_login_progress(gc, "Invalid UIN.");
|
|
160 signoff(gc);
|
|
161 }
|
|
162
|
|
163 static void icq_login(struct aim_user *user) {
|
|
164 struct gaim_connection *gc = new_gaim_conn(user);
|
|
165 struct icq_data *id = gc->proto_data = g_new0(struct icq_data, 1);
|
|
166 ICQLINK *link = id->link = g_new0(ICQLINK, 1);
|
|
167 int icqSocket;
|
|
168
|
|
169 icq_LogLevel = ICQ_LOG_MESSAGE;
|
|
170
|
|
171 icq_Init(link, atol(user->username), user->password, "gaim user" /* hehe :) */);
|
|
172
|
|
173 link->icq_Logged = icq_online;
|
|
174 link->icq_Disconnected = icq_logged_off;
|
|
175 link->icq_RecvMessage = icq_msg_incoming;
|
|
176 link->icq_RecvURL = icq_url_incoming;
|
|
177 link->icq_UserOnline = icq_user_online;
|
|
178 link->icq_UserOffline = icq_user_offline;
|
|
179 link->icq_UserStatusUpdate = icq_user_status;
|
|
180 link->icq_WrongPassword = icq_wrong_passwd;
|
|
181 link->icq_InvalidUIN = icq_invalid_uin;
|
|
182 link->icq_Log = icq_do_log;
|
|
183 link->icq_SetTimeout = icq_set_timeout;
|
|
184
|
|
185 icq_UnsetProxy(link);
|
|
186
|
|
187 if (icq_Connect(link, "icq.mirabilis.com", 4000) < 1) {
|
|
188 hide_login_progress(gc, "Unable to connect");
|
|
189 g_free(id);
|
|
190 signoff(gc);
|
|
191 return;
|
|
192 }
|
|
193
|
|
194 icqSocket = icq_GetSok(link);
|
|
195 gc->inpa = gdk_input_add(icqSocket, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, icq_callback, gc);
|
|
196
|
|
197 icq_Login(link, STATUS_ONLINE);
|
|
198 id->cur_status = STATUS_ONLINE;
|
|
199
|
|
200 id->tcp_timer = gtk_timeout_add(100, (GtkFunction)icq_tcp_timer, link);
|
|
201
|
|
202 set_login_progress(gc, 0, "Connecting...");
|
|
203 }
|
|
204
|
|
205 static void icq_close(struct gaim_connection *gc) {
|
|
206 struct icq_data *id = (struct icq_data *)gc->proto_data;
|
|
207
|
|
208 gtk_timeout_remove(id->tcp_timer);
|
|
209 gdk_input_remove(gc->inpa);
|
|
210 icq_Logout(id->link);
|
|
211 icq_Disconnect(id->link);
|
|
212 icq_Done(id->link);
|
|
213 g_free(id->link);
|
|
214 }
|
|
215
|
|
216 static struct prpl *my_protocol = NULL;
|
|
217
|
|
218 static void icq_send_msg(struct gaim_connection *gc, char *who, char *msg, int away) {
|
|
219 struct icq_data *id = (struct icq_data *)gc->proto_data;
|
|
220 icq_SendMessage(id->link, atol(who), msg, !away);
|
|
221 }
|
|
222
|
|
223 static void icq_keepalive(struct gaim_connection *gc) {
|
|
224 struct icq_data *id = (struct icq_data *)gc->proto_data;
|
|
225 icq_KeepAlive(id->link);
|
|
226 }
|
|
227
|
|
228 static void icq_add_buddy(struct gaim_connection *gc, char *who) {
|
|
229 struct icq_data *id = (struct icq_data *)gc->proto_data;
|
|
230 icq_ContactAdd(id->link, atol(who));
|
|
231 icq_ContactSetVis(id->link, atol(who), TRUE);
|
|
232 icq_SendNewUser(id->link, atol(who));
|
|
233 }
|
|
234
|
|
235 static void icq_add_buddies(struct gaim_connection *gc, GList *whos) {
|
|
236 struct icq_data *id = (struct icq_data *)gc->proto_data;
|
|
237 while (whos) {
|
|
238 icq_ContactAdd(id->link, atol(whos->data));
|
|
239 icq_ContactSetVis(id->link, atol(whos->data), TRUE);
|
|
240 icq_SendNewUser(id->link, atol(whos->data));
|
|
241 whos = whos->next;
|
|
242 }
|
|
243 }
|
|
244
|
|
245 static void icq_rem_buddy(struct gaim_connection *gc, char *who) {
|
|
246 struct icq_data *id = (struct icq_data *)gc->proto_data;
|
|
247 icq_ContactRemove(id->link, atol(who));
|
|
248 }
|
|
249
|
|
250 static void icq_set_away(struct gaim_connection *gc, char *msg) {
|
|
251 struct icq_data *id = (struct icq_data *)gc->proto_data;
|
|
252
|
|
253 if (msg && msg[0]) {
|
|
254 icq_ChangeStatus(id->link, STATUS_NA);
|
|
255 } else {
|
|
256 icq_ChangeStatus(id->link, STATUS_ONLINE);
|
|
257 }
|
|
258 }
|
|
259
|
|
260 static void icq_init(struct prpl *ret) {
|
|
261 ret->protocol = PROTO_ICQ;
|
|
262 ret->name = icq_name;
|
|
263 ret->login = icq_login;
|
|
264 ret->close = icq_close;
|
|
265 ret->send_im = icq_send_msg;
|
|
266 ret->add_buddy = icq_add_buddy;
|
|
267 ret->add_buddies = icq_add_buddies;
|
|
268 ret->remove_buddy = icq_rem_buddy;
|
|
269 ret->set_away = icq_set_away;
|
|
270 ret->keepalive = icq_keepalive;
|
|
271
|
|
272 my_protocol = ret;
|
|
273 }
|
|
274
|
|
275 char *gaim_plugin_init(GModule *handle) {
|
|
276 load_protocol(icq_init);
|
|
277 return NULL;
|
|
278 }
|
|
279
|
|
280 void gaim_plugin_remove() {
|
|
281 struct prpl *p = find_prpl(PROTO_ICQ);
|
|
282 if (p == my_protocol)
|
|
283 unload_protocol(p);
|
|
284 }
|
|
285
|
|
286 char *name() {
|
|
287 return "ICQ";
|
|
288 }
|
|
289
|
|
290 char *description() {
|
|
291 return "Allows gaim to use the ICQ protocol";
|
|
292 }
|