diff libpurple/protocols/gg/lib/pubdir50.c @ 29995:2292d8896b0b

merged with im.pidgin.pidgin
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Tue, 16 Mar 2010 12:07:06 +0900
parents 4491a662d527 6359fde67f4c
children fa88dc1dcabb
line wrap: on
line diff
--- a/libpurple/protocols/gg/lib/pubdir50.c	Thu Mar 04 15:19:39 2010 +0900
+++ b/libpurple/protocols/gg/lib/pubdir50.c	Tue Mar 16 12:07:06 2010 +0900
@@ -1,4 +1,4 @@
-/* $Id: pubdir50.c 16856 2006-08-19 01:13:25Z evands $ */
+/* $Id: pubdir50.c 854 2009-10-12 21:06:28Z wojtekka $ */
 
 /*
  *  (C) Copyright 2003 Wojtek Kaniewski <wojtekka@irc.pl>
@@ -14,11 +14,15 @@
  *
  *  You should have received a copy of the GNU Lesser General Public
  *  License along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301,
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
  *  USA.
  */
 
-#include "libgadu.h"
+/**
+ * \file pubdir50.c
+ *
+ * \brief Obsługa katalogu publicznego od wersji Gadu-Gadu 5.x
+ */
 
 #include <errno.h>
 #include <stdlib.h>
@@ -26,12 +30,17 @@
 #include <time.h>
 #include <glib.h>
 
-/*
- * gg_pubdir50_new()
+#include "libgadu.h"
+#include "libgadu-internal.h"
+
+/**
+ * Tworzy nowe zapytanie katalogu publicznego.
  *
- * tworzy now± zmienn± typu gg_pubdir50_t.
+ * \param type Rodzaj zapytania
  *
- * zaalokowana zmienna lub NULL w przypadku braku pamięci.
+ * \return Zmienna \c gg_pubdir50_t lub \c NULL w przypadku błędu.
+ *
+ * \ingroup pubdir50
  */
 gg_pubdir50_t gg_pubdir50_new(int type)
 {
@@ -51,17 +60,16 @@
 	return res;
 }
 
-/*
- * gg_pubdir50_add_n()  // funkcja wewnętrzna
- *
- * funkcja dodaje lub zastępuje istniej±ce pole do zapytania lub odpowiedzi.
+/**
+ * \internal Dodaje lub zastępuje pole zapytania lub odpowiedzi katalogu
+ * publicznego.
  *
- *  - req - wskaĽnik opisu zapytania,
- *  - num - numer wyniku (0 dla zapytania),
- *  - field - nazwa pola,
- *  - value - warto¶ć pola,
+ * \param req Zapytanie lub odpowiedĹş
+ * \param num Numer wyniku odpowiedzi (0 dla zapytania)
+ * \param field Nazwa pola
+ * \param value Wartość pola
  *
- * 0/-1
+ * \return 0 jeśli się powiodło, -1 w przypadku błędu
  */
 static int gg_pubdir50_add_n(gg_pubdir50_t req, int num, const char *field, const char *value)
 {
@@ -111,31 +119,31 @@
 	return 0;
 }
 
-/*
- * gg_pubdir50_add()
- *
- * funkcja dodaje pole do zapytania.
+/**
+ * Dodaje pole zapytania.
  *
- *  - req - wskaĽnik opisu zapytania,
- *  - field - nazwa pola,
- *  - value - warto¶ć pola,
+ * \param req Zapytanie
+ * \param field Nazwa pola
+ * \param value Wartość pola
  *
- * 0/-1
+ * \return 0 jeśli się powiodło, -1 w przypadku błędu
+ *
+ * \ingroup pubdir50
  */
 int gg_pubdir50_add(gg_pubdir50_t req, const char *field, const char *value)
 {
 	return gg_pubdir50_add_n(req, 0, field, value);
 }
 
-/*
- * gg_pubdir50_seq_set()
- *
- * ustawia numer sekwencyjny zapytania.
+/**
+ * Ustawia numer sekwencyjny zapytania.
  *
- *  - req - zapytanie,
- *  - seq - nowy numer sekwencyjny.
+ * \param req Zapytanie
+ * \param seq Numer sekwencyjny
  *
- * 0/-1.
+ * \return 0 jeśli się powiodło, -1 w przypadku błędu
+ *
+ * \ingroup pubdir50
  */
 int gg_pubdir50_seq_set(gg_pubdir50_t req, uint32_t seq)
 {
@@ -152,12 +160,12 @@
 	return 0;
 }
 
