1 /* $Id: pubdir50.c,v 1.1 2004/01/26 23:49:54 konst Exp $ */
4 * (C) Copyright 2003 Wojtek Kaniewski <wojtekka@irc.pl>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License Version
8 * 2.1 as published by the Free Software Foundation.
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 Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 * tworzy now± zmienn± typu gg_pubdir50_t.
32 * zaalokowana zmienna lub NULL w przypadku braku pamiêci.
34 gg_pubdir50_t
gg_pubdir50_new(int type
)
36 gg_pubdir50_t res
= malloc(sizeof(struct gg_pubdir50_s
));
38 gg_debug(GG_DEBUG_FUNCTION
, "** gg_pubdir50_new(%d);\n", type
);
41 gg_debug(GG_DEBUG_MISC
, "// gg_pubdir50_new() out of memory\n");
45 memset(res
, 0, sizeof(struct gg_pubdir50_s
));
53 * gg_pubdir50_add_n() // funkcja wewnêtrzna
55 * funkcja dodaje lub zastêpuje istniej±ce pole do zapytania lub odpowiedzi.
57 * - req - wska¼nik opisu zapytania,
58 * - num - numer wyniku (0 dla zapytania),
59 * - field - nazwa pola,
60 * - value - warto¶æ pola,
64 int gg_pubdir50_add_n(gg_pubdir50_t req
, int num
, const char *field
, const char *value
)
66 struct gg_pubdir50_entry
*tmp
= NULL
, *entry
;
67 char *dupfield
, *dupvalue
;
70 gg_debug(GG_DEBUG_FUNCTION
, "** gg_pubdir50_add_n(%p, %d, \"%s\", \"%s\");\n", req
, num
, field
, value
);
72 if (!(dupvalue
= strdup(value
))) {
73 gg_debug(GG_DEBUG_MISC
, "// gg_pubdir50_add_n() out of memory\n");
77 for (i
= 0; i
< req
->entries_count
; i
++) {
78 if (req
->entries
[i
].num
!= num
|| strcmp(req
->entries
[i
].field
, field
))
81 free(req
->entries
[i
].value
);
82 req
->entries
[i
].value
= dupvalue
;
87 if (!(dupfield
= strdup(field
))) {
88 gg_debug(GG_DEBUG_MISC
, "// gg_pubdir50_add_n() out of memory\n");
93 if (!(tmp
= realloc(req
->entries
, sizeof(struct gg_pubdir50_entry
) * (req
->entries_count
+ 1)))) {
94 gg_debug(GG_DEBUG_MISC
, "// gg_pubdir50_add_n() out of memory\n");
102 entry
= &req
->entries
[req
->entries_count
];
104 entry
->field
= dupfield
;
105 entry
->value
= dupvalue
;
107 req
->entries_count
++;
115 * funkcja dodaje pole do zapytania.
117 * - req - wska¼nik opisu zapytania,
118 * - field - nazwa pola,
119 * - value - warto¶æ pola,
123 int gg_pubdir50_add(gg_pubdir50_t req
, const char *field
, const char *value
)
125 return gg_pubdir50_add_n(req
, 0, field
, value
);
129 * gg_pubdir50_seq_set()
131 * ustawia numer sekwencyjny zapytania.
134 * - seq - nowy numer sekwencyjny.
138 int gg_pubdir50_seq_set(gg_pubdir50_t req
, uint32_t seq
)
140 gg_debug(GG_DEBUG_FUNCTION
, "** gg_pubdir50_seq_set(%p, %d);\n", req
, seq
);
143 gg_debug(GG_DEBUG_MISC
, "// gg_pubdir50_seq_set() invalid arguments\n");
156 * zwalnia pamiêæ po zapytaniu lub rezultacie szukania u¿ytkownika.
158 * - s - zwalniana zmienna,
160 void gg_pubdir50_free(gg_pubdir50_t s
)
167 for (i
= 0; i
< s
->entries_count
; i
++) {
168 free(s
->entries
[i
].field
);
169 free(s
->entries
[i
].value
);
179 * wysy³a zapytanie katalogu publicznego do serwera.
184 * numer sekwencyjny wyszukiwania lub 0 w przypadku b³êdu.
186 uint32_t gg_pubdir50(struct gg_session
*sess
, gg_pubdir50_t req
)
191 struct gg_pubdir50_request
*r
;
193 gg_debug(GG_DEBUG_FUNCTION
, "** gg_pubdir50(%p, %p);\n", sess
, req
);
196 gg_debug(GG_DEBUG_MISC
, "// gg_pubdir50() invalid arguments\n");
201 if (sess
->state
!= GG_STATE_CONNECTED
) {
202 gg_debug(GG_DEBUG_MISC
, "// gg_pubdir50() not connected\n");
207 for (i
= 0; i
< req
->entries_count
; i
++) {
208 /* wyszukiwanie bierze tylko pierwszy wpis */
209 if (req
->entries
[i
].num
)
212 size
+= strlen(req
->entries
[i
].field
) + 1;
213 size
+= strlen(req
->entries
[i
].value
) + 1;
216 if (!(buf
= malloc(size
))) {
217 gg_debug(GG_DEBUG_MISC
, "// gg_pubdir50() out of memory (%d bytes)\n", size
);
221 r
= (struct gg_pubdir50_request
*) buf
;
224 r
->seq
= (req
->seq
) ? gg_fix32(req
->seq
) : gg_fix32(time(NULL
));
225 req
->seq
= gg_fix32(r
->seq
);
227 for (i
= 0, p
= buf
+ 5; i
< req
->entries_count
; i
++) {
228 if (req
->entries
[i
].num
)
231 strcpy(p
, req
->entries
[i
].field
);
234 strcpy(p
, req
->entries
[i
].value
);
238 if (gg_send_packet(sess
, GG_PUBDIR50_REQUEST
, buf
, size
, NULL
, 0) == -1)
247 * gg_pubdir50_handle_reply() // funkcja wewnêtrzna
249 * analizuje przychodz±cy pakiet odpowiedzi i zapisuje wynik w struct gg_event.
251 * - e - opis zdarzenia
252 * - packet - zawarto¶æ pakietu odpowiedzi
253 * - length - d³ugo¶æ pakietu odpowiedzi
257 int gg_pubdir50_handle_reply(struct gg_event
*e
, const char *packet
, int length
)
259 const char *end
= packet
+ length
, *p
;
260 struct gg_pubdir50_reply
*r
= (struct gg_pubdir50_reply
*) packet
;
264 gg_debug(GG_DEBUG_FUNCTION
, "** gg_pubdir50_handle_reply(%p, %p, %d);\n", e
, packet
, length
);
267 gg_debug(GG_DEBUG_MISC
, "// gg_pubdir50_handle_reply() invalid arguments\n");
273 gg_debug(GG_DEBUG_MISC
, "// gg_pubdir50_handle_reply() packet too short\n");
278 if (!(res
= gg_pubdir50_new(r
->type
))) {
279 gg_debug(GG_DEBUG_MISC
, "// gg_pubdir50_handle_reply() unable to allocate reply\n");
283 e
->event
.pubdir50
= res
;
285 res
->seq
= gg_fix32(r
->seq
);
288 case GG_PUBDIR50_READ
:
289 e
->type
= GG_EVENT_PUBDIR50_READ
;
292 case GG_PUBDIR50_WRITE
:
293 e
->type
= GG_EVENT_PUBDIR50_WRITE
;
297 e
->type
= GG_EVENT_PUBDIR50_SEARCH_REPLY
;
305 /* pomiñ pocz±tek odpowiedzi */
309 const char *field
, *value
;
313 /* sprawd¼, czy nie mamy podzia³u na kolejne pole */
321 for (p
= field
; p
< end
; p
++) {
322 /* je¶li mamy koniec tekstu... */
324 /* ...i jeszcze nie mieli¶my warto¶ci pola to
325 * wiemy, ¿e po tym zerze jest warto¶æ... */
329 /* ...w przeciwym wypadku koniec
330 * warto¶ci i mo¿emy wychodziæ
331 * grzecznie z pêtli */
336 /* sprawd¼my, czy pole nie wychodzi poza pakiet, ¿eby nie
337 * mieæ segfaultów, je¶li serwer przestanie zakañczaæ pakietów
341 gg_debug(GG_DEBUG_MISC
, "// gg_pubdir50_handle_reply() premature end of packet\n");
347 /* je¶li dostali¶my namier na nastêpne wyniki, to znaczy ¿e
348 * mamy koniec wyników i nie jest to kolejna osoba. */
349 if (!strcasecmp(field
, "nextstart")) {
350 res
->next
= atoi(value
);
353 if (gg_pubdir50_add_n(res
, num
, field
, value
) == -1)
358 res
->count
= num
+ 1;
363 gg_pubdir50_free(res
);
370 * pobiera informacjê z rezultatu wyszukiwania.
372 * - res - rezultat wyszukiwania,
373 * - num - numer odpowiedzi,
374 * - field - nazwa pola (wielko¶æ liter nie ma znaczenia).
376 * warto¶æ pola lub NULL, je¶li nie znaleziono.
378 const char *gg_pubdir50_get(gg_pubdir50_t res
, int num
, const char *field
)
383 gg_debug(GG_DEBUG_FUNCTION
, "** gg_pubdir50_get(%p, %d, \"%s\");\n", res
, num
, field
);
385 if (!res
|| num
< 0 || !field
) {
386 gg_debug(GG_DEBUG_MISC
, "// gg_pubdir50_get() invalid arguments\n");
391 for (i
= 0; i
< res
->entries_count
; i
++) {
392 if (res
->entries
[i
].num
== num
&& !strcasecmp(res
->entries
[i
].field
, field
)) {
393 value
= res
->entries
[i
].value
;
402 * gg_pubdir50_count()
404 * zwraca ilo¶æ wyników danego zapytania.
408 * ilo¶æ lub -1 w przypadku b³êdu.
410 int gg_pubdir50_count(gg_pubdir50_t res
)
412 return (!res
) ? -1 : res
->count
;
418 * zwraca rodzaj zapytania lub odpowiedzi.
420 * - res - zapytanie lub odpowied¼
422 * ilo¶æ lub -1 w przypadku b³êdu.
424 int gg_pubdir50_type(gg_pubdir50_t res
)
426 return (!res
) ? -1 : res
->type
;
432 * zwraca numer, od którego nale¿y rozpocz±æ kolejne wyszukiwanie, je¶li
433 * zale¿y nam na kolejnych wynikach.
437 * numer lub -1 w przypadku b³êdu.
439 uin_t
gg_pubdir50_next(gg_pubdir50_t res
)
441 return (!res
) ? (unsigned) -1 : res
->next
;
447 * zwraca numer sekwencyjny zapytania lub odpowiedzi.
449 * - res - zapytanie lub odpowied¼
451 * numer lub -1 w przypadku b³êdu.
453 uint32_t gg_pubdir50_seq(gg_pubdir50_t res
)
455 return (!res
) ? (unsigned) -1 : res
->seq
;
460 * c-indentation-style: k&r
462 * indent-tabs-mode: notnil