-/*
- * gg_pubdir50_free()
+/**
+ * Zwalnia zasoby po zapytaniu lub odpowiedzi katalogu publicznego.
  *
- * zwalnia pamięć po zapytaniu lub rezultacie szukania użytkownika.
+ * \param s Zapytanie lub odpowiedĹş
  *
- *  - s - zwalniana zmienna,
+ * \ingroup pubdir50
  */
 void gg_pubdir50_free(gg_pubdir50_t s)
 {
@@ -175,15 +183,15 @@
 	free(s);
 }
 
-/*
- * gg_pubdir50()
- *
- * wysyła zapytanie katalogu publicznego do serwera.
+/**
+ * Wysyła zapytanie katalogu publicznego do serwera.
  *
- *  - sess - sesja,
- *  - req - zapytanie.
+ * \param sess Struktura sesji
+ * \param req Zapytanie
  *
- * numer sekwencyjny wyszukiwania lub 0 w przypadku błędu.
+ * \return Numer sekwencyjny zapytania lub 0 w przypadku błędu
+ *
+ * \ingroup pubdir50
  */
 uint32_t gg_pubdir50(struct gg_session *sess, gg_pubdir50_t req)
 {
@@ -192,16 +200,16 @@
 	char *buf, *p;
 	struct gg_pubdir50_request *r;
 
-	gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50(%p, %p);\n", sess, req);
+	gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_pubdir50(%p, %p);\n", sess, req);
 	
 	if (!sess || !req) {
-		gg_debug(GG_DEBUG_MISC, "// gg_pubdir50() invalid arguments\n");
+		gg_debug_session(sess, GG_DEBUG_MISC, "// gg_pubdir50() invalid arguments\n");
 		errno = EFAULT;
 		return 0;
 	}
 
 	if (sess->state != GG_STATE_CONNECTED) {
-		gg_debug(GG_DEBUG_MISC, "// gg_pubdir50() not connected\n");
+		gg_debug_session(sess, GG_DEBUG_MISC, "// gg_pubdir50() not connected\n");
 		errno = ENOTCONN;
 		return 0;
 	}
@@ -211,30 +219,81 @@
 		if (req->entries[i].num)
 			continue;
 		
-		size += strlen(req->entries[i].field) + 1;
-		size += strlen(req->entries[i].value) + 1;
+		if (sess->encoding == GG_ENCODING_CP1250) {
+			size += strlen(req->entries[i].field) + 1;
+			size += strlen(req->entries[i].value) + 1;
+		} else {
+			char *tmp;
+
+			tmp = gg_utf8_to_cp(req->entries[i].field);
+
+			if (tmp == NULL)
+				return -1;
+
+			size += strlen(tmp) + 1;
+
+			free(tmp);
+
+			tmp = gg_utf8_to_cp(req->entries[i].value);
+
+			if (tmp == NULL)
+				return -1;
+
+			size += strlen(tmp) + 1;
+
+			free(tmp);
+		}
 	}
 
 	if (!(buf = malloc(size))) {
-		gg_debug(GG_DEBUG_MISC, "// gg_pubdir50() out of memory (%d bytes)\n", size);
+		gg_debug_session(sess, GG_DEBUG_MISC, "// gg_pubdir50() out of memory (%d bytes)\n", size);
 		return 0;
 	}
 
+	if (!req->seq)
+		req->seq = time(NULL);
+
+	res = req->seq;
+
 	r = (struct gg_pubdir50_request*) buf;
-	res = time(NULL);
 	r->type = req->type;
-	r->seq = (req->seq) ? gg_fix32(req->seq) : gg_fix32(time(NULL));
-	req->seq = gg_fix32(r->seq);
+	r->seq = gg_fix32(req->seq);
 
 	for (i = 0, p = buf + 5; i < req->entries_count; i++) {
 		if (req->entries[i].num)
 			continue;
 
-		strcpy(p, req->entries[i].field);
-		p += strlen(p) + 1;
+		if (sess->encoding == GG_ENCODING_CP1250) {
+			strcpy(p, req->entries[i].field);
+			p += strlen(p) + 1;
+
+			strcpy(p, req->entries[i].value);
+			p += strlen(p) + 1;
+		} else {
+			char *tmp;
+
+			tmp = gg_utf8_to_cp(req->entries[i].field);
+
+			if (tmp == NULL) {
+				free(buf);
+				return -1;
+			}
 
-		strcpy(p, req->entries[i].value);
-		p += strlen(p) + 1;
+			strcpy(p, tmp);
+			p += strlen(tmp) + 1;
+			free(tmp);
+
+			tmp = gg_utf8_to_cp(req->entries[i].value);
+
+			if (tmp == NULL) {
+				free(buf);
+				return -1;
+			}
+
+			strcpy(p, tmp);
+			p += strlen(tmp) + 1;
+			free(tmp);
+		}
 	}
 
 	if (gg_send_packet(sess, GG_PUBDIR50_REQUEST, buf, size, NULL, 0) == -1)
@@ -246,26 +305,26 @@
 }
 
 /*
- * gg_pubdir50_handle_reply()  // funkcja wewnętrzna
- *
- * analizuje przychodz±cy pakiet odpowiedzi i zapisuje wynik w struct gg_event.
+ * \internal Analizuje przychodzÄ…cy pakiet odpowiedzi i zapisuje wynik
+ * w strukturze \c gg_event.
  *
- *  - e - opis zdarzenia
- *  - packet - zawarto¶ć pakietu odpowiedzi
- *  - length - długo¶ć pakietu odpowiedzi
+ * \param sess Struktura sesji
+ * \param e Struktura zdarzenia
+ * \param packet Pakiet odpowiedzi
+ * \param length Długość pakietu odpowiedzi
  *
- * 0/-1
+ * \return 0 jeśli się powiodło, -1 w przypadku błędu
  */
-int gg_pubdir50_handle_reply(struct gg_event *e, const char *packet, int length)
+int gg_pubdir50_handle_reply_sess(struct gg_session *sess, struct gg_event *e, const char *packet, int length)
 {
 	const char *end = packet + length, *p;
 	struct gg_pubdir50_reply *r = (struct gg_pubdir50_reply*) packet;
 	gg_pubdir50_t res;
 	int num = 0;
 	
-	gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_handle_reply(%p, %p, %d);\n", e, packet, length);
+	gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_handle_reply_sess(%p, %p, %p, %d);\n", sess, e, packet, length);
 
-	if (!e || !packet) {
+	if (!sess || !e || !packet) {
 		gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() invalid arguments\n");
 		errno = EFAULT;
 		return -1;
@@ -300,11 +359,11 @@
 			break;
 	}
 
-	/* brak wyników? */
+	/* brak wynikĂłw? */
 	if (length == 5)
 		return 0;
 
-	/* pomiń pocz±tek odpowiedzi */
+	/* pomiń początek odpowiedzi */
 	p = packet + 5;
 
 	while (p < end) {
@@ -312,7 +371,7 @@
 
 		field = p;
 
-		/* sprawdĽ, czy nie mamy podziału na kolejne pole */
+		/* sprawdź, czy nie mamy podziału na kolejne pole */
 		if (!*field) {
 			num++;
 			field++;
@@ -321,22 +380,22 @@
 		value = NULL;
 		
 		for (p = field; p < end; p++) {
-			/* je¶li mamy koniec tekstu... */
+			/* jeśli mamy koniec tekstu... */
 			if (!*p) {
-				/* ...i jeszcze nie mieli¶my warto¶ci pola to
-				 * wiemy, że po tym zerze jest warto¶ć... */
+				/* ...i jeszcze nie mieliśmy wartości pola to
+				 * wiemy, że po tym zerze jest wartość... */
 				if (!value)
 					value = p + 1;
 				else
 					/* ...w przeciwym wypadku koniec
-					 * warto¶ci i możemy wychodzić
-					 * grzecznie z pętli */
+					 * wartości i możemy wychodzić
+					 * grzecznie z pętli */
 					break;
 			}
 		}
 		
-		/* sprawdĽmy, czy pole nie wychodzi poza pakiet, żeby nie
-		 * mieć segfaultów, je¶li serwer przestanie zakańczać pakietów
+		/* sprawdĹşmy, czy pole nie wychodzi poza pakiet, ĹĽeby nie
+		 * mieć segfaultów, jeśli serwer przestanie zakańczać pakietów
 		 * przez \0 */
 
 		if (p == end) {
@@ -346,14 +405,30 @@
 
 		p++;
 
-		/* je¶li dostali¶my namier na następne wyniki, to znaczy że
-		 * mamy koniec wyników i nie jest to kolejna osoba. */
+		/* jeśli dostaliśmy namier na następne wyniki, to znaczy że
+		 * mamy koniec wynikĂłw i nie jest to kolejna osoba. */
 		if (!strcasecmp(field, "nextstart")) {
 			res->next = atoi(value);
 			num--;
 		} else {
-			if (gg_pubdir50_add_n(res, num, field, value) == -1)
-				goto failure;
+			if (sess->encoding == GG_ENCODING_CP1250) {
+				if (gg_pubdir50_add_n(res, num, field, value) == -1)
+					goto failure;
+			} else {
+				char *tmp;
+
+				tmp = gg_cp_to_utf8(value);
+
+				if (tmp == NULL)
+					goto failure;
+
+				if (gg_pubdir50_add_n(res, num, field, tmp) == -1) {
+					free(tmp);
+					goto failure;
+				}
+
+				free(tmp);
+			}
 		}
 	}	
 
@@ -366,16 +441,16 @@
 	return -1;
 }
 
-/*
- * gg_pubdir50_get()
- *
- * pobiera informację z rezultatu wyszukiwania.
+/**
+ * Pobiera pole z odpowiedzi katalogu publicznego.
  *
- *  - res - rezultat wyszukiwania,
- *  - num - numer odpowiedzi,
- *  - field - nazwa pola (wielko¶ć liter nie ma znaczenia).
+ * \param res OdpowiedĹş
+ * \param num Numer wyniku odpowiedzi
+ * \param field Nazwa pola (wielkość liter nie ma znaczenia)
  *
- * warto¶ć pola lub NULL, je¶li nie znaleziono.
+ * \return Wartość pola lub \c NULL jeśli nie znaleziono
+ *
+ * \ingroup pubdir50
  */
 const char *gg_pubdir50_get(gg_pubdir50_t res, int num, const char *field)
 {
@@ -400,57 +475,61 @@
 	return value;
 }
 
-/*
- * gg_pubdir50_count()
+/**
+ * Zwraca liczbÄ™ wynikĂłw odpowiedzi.
  *
- * zwraca ilo¶ć wyników danego zapytania.
+ * \param res OdpowiedĹş
  *
- *  - res - odpowiedĽ
+ * \return Liczba wyników lub -1 w przypadku błędu
  *
- * ilo¶ć lub -1 w przypadku błędu.
+ * \ingroup pubdir50
  */
 int gg_pubdir50_count(gg_pubdir50_t res)
 {
 	return (!res) ? -1 : res->count;
 }
 
-/*
- * gg_pubdir50_type()
+/**
+ * Zwraca rodzaj zapytania lub odpowiedzi.
  *
- * zwraca rodzaj zapytania lub odpowiedzi.
+ * \param res Zapytanie lub odpowiedĹş
  *
- *  - res - zapytanie lub odpowiedĽ
+ * \return Rodzaj lub -1 w przypadku błędu
  *
- * ilo¶ć lub -1 w przypadku błędu.
+ * \ingroup pubdir50
  */
 int gg_pubdir50_type(gg_pubdir50_t res)
 {
 	return (!res) ? -1 : res->type;
 }
 
-/*
- * gg_pubdir50_next()
+/**
+ * Zwraca numer, od ktĂłrego naleĹĽy rozpoczÄ…c kolejne wyszukiwanie.
  *
- * zwraca numer, od którego należy rozpocz±ć kolejne wyszukiwanie, je¶li
- * zależy nam na kolejnych wynikach.
+ * Dłuższe odpowiedzi katalogu publicznego są wysyłane przez serwer
+ * w mniejszych paczkach. Po otrzymaniu odpowiedzi, jeśli numer kolejnego
+ * wyszukiwania jest większy od zera, dalsze wyniki można otrzymać przez
+ * wywołanie kolejnego zapytania z określonym numerem początkowym.
  *
- *  - res - odpowiedĽ
+ * \param res OdpowiedĹş
  *
- * numer lub -1 w przypadku błędu.
+ * \return Numer lub -1 w przypadku błędu
+ *
+ * \ingroup pubdir50
  */
 uin_t gg_pubdir50_next(gg_pubdir50_t res)
 {
 	return (!res) ? (unsigned) -1 : res->next;
 }
 
-/*
- * gg_pubdir50_seq()
+/**
+ * Zwraca numer sekwencyjny zapytania lub odpowiedzi.
  *
- * zwraca numer sekwencyjny zapytania lub odpowiedzi.
+ * \param res Zapytanie lub odpowiedĹş
  *
- *  - res - zapytanie lub odpowiedĽ
+ * \return Numer sekwencyjny lub -1 w przypadku błędu
  *
- * numer lub -1 w przypadku błędu.
+ * \ingroup pubdir50
  */
 uint32_t gg_pubdir50_seq(gg_pubdir50_t res)
 {