File: protocol.html

package info (click to toggle)
libgadu 1%3A1.12.2-7
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,888 kB
  • sloc: ansic: 21,748; perl: 370; makefile: 208; sh: 125
file content (2438 lines) | stat: -rw-r--r-- 92,294 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Protokół Gadu-Gadu</title>
<style type="text/css">
body { font-family: tahoma, verdana, arial, helvetica, sans-serif; }
.tab { background-color: #a0a0a0; }
.tabh { background-color: #d0d0d0; }
.tabf { background-color: white; }
.tabf2 { background-color: white; color: silver; }
.check { background-color: white; color: silver; padding: 0.7em; border: 1px dashed silver; }
.warn { font-family: monospace; padding: 0.7em; background-color: #ffe0e0; border: 1px solid #a08080; }
.c { font-family: monospace; padding: 0.7em; background-color: #e0e0e0; border: 1px solid #a0a0a0; }
.http { font-family: monospace; padding: 0.7em; background-color: #c0f0c0; border: 1px solid #80a080; }
.example { font-family: monospace; padding: 0.7em; background-color: #c0f0f0; border: 1px solid #80a0a0; }
pre { margin: 0px; }
.main { max-width: 800px; text-align: left; }
.footer { font-family: monospace; color: silver; }
</style>
</head>

<body bgcolor="white" text="black">

<center>
<div class="main">

<center>
<h1>Protokół Gadu-Gadu</h1>
<h3>&copy; Copyright 2001-2011 <a href="#ch4">Autorzy</a></h3>
<script>
var language = window.navigator.userLanguage || window.navigator.language;
if (language.indexOf("pl") != 0)
	document.writeln('<div><em>Note:</em> You can try an automatic <a href="http://translate.google.com/translate?sl=pl&tl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u='+escape(location.href)+'">translation by Google</a></div>');
</script>
</center>

<hr />

<a name="index"></a>

<h2>Spis treści</h2>

<ol>
	<li><a href="#ch1">Protokół Gadu-Gadu</a><br />
		1.1.&nbsp;&nbsp;<a href="#ch1.1">Format pakietów i konwencje</a><br />
		1.2.&nbsp;&nbsp;<a href="#ch1.2">Zanim się połączymy</a><br />
		1.3.&nbsp;&nbsp;<a href="#ch1.3">Logowanie się</a><br />
		1.4.&nbsp;&nbsp;<a href="#ch1.4">Zmiana stanu</a><br />
		1.5.&nbsp;&nbsp;<a href="#ch1.5">Ludzie przychodzą, ludzie odchodzą</a><br />
		1.6.&nbsp;&nbsp;<a href="#ch1.6">Wysyłanie wiadomości</a><br />
		1.7.&nbsp;&nbsp;<a href="#ch1.7">Otrzymywanie wiadomości</a><br />
		1.8.&nbsp;&nbsp;<a href="#ch1.8">Powiadomienie o pisaniu ("pisak")</a><br />
		1.9.&nbsp;&nbsp;<a href="#ch1.9">Multilogowanie</a><br />
		1.10.&nbsp;&nbsp;<a href="#ch1.10">Ping, pong</a><br />
		1.11.&nbsp;&nbsp;<a href="#ch1.11">Rozłączenie</a><br />
		1.12.&nbsp;&nbsp;<a href="#ch1.12">Wiadomości systemowe</a><br />
		1.13.&nbsp;&nbsp;<a href="#ch1.13">Wiadomości GG_XML_ACTION</a><br />
		1.14.&nbsp;&nbsp;<a href="#ch1.14">Katalog publiczny</a><br />
		1.15.&nbsp;&nbsp;<a href="#ch1.15">Lista kontaktów</a><br />
		1.16.&nbsp;&nbsp;<a href="#ch1.16">Indeks pakietów</a><br />
	</li>
	<li><a href="#ch2">Usługi HTTP</a><br />
		2.1.&nbsp;&nbsp;<a href="#ch2.1">Format danych</a><br />
		2.2.&nbsp;&nbsp;<a href="#ch2.2">Tokeny</a><br />
		2.3.&nbsp;&nbsp;<a href="#ch2.3">Rejestracja konta</a><br />
		2.4.&nbsp;&nbsp;<a href="#ch2.4">Usunięcie konta</a><br />
		2.5.&nbsp;&nbsp;<a href="#ch2.5">Zmiana hasła</a><br />
		2.6.&nbsp;&nbsp;<a href="#ch2.6">Przypomnienie hasła pocztą</a><br />
	</li>
	<li><a href="#ch3">Połączenia między klientami</a><br />
		3.1.&nbsp;&nbsp;<a href="#ch3.1">Identyfikator połączenia</a><br />
		3.2.&nbsp;&nbsp;<a href="#ch3.2">Przesyłanie plików</a><br />
		3.3.&nbsp;&nbsp;<a href="#ch3.3">Połączenie bezpośrednie</a><br />
		3.4.&nbsp;&nbsp;<a href="#ch3.4">Połączenie przez serwer</a><br />
		3.5.&nbsp;&nbsp;<a href="#ch3.5">Rozmowy głosowe</a><br />
	</li>
	<li><a href="#ch4">Autorzy</a></li>
</ol>

<hr />

<a name="ch0"></a>
<h2>Informacje wstępne</h2>

<p>
Opis protokołu używanego przez Gadu-Gadu bazuje na doświadczeniach
przeprowadzonych przez autorów oraz informacjach nadsyłanych przez 
użytkowników. Żaden klient Gadu-Gadu nie został skrzywdzony podczas
badań. Reverse-engineering opierał się głównie na analizie pakietów
przesyłanych między klientem a serwerem.
</p>

<p>
Najnowsza wersja opisu protokołu znajduje się pod adresem
<a href="http://libgadu.net/protocol/">http://libgadu.net/protocol/</a>.
</p>

<hr />

<a name="ch1"></a>
<h2>1. Protokół Gadu-Gadu</h2>

<a name="ch1.1"></a>
<h3>1.1. Format pakietów i konwencje</h3>

<p>
Podobnie jak coraz większa ilość komunikatorów, Gadu-Gadu korzysta z
protokołu TCP/IP. Każdy pakiet zawiera na początku dwa stałe pola:
</p>

<div class="c">
<pre>struct gg_header {
	int type;	<i>/* typ pakietu */</i>
	int length;	<i>/* długość reszty pakietu */</i>
};</pre>
</div>

<p>
Wszystkie zmienne liczbowe są zgodne z kolejnością bajtów maszyn Intela,
czyli Little-Endian. Wszystkie teksty są kodowane przy użyciu zestawu
znaków UTF-8, chyba że zaznaczono inaczej. Linie kończą się znakami
<tt>\r\n</tt>.
</p>

<p>
Przy opisie struktur, założono, że <tt>char</tt> ma rozmiar 1 bajtu,
<tt>short</tt> 2 bajtów, <tt>int</tt> 4 bajtów, <tt>long long</tt> 8 bajtów,
wszystkie bez znaku. Używając architektur innych niż i386, należy zwrócić
szczególną uwagę na rozmiar typów zmiennych i kolejność bajtów. Poza tym,
większość dostępnych obecnie kompilatorów domyślnie wyrównuje zmienne do
rozmiaru słowa danej architektury, więc należy wyłączyć tą funkcję. W przypadku
gcc będzie to <tt>__attribute__ ((packed))</tt> zaraz za deklaracją każdej
struktury, a dla Microsoft Visual C++ powinno pomóc: </p>

<div class="c">
<pre>#pragma pack(push, 1)

<i>/* deklaracje */</i>

#pragma pack(pop)</pre>
</div>

<p>
Pola, których znaczenie jest nieznane, lub nie do końca jasne, oznaczono
przedrostkiem <tt>unknown</tt>.
</p>

<hr />

<a name="ch1.2"></a>
<h3>1.2. Zanim się połączymy</h3>

<p>
Żeby wiedzieć, z jakim serwerem mamy się połączyć, należy za pomocą HTTP
połączyć się z <tt>appmsg.gadu-gadu.pl</tt> i wysłać:
</p>

<div class="http">
<pre>GET /appsvc/appmsg_ver8.asp?fmnumber=<b>NUMER</b>&amp;fmt=<b>FORMAT</b>&amp;lastmsg=<b>WIADOMOŚĆ</b>&amp;version=<b>WERSJA</b> HTTP/1.1
Connection: Keep-Alive
Host: appmsg.gadu-gadu.pl</pre>
</div>

<p>
Gdzie:
</p>

<ul>
<li><b>NUMER</b> jest numerem Gadu-Gadu.</li>
<li><b>WERSJA</b> jest wersją klienta w postaci &bdquo;<tt>A.B.C.D</tt>&rdquo;
(na przykład &bdquo;<tt>8.0.0.7669</tt>&rdquo;).</li>
<li><b>FORMAT</b> określa czy wiadomość systemowa będzie przesyłana czystym
tekstem (brak zmiennej &bdquo;fmt&rdquo;) czy w HTMLu (wartość &bdquo;<tt>2</tt>&rdquo;).</li>
<li><b>WIADOMOŚĆ</b> jest numerem ostatnio otrzymanej wiadomości systemowej.</li>
</ul>

<p>
Na postawione w ten sposób zapytanie, serwer może odpowiedzieć w następujący
sposób:
</p>

<div class="example">
<pre>HTTP/1.0 200 OK
Connection: close

0 0 91.197.13.78:8074 91.197.13.78</pre>
</div>

<p>
Pierwsze pole jest numerem wiadomości systemowej, a trzecie i czwarte
podają nam namiary na właściwy serwer. Jeśli serwer jest niedostępny,
zamiast adresu IP jest zwracany tekst &bdquo;<tt>notoperating</tt>&rdquo;.
Jeżeli połączenie z portem 8074 nie powiedzie się z jakichś powodów,
można się łączyć na port 443. 
</p>

<p>
Jeśli pierwsza liczba jest różna od zera, zaraz po nagłówku znajduje się
wiadomość systemowa w wybranym formacie, lub jeśli linia zaczyna się od znaku
&bdquo;<tt>@</tt>&rdquo;, adres strony, którą należy otworzyć w przeglądarce.
</p>

<div class="http">
<pre>GET /appsvc/appmsg3.asp?fmnumber=<b>NUMER</b>&amp;version=<b>WERSJA</b>&amp;fmt=<b>FORMAT</b>&amp;lastmsg=<b>WIADOMOŚĆ</b>
Host: appmsg.gadu-gadu.pl
User-Agent: <b>PRZEGLĄDARKA</b>
Pragma: no-cache</pre>
</div>

<hr />

<a name="ch1.3"></a>
<h3>1.3. Logowanie się</h3>

<p>
Po połączeniu się portem 8074 lub 443 serwera Gadu-Gadu, otrzymujemy pakiet
typu <tt>0x0001</tt>, który na potrzeby tego dokumentu nazwiemy:
</p>

<div class="c">
<pre>#define GG_WELCOME 0x0001</pre>
</div>

<p>
Reszta pakietu zawiera ziarno &mdash; wartość, którą razem z hasłem przekazuje
się do funkcji skrótu:
</p>

<div class="c">
<pre>struct gg_welcome {
	int seed;	<i>/* ziarno */</i>
};</pre>
</div>

<p>
Kiedy mamy już tą wartość możemy odesłać pakiet logowania:
</p>

<div class="c">
<pre>#define GG_LOGIN80 0x0031

struct gg_login80 {
        int uin;              <i>/* numer Gadu-Gadu */</i>
        char language[2];     <i>/* język: "pl" */</i>
        char hash_type;       <i>/* rodzaj funkcji skrótu hasła */</i>
        char hash[64];        <i>/* skrót hasła dopełniony \0 */</i>
        int status;           <i>/* początkowy status połączenia */</i>
        int flags;            <i>/* początkowe flagi połączenia */</i>
        int features;         <i>/* opcje protokołu (0x00000367)*/</i>
        int local_ip;         <i>/* lokalny adres połączeń bezpośrednich (nieużywany) */</i>
        short local_port;     <i>/* lokalny port połączeń bezpośrednich (nieużywany) */</i>
        int external_ip;      <i>/* zewnętrzny adres (nieużywany) */</i>
        short external_port;  <i>/* zewnętrzny port (nieużywany) */</i>
        char image_size;      <i>/* maksymalny rozmiar grafiki w KB */</i>
        char unknown1;        <i>/* 0x64 */</i>
        int version_len;      <i>/* długość ciągu z wersją (0x23) */</i>
        char version[];       <i>/* "Gadu-Gadu Client build 10.0.0.10450" (bez \0) */</i>
        int description_size; <i>/* rozmiar opisu */</i>
        char description[];   <i>/* opis (nie musi wystąpić, bez \0) */</i>
};</pre>
</div>

<p>
Pola określające adresy i port są pozostałościami po poprzednich wersjach
protokołów i w obecnej wersji zawierają zera.
</p>

<p>
Pole <tt>features</tt> jest mapą bitową informującą serwer, które z funkcji
protokołu obsługujemy. Do minimalnej zgodności z protokołem Nowego Gadu-Gadu
niezbędna jest co najmniej wartość <tt>0x00000007</tt>.
</p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td><b>Bit</b></td><td><b>Wartość</b></td><td><b>Znaczenie</b></td></tr>
<tr class="tabf"><td>0</td><td><tt>0x00000001</tt></td><td>Rodzaj pakietu informującego o zmianie stanu kontaktów (patrz bit 2)<br /><tt>0</tt> &mdash; <tt>GG_STATUS77</tt>, <tt>GG_NOTIFY_REPLY77</tt><br /><tt>1</tt> &mdash; <tt>GG_STATUS80BETA</tt>, <tt>GG_NOTIFY_REPLY80BETA</tt></td></tr>
<tr class="tabf"><td>1</td><td><tt>0x00000002</tt></td><td>Rodzaj pakietu z otrzymają wiadomością<br /><tt>0</tt> &mdash; <tt>GG_RECV_MSG</tt><br /><tt>1</tt> &mdash; <tt>GG_RECV_MSG80</tt></td></tr>
<tr class="tabf"><td>2</td><td><tt>0x00000004</tt></td><td>Rodzaj pakietu informującego o zmianie stanu kontaktów (patrz bit 0)<br /><tt>0</tt> &mdash; wybrany przez bit 0<br /><tt>1</tt> &mdash; <tt>GG_STATUS80</tt>, <tt>GG_NOTIFY_REPLY80</tt></td></tr>
<tr class="tabf"><td>4</td><td><tt>0x00000010</tt></td><td>Klient obsługuje statusy "nie przeszkadzać" i "poGGadaj ze mną"</td></tr>
<tr class="tabf"><td>5</td><td><tt>0x00000020</tt></td><td>Klient obsługuje statusy graficzne i <tt>GG_STATUS_DESCR_MASK</tt> (patrz <a href="#ch1.4">Zmiana stanu</a>)</td></tr>
<tr class="tabf"><td>6</td><td><tt>0x00000040</tt></td><td>Znaczenie nie jest znane, ale klient otrzyma w przypadku błędnego hasła pakiet <tt>GG_LOGIN80_FAILED</tt> zamiast <tt>GG_LOGIN_FAILED</tt></td></tr>
<tr class="tabf"><td>7</td><td><tt>0x00000100</tt></td><td>Znaczenie nie jest znane, ale jest używane przez nowe klienty</td></tr>
<tr class="tabf"><td>9</td><td><tt>0x00000200</tt></td><td>Klient obsługuje <a href="#ch1.5.1">dodatkowe informacje o liście kontaktów</a></td></tr>
<tr class="tabf"><td>10</td><td><tt>0x00000400</tt></td><td>Klient wysyła <a href="#ch1.7.1">potwierdzenia odebrania wiadomości</a></td></tr>
<tr class="tabf"><td>13</td><td><tt>0x00002000</tt></td><td>Klient obsługuje <a href="#ch1.8">powiadomienia o pisaniu</a></td></tr>
<tr class="tabf"><td>13</td><td><tt>0x00004000</tt></td><td>Klient obsługuje <a href="#ch1.9">multilogowanie</a></td></tr>
</table>

<p>
Skrót hasła można liczyć na dwa sposoby:
</p>

<div class="c">
<pre>#define GG_LOGIN_HASH_GG32 0x01
#define GG_LOGIN_HASH_SHA1 0x02</pre>
</div>

<p>
Pierwszy, nieużywany już algorytm (<tt>GG_LOGIN_HASH_GG32</tt>) został
wymyślony na potrzeby Gadu-Gadu i zwraca 32-bitową wartość dla danego ziarna
i hasła. Jego implementacja w języku C wygląda następująco:
</p>

<div class="c">
<pre>int gg_login_hash(unsigned char *password, unsigned int seed)
{
	unsigned int x, y, z;

	y = seed;

	for (x = 0; *password; password++) {
		x = (x &amp; 0xffffff00) | *password;
		y ^= x;
		y += x;
		x &lt;&lt;= 8;
		y ^= x;
		x &lt;&lt;= 8;
		y -= x;
		x &lt;&lt;= 8;
		y ^= x;

		z = y &amp; 0x1f;
		y = (y &lt;&lt; z) | (y &gt;&gt; (32 - z));
	}

	return y;
}</pre>
</div>

<p>
Ze względu na niewielki zakres wartości wyjściowych, istnieje
prawdopodobieństwo, że inne hasło przy odpowiednim ziarnie da taki sam wynik.
Z tego powodu zalecane jest używane algorytmu
<a href="http://pl.wikipedia.org/wiki/SHA-1">SHA-1</a>, którego implementacje
są dostępne dla większości współczesnych systemów operacyjnych. Skrót SHA-1
należy obliczyć z połączenia hasła (bez <tt>\0</tt>) i binarnej reprezentacji
ziarna. Przykładowy kod może wyglądać w następujący sposób:
</p>

<div class="c">
<pre>char *gg_sha_hash(char *password, unsigned int seed)
{
	SHA1_CTX ctx;
	static char result[20];
	  
	SHA1_Init(&amp;ctx);  
	SHA1_Update(&amp;ctx, password, strlen(password));
	SHA1_Update(&amp;ctx, &amp;seed, sizeof(seed));
	SHA1_Final(result, &amp;ctx);

	return result;
}</pre>
</div>

<p>
Jeśli autoryzacja się powiedzie, dostaniemy w odpowiedzi pakiet:
</p>

<div class="c">
<pre>#define GG_LOGIN80_OK 0x0035

struct gg_login80_ok {
	int unknown1;	<i>/* 01 00 00 00 */</i>
};</pre>
</div>

<p>
W przypadku błędu autoryzacji otrzymamy pakiet:
</p>

<div class="c">
<pre>#define GG_LOGIN80_FAILED 0x0043

struct gg_login80_failed {
	int unknown1;	<i>/* 01 00 00 00 */</i>
};</pre>
</div>

<p>
Starsze wersje oraz klienty z otrzymywały pusty pakiet:
</p>

<div class="c">
<pre>#define GG_LOGIN_FAILED 0x0009</pre>
</div>

<hr />

<a name="ch1.4"></a>
<h3>1.4. Zmiana stanu</h3>

<p>
Gadu-Gadu przewiduje kilka stanów klienta, które zmieniamy pakietem typu:
</p>

<div class="c">
<pre>#define GG_NEW_STATUS80 0x0038

struct gg_new_status80 {
	int status;		<i>/* nowy status */</i>
	int flags;              <i>/* nowe flagi */</i>
	int description_size;   <i>/* rozmiar opisu */</i>
	char description[];	<i>/* opis (nie musi wystąpić, bez \0) */</i>
};</pre>
</div>

<p>
Możliwe stany to:
</p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td><b>Etykieta</b></td><td><b>Wartość</b></td><td><b>Znaczenie</b></td></tr>
<tr class="tabf"><td><tt>GG_STATUS_NOT_AVAIL</tt></td><td><tt>0x0001</tt></td><td>Niedostępny</td></tr>
<tr class="tabf"><td><tt>GG_STATUS_NOT_AVAIL_DESCR</tt></td><td><tt>0x0015</tt></td><td>Niedostępny (z opisem)</td></tr>
<tr class="tabf"><td><tt>GG_STATUS_FFC</tt></td><td><tt>0x0017</tt></td><td>PoGGadaj ze mną</td></tr>
<tr class="tabf"><td><tt>GG_STATUS_FFC_DESCR</tt></td><td><tt>0x0018</tt></td><td>PoGGadaj ze mną (z opisem)</td></tr>
<tr class="tabf"><td><tt>GG_STATUS_AVAIL</tt></td><td><tt>0x0002</tt></td><td>Dostępny</td></tr>
<tr class="tabf"><td><tt>GG_STATUS_AVAIL_DESCR</tt></td><td><tt>0x0004</tt></td><td>Dostępny (z opisem)</td></tr>
<tr class="tabf"><td><tt>GG_STATUS_BUSY</tt></td><td><tt>0x0003</tt></td><td>Zajęty</td></tr>
<tr class="tabf"><td><tt>GG_STATUS_BUSY_DESCR</tt></td><td><tt>0x0005</tt></td><td>Zajęty (z opisem)</td></tr>
<tr class="tabf"><td><tt>GG_STATUS_DND</tt></td><td><tt>0x0021</tt></td><td>Nie przeszkadzać</td></tr>
<tr class="tabf"><td><tt>GG_STATUS_DND_DESCR</tt></td><td><tt>0x0022</tt></td><td>Nie przeszkadzać (z opisem)</td></tr>
<tr class="tabf"><td><tt>GG_STATUS_INVISIBLE</tt></td><td><tt>0x0014</tt></td><td>Niewidoczny</td></tr>
<tr class="tabf"><td><tt>GG_STATUS_INVISIBLE_DESCR</tt></td><td><tt>0x0016</tt></td><td>Niewidoczny (z opisem)</td></tr>
<tr class="tabf"><td><tt>GG_STATUS_BLOCKED</tt></td><td><tt>0x0006</tt></td><td>Zablokowany</td></tr>
<tr class="tabf"><td><tt>GG_STATUS_IMAGE_MASK</tt></td><td><tt>0x0100</tt></td><td>Maska bitowa oznaczająca ustawiony opis graficzny (tylko odbierane)</td></tr>
<tr class="tabf"><td><tt>GG_STATUS_ADAPT_STATUS_MASK</tt></td><td><tt>0x0400</tt></td>
<td>Maska bitowa informująca serwer, że jeśli istnieje już inne połączenie na tym numerze to nasze ma przyjać jego stan (podany przez nas zostanie zignorowany). Jeśli połączenia innego nie ma, to ustawiany jest stan podany przez nas.</td></tr>
<tr class="tabf"><td><tt>GG_STATUS_DESCR_MASK</tt></td><td><tt>0x4000</tt></td><td>Maska bitowa oznaczająca ustawiony opis</td></tr>
<tr class="tabf"><td><tt>GG_STATUS_FRIENDS_MASK</tt></td><td><tt>0x8000</tt></td><td>Maska bitowa oznaczająca tryb tylko dla przyjaciół</td></tr>
</table>

<p>
Możliwe flagi to:
</p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td><b>Bit</b></td><td><b>Wartość</b></td><td><b>Znaczenie</b></td></tr>
<tr class="tabf"><td>0</td><td><tt>0x00000001</tt></td>
<td>Prawdopodobnie połączenia audio</td></tr>
<tr class="tabf"><td>1</td><td><tt>0x00000002</tt></td><td>Klient obsługuje wideorozmowy</td></tr>
<tr class="tabf"><td>20</td><td><tt>0x00100000</tt></td><td>Klient mobilny (ikona telefonu komórkowego)</td></tr>
<tr class="tabf"><td>23</td><td><tt>0x00800000</tt></td><td>Klient chce otrzymywać linki od nieznajomych</td></tr>
</table>

<p>
Jeśli klient obsługuje statusy graficzne, to statusy opisowe będą dodatkowo
określane przez dodanie flagi <tt>GG_STATUS_DESCR_MASK</tt>. Dotyczy to zarówno
statusów wysyłanych, jak i odbieranych z serwera.
</p>

<p>
Należy pamiętać, żeby przed rozłączeniem się z serwerem należy zmienić
stan na <tt>GG_STATUS_NOT_AVAIL</tt> lub <tt>GG_STATUS_NOT_AVAIL_DESCR</tt>.
Jeśli ma być widoczny tylko dla przyjaciół, należy dodać
<tt>GG_STATUS_FRIENDS_MASK</tt> do normalnej wartości stanu.
</p>

<p>
Maksymalna długość opisu wynosi 255 bajtów, jednak należy pamiętać że znak w UTF-8
czasami zajmuje więcej niż 1 bajt.
</p>

<hr />

<a name="ch1.5"></a>
<h3>1.5. Ludzie przychodzą, ludzie odchodzą</h3>

<p>
Zaraz po zalogowaniu możemy wysłać serwerowi naszą listę kontaktów, żeby
dowiedzieć się, czy są w danej chwili dostępni. Lista kontaktów jest dzielona
na pakiety po 400 wpisów. Pierwsze wpisy są typu <tt>GG_NOTIFY_FIRST</tt>,
a ostatni typu <tt>GG_NOTIFY_LAST</tt>, żeby serwer wiedział, kiedy kończymy.
Jeśli lista kontaktów jest mniejsza niż 400 wpisów, wysyłamy oczywiście tylko
<tt>GG_NOTIFY_LAST</tt>. Pakiety te zawierają struktury <tt>gg_notify</tt>:
</p>

<div class="c">
<pre>#define GG_NOTIFY_FIRST 0x000f
#define GG_NOTIFY_LAST 0x0010
	
struct gg_notify {
	int uin;	<i>/* numer Gadu-Gadu kontaktu */</i>
	char type;	<i>/* rodzaj użytkownika */</i>
};</pre>	
</div>

<p>
Gdzie pole <tt>type</tt> jest mapą bitową następujących wartości:
</p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td><b>Etykieta</b></td><td><b>Wartość</b></td><td><b>Znaczenie</b></td></tr>
<tr class="tabf"><td><tt>GG_USER_BUDDY</tt></td><td><tt>0x01</tt></td><td>Każdy użytkownik dodany do listy kontaktów</td></tr>
<tr class="tabf"><td><tt>GG_USER_FRIEND</tt></td><td><tt>0x02</tt></td><td>Użytkownik, dla którego jesteśmy widoczni w trybie &bdquo;tylko dla przyjaciół&rdquo;</td></tr>
<tr class="tabf"><td><tt>GG_USER_BLOCKED</tt></td><td><tt>0x04</tt></td><td>Użytkownik, którego wiadomości nie chcemy otrzymywać</td></tr>
</table>

<p>
Jednak dla zachowania starego nazewnictwa stałych można używać najczęściej spotykane wartości to:
</p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td><b>Etykieta</b></td><td><b>Wartość</b></td><td><b>Znaczenie</b></td></tr>
<tr class="tabf"><td><tt>GG_USER_OFFLINE</tt></td><td><tt>0x01</tt></td><td>Użytkownik, dla którego będziemy niedostępni, ale mamy go w liście kontaktów</td></tr>
<tr class="tabf"><td><tt>GG_USER_NORMAL</tt></td><td><tt>0x03</tt></td><td>Zwykły użytkownik dodany do listy kontaktów</td></tr>
<tr class="tabf"><td><tt>GG_USER_BLOCKED</tt></td><td><tt>0x04</tt></td><td>Użytkownik, którego wiadomości nie chcemy otrzymywać</td></tr>
</table>

<p>
Jeśli nie mamy nikogo na liście wysyłamy następujący pakiet o zerowej długości:
</p>

<div class="c">
<pre>#define GG_LIST_EMPTY 0x0012</pre>
</div>

<p>
Jeśli ktoś jest, serwer odpowie pakietem <tt>GG_NOTIFY_REPLY80</tt>
zawierającym jedną lub więcej struktur <tt>gg_notify_reply80</tt>:
</p>

<div class="c">
<pre>#define GG_NOTIFY_REPLY80 0x0037
	
struct gg_notify_reply80 {
	int uin;		<i>/* numer Gadu-Gadu kontaktu */</i>
	int status;		<i>/* status */</i>
	int features;		<i>/* opcje protokołu (patrz GG_LOGIN80) */</i>
	int remote_ip;		<i>/* adres IP bezpośrednich połączeń (nieużywane) */</i>
	short remote_port;	<i>/* port bezpośrednich połączeń (nieużywane) */</i>
	char image_size;	<i>/* maksymalny rozmiar obrazków w KB */</i>
	char unknown1;		<i>/* 0x00 */</i>
	int flags;		<i>/* flagi połączenia (patrz GG_LOGIN80) */</i>
	int description_size;	<i>/* rozmiar opisu */</i>
	char description[];	<i>/* opis (nie musi wystąpić, bez \0) */</i>
};</pre>
</div>

<p>
Zdarzają się też inne &bdquo;nietypowe&rdquo; wartości, ale ich znaczenie nie
jest jeszcze do końca znane.
</p>

<p>
Aby dodać do listy kontaktów numer w trakcie połączenia, należy wysłać niżej
opisany pakiet. Jego format jest identyczny jak <tt>GG_NOTIFY_*</tt>, z tą
różnicą, że zawiera jeden numer.
</p>

<div class="c">
<pre>#define GG_ADD_NOTIFY 0x000d
	
struct gg_add_notify {
	int uin;	<i>/* numerek */</i>
	char type;	<i>/* rodzaj użytkownika */</i>
};</pre>
</div>

<p>
Poniższy pakiet usuwa z listy kontaktów:
</p>

<div class="c">
<pre>#define GG_REMOVE_NOTIFY 0x000e
	
struct gg_remove_notify {
	int uin;	<i>/* numerek */</i>
	char type;	<i>/* rodzaj użytkownika */</i>
};</pre>
</div>

<p>
Należy zwrócić uwagę, że pakiety <tt>GG_ADD_NOTIFY</tt>
i <tt>GG_REMOVE_NOTIFY</tt> dodają i usuwają flagi będące mapą bitową. Aby
zmienić status użytkownika z normalnego na blokowanego, należy najpierw
usunąć rodzaj <tt>GG_USER_NORMAL</tt>, a następnie dodać rodzaj 
<tt>GG_USER_BLOCKED</tt>.
</p>

<p>
Jeśli ktoś opuści Gadu-Gadu lub zmieni stan, otrzymamy poniższy pakiet,
którego struktura jest identyczna z <tt>GG_NOTIFY_REPLY80</tt>.
</p>

<div class="c">
<pre>#define GG_STATUS80 0x0036</pre>
</div>

<a name="ch1.5.1"></a>
<h4>1.5.1 Dodatkowe informacje o kontaktach</h4>

<p>
Jeśli podczas logowania klient wyśle w polu <tt>features</tt> maskę bitową
<tt>0x00000200</tt>, to będzie otrzymywał od serwera pakiety typu
<tt>GG_USER_DATA</tt> o następującej strukturze:
</p>

<div class="c">
<pre>#define GG_USER_DATA 0x0044

struct gg_user_data {
	int type;	<i>/* typ */</i>
	int num;	<i>/* liczba struktur gg_user_data_user */</i>
};

struct gg_user_data_user {
	int uin;	<i>/* numer użytkownika */</i>
	int num;	<i>/* liczba struktur gg_user_data_attr */</i>
};

struct gg_user_data_attr {
	int name_size;	<i>/* długość nazwy atrybutu */</i>
	char name[];	<i>/* nazwa atrybutu (bez znaku \0) */</i>
	int type;	<i>/* typ atrybutu */</i>
	int value_size;	<i>/* długość wartości atrybutu */</i>
	char value[];	<i>/* wartość atrybutu (bez znaku \0) */</i>
};</pre>
</div>

<hr />

<a name="ch1.6"></a>
<h3>1.6. Wysyłanie wiadomości</h3>

<p>
Wiadomości wysyła się następującym typem pakietu:
</p>

<div class="c">
<pre>#define GG_SEND_MSG80 0x002d

struct gg_send_msg80 {
	int recipient;		<i>/* numer odbiorcy */</i>
	int seq;		<i>/* numer sekwencyjny */</i>
	int class;		<i>/* klasa wiadomości */</i>
	int offset_plain;	<i>/* położenie treści czystym tekstem */</i>
	int offset_attributes;	<i>/* położenie atrybutów */</i>
	char html_message[];	<i>/* treść w formacie HTML (zakończona \0) */</i>
	char plain_message[];	<i>/* treść czystym tekstem (zakończona \0) */</i>
	char attributes[];	<i>/* atrybuty wiadomości */</i>
};</pre>

</div>

<p>
Numer sekwencyjny w poprzednich wersjach protokołu był losową liczbą
pozwalającą przypisać potwierdzenie do wiadomości. Obecnie jest znacznikiem
czasu w postaci uniksowej (liczba sekund od 1 stycznia 1970r. UTC).
</p>

<p>
Klasa wiadomości jest mapą bitową (domyślna wartość to <tt>0x08</tt>):
</p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td><b>Etykieta</b></td><td><b>Wartość</b></td><td><b>Znaczenie</b></td></tr>
<tr class="tabf"><td><tt>GG_CLASS_QUEUED</tt></td><td><tt>0x0001</tt></td><td>Bit ustawiany wyłącznie przy odbiorze wiadomości, gdy wiadomość została wcześniej zakolejkowania z powodu nieobecności</td></tr>
<tr class="tabf"><td><tt>GG_CLASS_MSG</tt></td><td><tt>0x0004</tt></td><td>Wiadomość ma się pojawić w osobnym okienku (nieużywane)</td></tr>
<tr class="tabf"><td><tt>GG_CLASS_CHAT</tt></td><td><tt>0x0008</tt></td><td>Wiadomość jest częścią toczącej się rozmowy i zostanie wyświetlona w istniejącym okienku</td></tr>
<tr class="tabf"><td><tt>GG_CLASS_CTCP</tt></td><td><tt>0x0010</tt></td><td>Wiadomość jest przeznaczona dla klienta Gadu-Gadu i nie powinna być wyświetlona użytkownikowi (nieużywane)</td></tr>
<tr class="tabf"><td><tt>GG_CLASS_ACK</tt></td><td><tt>0x0020</tt></td><td>Klient nie życzy sobie potwierdzenia wiadomości</td></tr>
</table>

<p>
Długość treści wiadomości nie powinna przekraczać 2000 znaków. Oryginalny
klient zezwala na wysłanie do 1989 znaków. Treść w formacie HTML jest kodowana
UTF-8. Treść zapisana czystym tekstem jest kodowana zestawem znaków CP1250.
W obu przypadkach, mimo domyślnych atrybutów tekstu, oryginalny klient dodaje
blok atrybutów tekstu. Dla HTML wygląda to następująco:
</p>

<div class="http">
<pre>&lt;span style="color:#000000; font-family:'MS Shell Dlg 2'; font-size:9pt; "&gt;Test&lt;/span&gt;</pre>
</div>

<p>
Dla czystego tekstu dodawane są informacje o tym, że tekst ma kolor czarny:
</p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td><b>Bajty</b></td><td><b>Opis</b></td></tr>
<tr class="tabf"><td><tt>0x02</tt></td><td>Flaga formatowania tekstu</td></tr>
<tr class="tabf"><td><tt>0x06 0x00</tt></td><td>Długość bloku formatowania wynosi 6 bajtów</td></tr>
<tr class="tabf"><td><tt>0x00 0x00</tt></td><td>Atrybut tekstu od pozycji 0</td></tr>
<tr class="tabf"><td><tt>0x08</tt></td><td>Tekst kolorowy</td></tr>
<tr class="tabf"><td><tt>0x00 0x00 0x00</tt></td><td>Kolor czarny</td></tr>
</table>

<a name="ch1.6.1"></a>
<h4>1.6.1. Konferencje</h4>

<p>
Podczas konferencji ta sama wiadomość jest wysyłana do wszystkich odbiorców,
a do sekcji atrybutów dołączana jest lista pozostałych uczestników konferencji.
Dla przykładu, jeśli w konferencji biorą udział Ala, Bartek, Celina i Darek,
to osoba Ala wysyła wysyła do Bartka wiadomość z listą zawierającą numery
Celiny i Darka, do Celiny z numerami Bartka i Darka, a do Darka z numerami
Bartka i Celiny. Lista pozostałych uczestników konferencji jest przekazywana
za pomocą struktury:
</p>

<div class="c">
<pre>struct gg_msg_recipients {
	char flag;		<i>/* 0x01 */</i>
	int count;		<i>/* liczba odbiorców */</i>
	int recipients[];	<i>/* lista odbiorców */</i>
};</pre>
</div>

<p>
Na przykład, by wysłać wysłać do do dwóch osób, należy wysłać pakiet z
wiadomością o treści:
</p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td><b>Bajty</b></td><td><b>Opis</b></td></tr>
<tr class="tabf"><td><tt>0x01</tt></td><td>Flaga wiadomości konferencyjnej</td></tr>
<tr class="tabf"><td><tt>0x02 0x00 0x00 0x00</tt></td><td>Liczba pozostałych uczestników</td></tr>
<tr class="tabf"><td><tt>0xXX 0xXX 0xXX 0xXX</tt></td><td>Numer uczestnika #2</td></tr>
<tr class="tabf"><td><tt>0xYY 0xYY 0xYY 0xYY</tt></td><td>Numer uczestnika #3</td></tr>
</table>

<a name="ch1.6.2"></a>
<h4>1.6.2. Formatowanie tekstu</h4>

<p>
Dla protokołu Nowego Gadu-Gadu natywnym formatem jest HTML, ale blok
atrybutów również jest przesyłany dla zachowania kompatybilności ze starszymi
klientami.
</p>

<a name="ch1.6.2.1"></a>
<h4>1.6.2.1. Format HTML</h4>

<p>
Każdy fragment tekstu o spójnych atrybutach jest zawarty w jednym znaczniku
<tt>&lt;span&gt;</tt>, nawet jeśli są to atrybuty domyślne. Dla przykładu,
wiadomość o treści &bdquo;Test&rdquo; wysłana bez zmiany atrybutów tekstu
przedstawia się następująco:
</p>

<div class="http">
<pre>&lt;span style="color:#000000; font-family:'MS Shell Dlg 2'; font-size:9pt; "&gt;Test&lt;/span&gt;</pre>
</div>

<p>
Oryginalny klient korzysta z następujących znaczników HTML:
</p>

<ul>
<li>pogrubienie &mdash; <tt>&lt;b&gt;</tt></li>
<li>kursywa &mdash; <tt>&lt;i&gt;</tt></li>
<li>podkreślenie &mdash; <tt>&lt;u&gt;</tt></li>
<li>kolor tła &mdash; <tt>&lt;span style="background-color:#... "&gt;</tt></li>
<li>kolor tekstu &mdash; <tt>&lt;span style="color:#... "&gt;</tt></li>
<li>czcionka &mdash; <tt>&lt;span style="font-family:'...' "&gt;</tt></li>
<li>rozmiar czcionki &mdash; <tt>&lt;span style="font-size:...pt "&gt;</tt></li>
<li>nowa linia &mdash; <tt>&lt;br&gt;</tt></li>
<li>obrazek &mdash; <tt>&lt;img name="..."&gt;</tt></li>
</ul>

<p>
Źródło obrazka obrazka jest połączeniem heksadecymalnego zapisu (małymi
literami) sumy kontrolnej CRC32 oraz rozmiaru dopełnionego do czterech
bajtów. Dla obrazka o sumie kontrolnej <tt>0x45fb2e46</tt> i rozmiarze
16568 bajtów źródłem będzie <tt>45fb2e46000040b8</tt>.
</p>

<p>
Przykładowa wiadomość wykorzystująca wszystkie dostępne znaczniki oraz
obrazek:
</p>

<div class="http">
&lt;span style="background-color:#00ff00; color:#000000; font-family:'MS Shell Dlg 2'; font-size:9pt; "&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;Wiadomość&lt;br&gt;testowa&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;img name="45fb2e46000040b8"&gt;&lt;/span&gt;
</div>

<a name="ch1.6.2.2"></a>
<h4>1.6.2.2. Czysty tekst z atrybutami</h4>

<p>
Możliwe jest również dodawanie do wiadomości różnych atrybutów tekstu, jak
pogrubienie czy kolory. Niezbędne jest dołączenie do wiadomości następującej
struktury:
</p>

<div class="c">
<pre>struct gg_msg_richtext {
	char flag;	<i>/* 0x02 */</i>
	short length;	<i>/* długość dalszej części */</i>
};</pre>
</div>

<p>
Dalsza część pakietu zawiera odpowiednią ilość struktur o łącznej długości
określonej polem <tt>length</tt>:
</p>

<div class="c">
<pre>struct gg_msg_richtext_format {
	short position;	<i>/* pozycja atrybutu w tekście */</i>
	char font;	<i>/* atrybuty czcionki */</i>
	char rgb[3];	<i>/* kolor czcionki (nie musi wystąpić) */</i>
	struct gg_msg_richtext_image image; <i>/* obrazek (nie musi wystąpić) */</i>
};</pre>
</div>

<p>
Każda z tych struktur określa kawałek tekstu począwszy od znaku określonego
przez pole <tt>position</tt> (liczone od zera) aż do następnego wpisu lub
końca tekstu. Pole <tt>font</tt> jest mapą bitową i kolejne bity mają
następujące znaczenie:
</p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td><b>Etykieta</b></td><td><b>Wartość</b></td><td><b>Znaczenie</b></td></tr>
<tr class="tabf"><td><tt>GG_FONT_BOLD</tt></td><td><tt>0x01</tt></td><td>Pogrubiony tekst</td></tr>
<tr class="tabf"><td><tt>GG_FONT_ITALIC</tt></td><td><tt>0x02</tt></td><td>Kursywa</td></tr>
<tr class="tabf"><td><tt>GG_FONT_UNDERLINE</tt></td><td><tt>0x04</tt></td><td>Podkreślenie</td></tr>
<tr class="tabf"><td><tt>GG_FONT_COLOR</tt></td><td><tt>0x08</tt></td><td>Kolorowy tekst. Tylko w tym wypadku struktura <tt>gg_msg_richtext_format</tt> zawiera pole <tt>rgb[]</tt> będące opisem trzech składowych koloru, kolejno czerwonej, zielonej i niebieskiej.</td></tr>
<tr class="tabf"><td><tt>GG_FONT_IMAGE</tt></td><td><tt>0x80</tt></td><td>Obrazek. Tylko w tym wypadku struktura <tt>gg_msg_richtext_format</tt> zawiera pole <tt>image</tt>.</td></tr>
</table>

<p>
Jeśli wiadomość zawiera obrazek, przesyłana jest jego suma kontrolna CRC32
i rozmiar. Dzięki temu nie trzeba za każdym razem wysyłać każdego obrazka
&mdash; klienty je zachowują. Struktura <tt>gg_msg_richtext_image</tt> opisująca
obrazek umieszczony w wiadomości wygląda następująco:
</p>

<div class="c">
<pre>struct gg_msg_richtext_image {
	char length;	<i>/* długość opisu obrazka (0x09) */</i>
	char type;	<i>/* rodzaj opisu obrazka (0x01) */</i>
	int size;	<i>/* rozmiar obrazka */</i>
	int crc32;	<i>/* suma kontrolna obrazka */</i>
};</pre>
</div>

<p>
Przykładowo, by przesłać tekst &bdquo;ala <b>ma</b> kota&rdquo;, należy
dołączyć do wiadomości następującą sekwencję bajtów:
</p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td><b>Bajty</b></td><td><b>Opis</b></td></tr>
<tr class="tabf"><td><tt>0x02</tt></td><td>Flaga formatowania tekstu</td></tr>
<tr class="tabf"><td><tt>0x06 0x00</tt></td><td>Długość bloku formatowania wynosi 6 bajtów</td></tr>
<tr class="tabf"><td><tt>0x04 0x00</tt></td><td>Atrybut tekstu od pozycji 4</td></tr>
<tr class="tabf"><td><tt>0x01</tt></td><td>Tekst pogrubiony</td></tr>
<tr class="tabf"><td><tt>0x06 0x00</tt></td><td>Atrybut tekstu od pozycji 6</td></tr>
<tr class="tabf"><td><tt>0x00</tt></td><td>Tekst normalny</td></tr>
</table>

<p>
W przypadku gdy wiadomość zawiera zarówno informacje o uczestnikach konferencji,
jaki i o formatowaniu, najpierw informacje o konferencji powinny znajdować się
przed formatowaniem.
</p>

<p>
Jeśli obrazek jest przesyłany w wiadomości bez tekstu, jej treść zapisana
czystym tekstem powinna zawierać znak niełamliwej spacji (kod 160 w kodowaniu
CP1250). W innym przypadku nowsze klienty (np. Nowe Gadu-Gadu) nie wyświetlą
obrazka. Wiadomość w formacie HTML może zawierać wyłącznie znacznik
<tt>&lt;img&gt;</tt>.
</p>

<a name="ch1.6.3"></a>
<h4>1.6.3. Przesyłanie obrazków</h4>

<p>
Gdy klient nie posiada w pamięci podręcznej obrazka o podanych parametrach,
wysyła pustą wiadomość o klasie <tt>GG_CLASS_MSG</tt> z dołączoną strukturą
<tt>gg_msg_image_request</tt>:
</p>

<div class="c">
<pre>struct gg_msg_image_request {
	char flag;	<i>/* 0x04 */</i>
	int size;	<i>/* rozmiar */</i>
	int crc32;	<i>/* suma kontrolna */</i>
};</pre>
</div>

<p>
Przykładowa treść wiadomości z prośbą o wysłanie obrazka o długości 10000
bajtów i sumie kontrolnej 0x12345678 to:
</p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td><b>Bajty</b></td><td><b>Opis</b></td></tr>
<tr class="tabf"><td><tt>0x04</tt></td><td>Flaga pobrania obrazka</td></tr>
<tr class="tabf"><td><tt>0x10 0x27 0x00 0x00</tt></td><td>Rozmiar obrazka w bajtach</td></tr>
<tr class="tabf"><td><tt>0x78 0x56 0x34 0x12</tt></td><td>Suma kontrolna</td></tr>
</table>

<p>
W odpowiedzi, drugi klient wysyła obrazek za pomocą wiadomości o zerowej
długości (należy pamiętać o kończącym bajcie o wartości <tt>0x00</tt>)
z dołączoną strukturą <tt>gg_msg_image_reply</tt>:
</p>

<div class="c">
<pre>struct gg_msg_image_reply {
	char flag;      	<i>/* 0x05 lub 0x06 */</i>
	int size;       	<i>/* rozmiar */</i>
	int crc32;      	<i>/* suma kontrolna */</i>
	char filename[];	<i>/* nazwa pliku (nie musi wystąpić) */</i>
	char image[];		<i>/* zawartość obrazka (nie musi wystąpić) */</i>
};</pre>
</div>

<p>
Jeśli długość struktury <tt>gg_msg_image_reply</tt> jest dłuższa niż 1909
bajtów, treść obrazka jest dzielona na kilka pakietów nie przekraczających
1909 bajtów. Pierwszy pakiet ma pole <tt>flag</tt> równe <tt>0x05</tt> i ma
wypełnione pole <tt>filename</tt>, a w kolejnych pole <tt>flag</tt> jest równe
<tt>0x06</tt> i pole <tt>filename</tt> w ogóle nie występuje (nawet bajt
zakończenia ciągu znaków).
</p>

<p>
Jeśli otrzymamy pakiet bez pola <tt>filename</tt> oraz <tt>image</tt>, oznacza
to, że klient nie posiada żądanego obrazka.
</p>

<a name="ch1.6.4"></a>
<h4>1.6.4. Potwierdzenie</h4>

<p>
Serwer po otrzymaniu wiadomości odsyła potwierdzenie, które przy okazji
mówi nam, czy wiadomość dotarła do odbiorcy czy została zakolejkowana
z powodu nieobecności. Otrzymujemy je w postaci pakietu:
</p>

<div class="c">
<pre>#define GG_SEND_MSG_ACK 0x0005
	
struct gg_send_msg_ack {
	int status;	<i>/* stan wiadomości */</i>
	int recipient;	<i>/* numer odbiorcy */</i>
	int seq;	<i>/* numer sekwencyjny */</i>
};</pre>
</div>

<p>
Numer sekwencyjny i numer adresata są takie same jak podczas wysyłania,
a stan wiadomości może być jednym z następujących:
</p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td><b>Etykieta</b></td><td><b>Wartość</b></td><td><b>Znaczenie</b></td></tr>
<tr class="tabf"><td><tt>GG_ACK_BLOCKED</tt></td><td><tt>0x0001</tt></td><td>Wiadomości nie przesłano (zdarza się przy wiadomościach zawierających adresy internetowe blokowanych przez serwer GG gdy odbiorca nie ma nas na liście)</td></tr>
<tr class="tabf"><td><tt>GG_ACK_DELIVERED</tt></td><td><tt>0x0002</tt></td><td>Wiadomość dostarczono</td></tr>
<tr class="tabf"><td><tt>GG_ACK_QUEUED</tt></td><td><tt>0x0003</tt></td><td>Wiadomość zakolejkowano</td></tr>
<tr class="tabf"><td><tt>GG_ACK_MBOXFULL</tt></td><td><tt>0x0004</tt></td><td>Wiadomości nie dostarczono. Skrzynka odbiorcza na serwerze jest pełna (20 wiadomości maks). Występuje tylko w trybie offline</td></tr>
<tr class="tabf"><td><tt>GG_ACK_NOT_DELIVERED</tt></td><td><tt>0x0006</tt></td><td>Wiadomości nie dostarczono. Odpowiedź ta występuje tylko w przypadku wiadomości klasy <tt>GG_CLASS_CTCP</tt></td></tr>
</table>

<hr />

<a name="ch1.7"></a>
<h3>1.7. Otrzymywanie wiadomości</h3>

<p>
Wiadomości serwer przysyła za pomocą pakietu:
</p>

<div class="c">
<pre>#define GG_RECV_MSG80 0x002e

struct gg_recv_msg80 {
	int sender;		<i>/* numer nadawcy */</i>
	int seq;		<i>/* numer sekwencyjny */</i>
	int time;		<i>/* czas nadania */</i>
	int class;		<i>/* klasa wiadomości */</i>
	int offset_plain;	<i>/* położenie treści czystym tekstem */</i>
	int offset_attributes;	<i>/* położenie atrybutów */</i>
	char html_message[];	<i>/* treść w formacie HTML (zakończona \0) */</i>
	char plain_message[];	<i>/* treść czystym tekstem (zakończona \0) */</i>
	char attributes[];	<i>/* atrybuty wiadomości */</i>
};</pre>

</div>

<p>
Czas nadania jest zapisany w postaci UTC, jako ilości sekund od 1 stycznia
1970r.
</p>

<p>
W przypadku pakietów &bdquo;konferencyjnych&rdquo; na końcu pakietu doklejona
jest struktura identyczna z <tt>gg_msg_recipients</tt> zawierająca pozostałych
rozmówców.
</p>

<a name="ch1.7.1"></a>
<h4>1.7.1. Potwierdzenie</h4>

<p>
Jeśli podczas logowania klient wyśle w polu <tt>features</tt> maskę bitową
<tt>0x00000400</tt>, to zobowiązuje się wysłać potwierdzenie po każdej odebranej
wiadomości. Wysyła je w postaci pakietu:
</p>

<div class="c">
<pre>#define GG_RECV_MSG_ACK 0x0046
	
struct gg_recv_msg_ack {
	int seq;	<i>/* numer sekwencyjny ostatnio odebranej wiadomości */</i>
};</pre>
</div>

<hr />

<a name="ch1.8"></a>
<h3>1.8. Powiadomienie o pisaniu (&quot;pisak&quot;)</h3>

<p>
Jeśli podczas logowania klient wyśle w polu <tt>features</tt> maskę bitową
<tt>0x00002000</tt>, to może wtedy informować drugą stronę o tym czy piszemy
wiadomość (oraz odbierać informacje czy druga strona coś pisze). Powiadomienia
wysyłamy/otrzymujemy tym samym pakietem:
</p>

<div class="c">
<pre>#define GG_TYPING_NOTIFY 0x0059

struct gg_typing_notify {
	short type;	<i>/* typ powiadomienia */</i>
	int uin;	<i>/* do/od kogo wysyłamy/odebraliśmy */</i>
};</pre>
</div>

<p>
Gdzie pole typ może przyjmować następujące stałe wartości:
</p>

<div class="c">
<pre>#define GG_TYPING_NOTIFY_TYPE_START	0x0001	<i>/* rozpoczelismy pisanie */</i>
#define GG_TYPING_NOTIFY_TYPE_STOP	0x0000	<i>/* pozbyliśmy się wiadomości */</i></pre>
</div>

<p>
Jeśli otrzymamy w polu type inną wartość, oznacza ona długość wpisanego przez
drugą stronę w pole wysyłki tekstu.
</p>

<hr />

<a name="ch1.9" id="ch1.9"></a>
<h3>1.9. Multilogowanie</h3>

<p>
Czyli wiele klientów, z różnych miejsc &mdash; na jednym numerze. Co prawda
do samego zalogowania się na dany numer wiele razy, wcale nie są potrzebne
specjalne modyfikacje. To jeśli chcemy obsługiwać synchronziację wysyłanych
wiadomości &mdash; obsługa dodatkowych pakietów będzie nam potrzebna. Aby
otrzymywać pakiety związane z tą funkcją w polu features przy logowaniu
dodajemy flagę <tt>0x00004000</tt>.
</p>

<a name="ch1.9.1" id="ch1.9.1"></a>
<h4>1.9.1. Synchronizacja wiadomości</h4>

<p>
Jeśli z innego klienta zostanie wysłana wiadomośc (z naszego numeru) to
otrzymamy pakiet:
</p>

<div class="c">
<pre>#define GG_RECV_OWN_MSG 0x005A
</pre>
</div>

<p>
O takiej strukturze jak <tt>gg_recv_msg80</tt>.
</p>

<a name="ch1.9.2" id="ch1.9.2"></a>
<h4>1.9.2. Informacje o innych połączeniach</h4>

<p>
Jeśli na nasz numer zaloguje się inny klient, lub kiedy my się logujemy,
a inny klient jest już zalogowany to dostaniemy pakiet:
</p>

<div class="c">
<pre>#define GG_MULTILOGON_INFO 0x005B

struct gg_multilogon_info {
	int count;	<i>/* ilość zalogowanych klientów / struktur gg_multilogon_item w tym pakiecie */</i>
	struct gg_multilogon_item items[];
};

struct gg_multilogon_item {
	int login_ip;		<i>/* IP z jakiego zalogowany jest dany klient */</i>
	int flags;		<i>/* to co podał w &quot;flags&quot; przy logowaniu */</i>
	int features;		<i>/* to co podał w &quot;features&quot; przy logowaniu */</i>
	int logon_time;		<i>/* kiedy zdalny klient się zalogował na nasz numerek */</i>
	long long conn_id;	<i>/* identyfikator polaczenia */</i>
	int unknown;		<i>/* nie wiemy co to, zawsze zero */</i>
	int client_name_size;	<i>/* rozmiar nazwy klieta uzytego po drugiej stronie */</i>
	char client_name[];	<i>/* nazwa klienta uzywanego w tym polaczeniu */</i>
};</pre>
</div>

<a name="ch1.9.3" id="ch1.9.3"></a>
<h4>1.9.3. Dostosowanie stanu</h4>

<p>
Protokół GG udostępnia możliwość dostosowania stanu
&bdquo;nowo-połaczonego&rdquo; klienta do tego jaki mają ustawione już
zalogowane na naszym numerze komunikatory. W tym celu w pakiecie
<tt>gg_login80</tt> w polu &bdquo;status&rdquo; dodajemy flagę <tt>0x0400</tt>.
Jeśli to zrobimy, w momencie gdy łączymy się na numer na którym jest już
obecny inny klient, stan który podajemy w pakiecie logowania zostanie przez
serwer zignorowany. W takiej sytuacji powinnismy zaprezentować użytkownikowi
stan przysłany do nas pakietem <tt>GG_NOTIFY_REPLY80</tt> gdzie
&bdquo;uin&rdquo; będzie zawierał nasz numer.
</p>

<p>
W wypadku kiedy &bdquo;inny&rdquo; klient zmieni stan naszego numeru także
dostaniemy <tt>GG_NOTIFY_REPLY80</tt> z naszym nowym stanem.
</p>

<a name="ch1.9.3" id="ch1.9.4"></a>
<h4>1.9.4. Rozłączenie zdalnego klienta</h4>

<p>
W razie kiedy chcemy rozłączyć którąś z sesji (podanych
w <tt>GG_MULTILOGON_INFO</tt>), wysyłamy pakiet:
</p>

<div class="c">
<pre>#define GG_MULTILOGON_DISCONNECT 0x0062

struct gg_multilogon_disconnect {
	long long conn_id; <i>/* id połączenia dostarczone w gg_multilogon_info */</i>
};</pre>
</div>

<hr />

<a name="ch1.10" id="ch1.10"></a>
<h3>1.10. Ping, pong</h3>

<p>
Od czasu do czasu klient wysyła pakiet do serwera, by oznajmić, że połączenie
jeszcze jest utrzymywane. Jeśli serwer nie dostanie takiego pakietu w
przeciągu 5 minut, zrywa połączenie. To, czy klient dostaje odpowiedź
zmienia się z wersji na wersję, więc najlepiej nie polegać na tym.
</p>

<div class="c">
<pre>#define GG_PING 0x0008

#define GG_PONG 0x0007</pre>
</div>

<hr />

<a name="ch1.11" id="ch1.11"></a>
<h3>1.11. Rozłączenie</h3>

<p>
Jeśli serwer zechce nas rozłączyć, wyśle wcześniej pusty pakiet:
</p>

<div class="c">
<pre>#define GG_DISCONNECTING 0x000b</pre>
</div>

<p>
Ma to miejsce, gdy próbowano zbyt wiele razy połączyć się z nieprawidłowym
hasłem (wtedy pakiet zostanie wysłany w odpowiedzi na GG_LOGIN70), lub gdy 
równocześnie połączy się drugi klient z tym samym numerem (nowe połączenie 
ma wyższy priorytet).
</p>

<p>
W pewnych wersjach protokołu (prawdopodobnie od <tt>0x29</tt> do okolic
Nowego Gadu-Gadu), po wysłaniu pakietu zmieniającego status na niedostępny,
serwer przysyła pakiet:
</p>

<div class="c">
<pre>#define GG_DISCONNECT_ACK 0x000d</pre>
</div>

<p>
Jest to potwierdzenie, że serwer odebrał pakiet zmiany stanu i klient może
zakończyć połączenie mając pewność, że zostanie ustawiony żądany opis. Klient
przedstawiający się jako Gadu-Gadu 10 takiego pakietu już nie dostaje &mdash;
serwer sam zrywa połączenie po zmianie stanu na niedostępny.
</p>

<hr />

<a name="ch1.12"></a>
<h3>1.12. Wiadomości systemowe</h3>

<p>
Od wersji 7.7 serwer może wysyłać nam wiadomości systemowe przy pomocy pakietu:
</p>

<div class="c">
<pre>#define GG_XML_EVENT 0x0027</pre>
</div>

<p>
Wiadomość systemowa zawiera kod XML zakodowany w UTF-8 z informacjami dotyczącymi 
np. przedłużenia konta w mobilnym GG, czy nowej wiadomości na poczcie głosowej. 
Przykładowy kod:
</p>

<div class="example">
<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;event xmlns:ev="www.gadu-gadu.pl/Event/1.0" id="" type="realtime" creation_time="1194732873" ttl="60"&gt;
  &lt;ev:actions&gt;
    &lt;ev:showMessage&gt;
      &lt;ev:text&gt;Wejdź na stronę EKG&lt;/ev:text&gt;

      &lt;ev:executeHtml url="ekg.chmurka.net" /&gt;
   &lt;/ev:showMessage&gt;
  &lt;/ev:actions&gt;
&lt;/event&gt;</pre>
</div>

<hr />

<a name="ch1.13"></a>
<h3>1.13. Wiadomości GG_XML_ACTION</h3>

<div class="c">
<pre>#define GG_XML_ACTION 0x002c</pre>
</div>

<a name="ch1.13.1"></a>
<h4>1.13.1 Wiadomości GGLive</h4>

<div class="check">
Opisać usługi http://life.gadu-gadu.pl/<br/>
Logowanie OAuth: /login?oauth_consumer_key=UIN&amp;oauth_nonce=....&amp;oauth_signature=...&amp;oauth_signature_method=HMAC-SHA1&amp;oauth_timestamp=...&amp;oauth_token=....&amp;oauth_version=1.0<br/>
Wysyłanie: POST /send/message/?USER_IS_AUTHENTICATED=1&amp;uin=UIN&amp;token=TOKEN<br/>
message=Testowa+wiadomo%C5%9B%C4%87&amp;send=Wy%C5%9Blij<br/>
</div>

<p>
Przykładowa otrzymana wiadomość:
</p>
<div class="example">
<pre>&lt;events&gt;
  &lt;event id="13106118792229117994"&gt;
  &lt;type&gt;1&lt;/type&gt;
  &lt;sender&gt;7496195&lt;/sender&gt;
  &lt;time&gt;1243461221&lt;/time&gt;
  &lt;bodyXML&gt;
    &lt;serviceID&gt;lifestreaming&lt;/serviceID&gt;
    &lt;msg&gt;&lt;![CDATA[Testowa wiadomość]]&gt;&lt;/msg&gt;
    &lt;link isLogin="0"&gt;&lt;/link&gt;
    &lt;creationTime&gt;1243461221&lt;/creationTime&gt;
  &lt;/bodyXML&gt;
 &lt;/event&gt;
&lt;/events&gt;
</pre>
</div>

<a name="ch1.13.2"></a>
<h4>1.13.2 Zmiana avatara przez znajomego</h4>

<p>Przykładowa informacja:</p>
<div class="example">
<pre>&lt;events&gt;
  &lt;event id="13095886332244853765"&gt;
    &lt;type&gt;28&lt;/type&gt;
    &lt;sender&gt;3732&lt;/sender&gt;
    &lt;time&gt;1245843651&lt;/time&gt;
    &lt;body&gt;&lt;/body&gt;
    &lt;bodyXML&gt;
      &lt;smallAvatar&gt;http://media6.mojageneracja.pl/oiytwyurtp/avatar/ueuivsp.jpg&lt;/smallAvatar&gt;
    &lt;/bodyXML&gt;
  &lt;/event&gt;
&lt;/events&gt;
</pre>
</div>

<a name="ch1.13.3"></a>
<h4>1.13.3 Nowy wpis na blogu znajomego</h4>

<p>Przykładowa informacja:</p>
<div class="example">
<pre>&lt;events&gt;
  &lt;event id="13095868082578904423"&gt;
    &lt;type&gt;7&lt;/type&gt;
    &lt;sender&gt;3732&lt;/sender&gt;
    &lt;time&gt;1245847900&lt;/time&gt;
    &lt;bodyXML&gt;
      &lt;serviceID&gt;MG&lt;/serviceID&gt;
      &lt;msg&gt;&lt;![CDATA[Doda\u0139, wpis do bloga]]&gt;&lt;/msg&gt;
      &lt;link isLogin="1"&gt;http://www.mojageneracja.pl/7233258/blog/4877775414a42215b91fd7/0&lt;/link&gt;
      &lt;creationTime&gt;1245847900&lt;/creationTime&gt;
    &lt;/bodyXML&gt;
 &lt;/event&gt;
&lt;/events&gt;
</pre>
</div>

<a name="ch1.13.4"></a>
<h4>1.13.4 Opisy graficzne</h4>

<p>
Serwer Gadu-Gadu po kupnie opisu graficznego na stronie
<a href="http://gadudodatki.pl/opisygraficzne">GaduDodatki</a> przesyła nam
pakiet <tt>GG_XML_EVENT</tt>:
</p>

<p>Przykładowy opis graficzny: Krol Popu</p>
<div class="example">
<pre>
&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;activeUserbarEventList&gt;
  &lt;activeUserbarEvent&gt;
     &lt;userbarId&gt;Krol Popu&lt;/userbarId&gt;
     &lt;beginTime&gt;2009-07-06T12:30:43+02:00&lt;/beginTime&gt;
     &lt;expireTime&gt;2009-08-05T12:30:43+02:00&lt;/expireTime&gt;
     &lt;userbarOwner&gt;7496195&lt;/userbarOwner&gt;
     &lt;userbarBuyer&gt;7496195&lt;/userbarBuyer&gt;
   &lt;/activeUserbarEvent&gt;
&lt;/activeUserbarEventList&gt;
</pre>
</div>

<p>
Użytkownik powinien zostać zapytany czy chce ustawić ten opis i jeśli tak, to wysyłany jest pakiet GG_NEW_STATUS80.
</p>

<p>Przykładowe ustawienie opisu graficznego: Krol Popu</p>
<div class="example">
<pre>
struct gg_new_status80 krol_popu = { 
	.status           = GG_STATUS_DESCR_MASK | GG_STATUS_IMAGE_MASK | status;
	.flags            = 0x03;
	.description_size = 9;
	.description      = "Krol Popu";
};</pre>
</div>

<p>
Gdy użytkownik ma ustawiony opis graficzny (flaga <tt>GG_STATUS_IMAGE_MASK</tt>)
możemy pobrać archiwum spod adresu <tt>http://www.gadudodatki.pl/userbar/get/id/</tt>
</p>

<p>
Dla przykładowego Króla Popu jest to adres <tt>http://www.gadudodatki.pl/userbar/get/id/Krol%20Popu</tt>
</p>

<hr />

<a name="ch1.14"></a>
<h3>1.14. Katalog publiczny</h3>

<div class="check">
Nowe Gadu-Gadu korzysta z OAutha do odczytu oraz zmian danych w katalogu, API opisane jest na:
<a href="http://dev.gadu-gadu.pl/api/pages/gaduapi.html">http://dev.gadu-gadu.pl/api/pages/gaduapi.html</a>
</div>

<p></p>

<div class="check">
Nowe Gadu-Gadu korzysta z wyszukiwarki dostępnej na: <a href="http://ipubdir.gadu-gadu.pl/ngg/">http://ipubdir.gadu-gadu.pl/ngg/</a><br />
Starsza wersja: <a href="http://ipubdir.gadu-gadu.pl/">http://ipubdir.gadu-gadu.pl</a>
</div>

<p>
Od wersji 5.0.2 zmieniono sposób dostępu do katalogu publicznego &mdash; stał
się częścią sesji, zamiast osobnej sesji HTTP. Aby obsługiwać wyszukiwanie
osób, odczytywanie własnych informacji lub ich modyfikację należy użyć
następującego typu pakietu:
</p>

<div class="c">
<pre>#define GG_PUBDIR50_REQUEST 0x0014
	
struct gg_pubdir50 {
	char type;
	int seq;
	char request[];
};</pre>
</div>

<p>
Pole <tt>type</tt> oznacza rodzaj zapytania:
</p>

<div class="c">
<pre>#define GG_PUBDIR50_WRITE 0x01
#define GG_PUBDIR50_READ 0x02
#define GG_PUBDIR50_SEARCH 0x03</pre>
</div>

<p>
Pole <tt>seq</tt> jest numerem sekwencyjnym zapytania, różnym od zera,
zwracanym również
w wyniku. Oryginalny klient tworzy go na podstawie aktualnego czasu.
<tt>request</tt> zawiera parametry zapytania. Ilość jest dowolna. Każdy
parametr jest postaci <tt>"<b>nazwa</b>\0<b>wartość</b>\0"</tt>, tzn.
nazwa od wartości są oddzielone znakiem o kodzie 0, podobnie jak kolejne
parametry od siebie. Możliwe parametry zapytania to:
</p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td><b>Etykieta</b></td><td><b>Wartość</b></td><td><b>Znaczenie</b></td></tr>
<tr class="tabf"><td><tt>GG_PUBDIR50_UIN</tt></td><td><tt>FmNumber</tt></td><td>Numer szukanej osoby</td></tr>
<tr class="tabf"><td><tt>GG_PUBDIR50_FIRSTNAME</tt></td><td><tt>firstname</tt></td><td>Imię</td></tr>
<tr class="tabf"><td><tt>GG_PUBDIR50_LASTNAME</tt></td><td><tt>lastname</tt></td><td>Nazwisko</td></tr>
<tr class="tabf"><td><tt>GG_PUBDIR50_NICKNAME</tt></td><td><tt>nickname</tt></td><td>Pseudonim</td></tr>
<tr class="tabf"><td><tt>GG_PUBDIR50_BIRTHYEAR</tt></td><td><tt>birthyear</tt></td><td>Rok urodzenia. Jeśli chcemy szukać osób z danego przedziału, podajemy rok początkowy i końcowy, oddzielone spacją. Na przykład &bdquo;<tt>1980 1985</tt>&rdquo;.</td></tr>
<tr class="tabf"><td><tt>GG_PUBDIR50_CITY</tt></td><td><tt>city</tt></td><td>Miejscowość</td></tr>
<tr class="tabf"><td><tt>GG_PUBDIR50_GENDER</tt></td><td><tt>gender</tt></td><td>Płeć. Jeśli szukamy kobiet, ma wartość &bdquo;<tt>1</tt>&rdquo; (stała <tt>GG_PUBDIR50_GENDER_FEMALE</tt>). Jeśli mężczyzn, ma wartość &bdquo;<tt>2</tt>&rdquo; (stała <tt>GG_PUBDIR50_GENDER_MALE</tt>). W przypadku pobierania lub ustawiania informacji o sobie stałe mają odwrócone znaczenia (stałe <tt>GG_PUBDIR50_GENDER_SET_FEMALE</tt> i <tt>GG_PUBDIR50_GENDER_SET_MALE</tt>)</td></tr>
<tr class="tabf"><td><tt>GG_PUBDIR50_ACTIVE</tt></td><td><tt>ActiveOnly</tt></td><td>Jeśli szukamy tylko dostępnych osób, ma mieć wartość &bdquo;<tt>1</tt>&rdquo; (stała <tt>GG_PUBDIR50_ACTIVE_TRUE</tt>).</td></tr>
<tr class="tabf"><td><tt>GG_PUBDIR50_FAMILYNAME</tt></td><td><tt>familyname</tt></td><td>Nazwisko panieńskie. Ma znaczenie tylko przy ustawianiu własnych danych.</td></tr>
<tr class="tabf"><td><tt>GG_PUBDIR50_FAMILYCITY</tt></td><td><tt>familycity</tt></td><td>Miejscowość pochodzenia. Ma znaczenie tylko przy ustawianiu własnych danych.</td></tr>
<tr class="tabf"><td><tt>GG_PUBDIR50_START</tt></td><td><tt>fmstart</tt></td><td>Numer, od którego rozpocząć wyszukiwanie. Ma znaczenie, gdy kontynuujemy wyszukiwanie.</td></tr>
</table>

<p>
Treść przykładowego zapytania (pomijając pola <tt>type</tt> i <tt>seq</tt>) znajduje się poniżej. Szukano dostępnych kobiet o imieniu Ewa z Warszawy. Znaki o kodzie 0 zastąpiono kropkami.
</p>

<div class="example">
<pre>firstname.Ewa.city.Warszawa.gender.1.ActiveOnly.1.</pre>
</div>

<p>
Wynik zapytania zostanie zwrócony za pomocą pakietu:
</p>

<div class="c">
<pre>#define GG_PUBDIR50_REPLY 0x000e
	
struct gg_pubdir50_reply {
	char type;
	int seq;
	char reply[];
};</pre>
</div>

<p>
Pole <tt>type</tt> poza wartościami takimi jak przy pakiecie typu
<tt>GG_PUBDIR50_REQUEST</tt> może przyjąć jeszcze wartość oznaczającą
odpowiedź wyszukiwania:
</p>

<div class="c">
<pre>#define GG_PUBDIR50_SEARCH_REPLY 0x05</pre>
</div>

<p>
Wyniki są zbudowane identycznie jak w przypadku zapytań, z tą różnicą, że
kolejne osoby oddzielane pustym polem: <tt>"<b>parametr</b>\0<b>wartość</b>\0\0<b>parametr</b>\0<b>wartość</b>\0"</tt>.
</p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td><b>Etykieta</b></td><td><b>Wartość</b></td><td><b>Znaczenie</b></td></tr>
<tr class="tabf"><td><tt>GG_PUBDIR50_STATUS</tt></td><td><tt>FmStatus</tt></td><td>Stan szukanej osoby</td></tr>
<tr class="tabf"><td>&nbsp;</td><td><tt>nextstart</tt></td><td>Pole występujące w ostatnim wyniku, określające, od jakiego numeru należy rozpocząć wyszukiwanie, by otrzymać kolejną porcję danych. Podaje się go w zapytaniu jako parametr &bdquo;<tt>start</tt>&rdquo;.</td></tr>
</table>

<p>
Przykładowy wynik zawierający dwie znalezione osoby:
</p>

<div class="example">
<pre>FmNumber.12345.FmStatus.1.firstname.Adam.nickname.Janek.birthyear.1979.city.Wzdów
..FmNumber.3141592.FmStatus.5.firstname.Ewa.nickname.Ewcia.birthyear.1982.city.Gd
dańsk..nextstart.0.</pre>
</div>

<p>
Wyszukiwanie <b>nie zwraca</b> nazwisk i płci znalezionych osób.
</p>

<hr />

<a name="ch1.15"></a>
<h3>1.15. Lista kontaktów</h3>

<div class="check">
Sprawdzić czy wszystkie #define dalej są potrzebne
</div>

<p>
Od wersji 6.0 lista kontaktów na serwerze stała częścią sesji, zamiast
osobnej sesji HTTP. Aby wysłać lub pobrać listę kontaktów z serwera należy
użyć pakietu:
</p>

<div class="c">
<pre>#define GG_USERLIST100_REQUEST 0x0040
	
struct gg_userlist100_request {
	char type;		<i>/* rodzaj zapytania */</i>
	int version;		<i>/* numer ostatniej znanej wersji listy kontaktów bądź 0 */</i>
	char format_type;	<i>/* rodzaj formatu listy kontaktów */</i>
	char unknown1;		<i>/* zawsze 0x01 */</i>
	char request[];		<i>/* treść (nie musi wystąpić) */</i>
};</pre>
</div>

<p>
Pole <tt>type</tt> oznacza rodzaj zapytania:
</p>

<div class="c">
<pre>#define GG_USERLIST100_PUT 0x00		<i>/* eksport listy */</i>
#define GG_USERLIST100_GET 0x02		<i>/* import listy */</i></pre>
</div>

<p>
Pole <tt>format_type</tt> oznacza typ formatu listy kontaktów:
</p>

<div class="c">
<pre>#define GG_USERLIST100_FORMAT_TYPE_NONE 0x00        <i>/* brak treści listy kontaktów */</i>
#define GG_USERLIST100_FORMAT_TYPE_GG70 0x01        <i>/* format listy kontaktów zgodny z Gadu-Gadu 7.0 */</i>
#define GG_USERLIST100_FORMAT_TYPE_GG100 0x02       <i>/* format listy kontaktów zgodny z Gadu-Gadu 10.0 */</i>
</div>

<p>
Typ <tt>GG_USERLIST100_FORMAT_TYPE_NONE</tt> ma sens wyłącznie w przypadku
importu listy kontaktów. Po jego użyciu serwer wysyła odpowiedź zawierającą
numer wersji listy kontaktów, ale bez samej listy kontaktów. Oryginalny klient
jednak w ogóle nie wykorzystuje tego sposobu.
</p>

<p>
W przypadku eksportu listy kontaktów, pole <tt>request</tt>, o ile zdefiniowano typ jako <tt>GG_USERLIST100_FORMAT_TYPE_GG100</tt>, zawiera dokument
XML opisany na stronie
<a href="http://dev.gadu-gadu.pl/api/pages/formaty_plikow.html">http://dev.gadu-gadu.pl/api/pages/formaty_plikow.html</a>. Zawartość tego pola musi być skompresowana algorytmem 
<a href="http://pl.wikipedia.org/wiki/Deflate">Deflate</a>. Wolnodostępna
implementacja algorytmu, używana również przez oryginalnego klienta, znajduje
się w biblotece <a href="http://www.zlib.net/">zlib</a>. Oryginalny klient używa najwyższego stopnia kompresji.
</p>

<p>
Na zapytania dotyczące listy kontaktów serwer odpowiada pakietem:
</p>

<div class="c">
<pre>#define GG_USERLIST100_REPLY 0x0041
	
struct gg_userlist100_reply {
	char type;		<i>/* rodzaj odpowiedzi */</i>
	int version;		<i>/* numer wersji listy kontaktów aktualnie przechowywanej przez serwer */</i>
	char format_type;	<i>/* rodzaj przesyłanego typu formatu listy kontaktów */</i>
	char unknown1;		<i>/* zawsze 0x01 */</i>
	char reply[];		<i>/* treść (nie musi wystąpić) */</i>
};</pre>
</div>

<p>
Pole <tt>type</tt> oznacza rodzaj odpowiedzi:
</p>

<div class="c">
<pre>#define GG_USERLIST100_REPLY_LIST 0x00       <i>/* w odpowiedzi znajduje się aktualna lista kontaktów na serwerze */</i>
#define GG_USERLIST100_REPLY_UPTODATE 0x01   <i>/* komunikat o tym, że lista kontaktów jest już zsynchronizowana */</i>
#define GG_USERLIST100_REPLY_ACK 0x10        <i>/* potwierdzenie odebrania nowej wersji listy kontaktów */</i>
#define GG_USERLIST100_REPLY_REJECT 0x12     <i>/* odmowa przyjęcia nowej wersji listy kontaktów z powodu
                                                niezgodności numeru wersji listy kontaktów */</i></pre>
</div>

<p>
W przypadku importu w polu <tt>request</tt> niekoniecznie musi znajdować się
lista kontaktów w takiej samej postaci, w jakiej ją umieszczono. Serwer stara się
utrzymywać obie wersje listy kontaktów (tzn. <tt>GG_USERLIST100_FORMAT_TYPE_GG70</tt>
oraz <tt>GG_USERLIST100_FORMAT_TYPE_GG100</tt>) w zgodności, dlatego po wysłaniu
jednej z nich serwer automatycznie modyfikuje drugą. W przypadku wysłania listy
kontaktów w formacie niezgodnym z zadeklarowanym w polu <tt>format_type</tt>,
serwer usunie istniejącą listę kontaktów, ale nie zachowa przesyłanej i zostanie
na nim pusta lista.
</p>

<p>
Aby usunąć listę kontaktów z serwera oryginalny klient wysyła spację jako
listę kontaktów czego wynikiem jest pole <tt>request</tt> o zawartości:
</p>

<div class="example">
<pre>78 da 53 00 00 00 21 00 21</pre>
</div>

<p>
W celu sprawnej synchronizacji listy kontaktów między różnymi instalacjami klienta sieci,
serwer wersjonuje listę kontaktów i pozwala ją nadpisać tylko w przypadku, gdy zadeklarujemy
znajomość jej ostatniej wersji. Serwer w pakiecie <tt>GG_USERLIST100_REPLY</tt> w polu
<tt>version</tt> zawsze przesyła numer ostatniej znanej mu wersji listy kontaktów, przy czym
w przypadku <tt>GG_USERLIST100_REPLY_ACK</tt> jest to nowo zaakceptowana przed chwilą wysłana
wersja. Wysyłając listę kontaktów, należy w polu <tt>version</tt> umieścić numer ostatniej
znanej wersji listy kontaktów. Zostanie ona zaakceptowana tylko jeśli jest to również ostatnia
znana serwerowi wersja. W przypadku importu listy przesyłany numer wersji nie ma znaczenia,
a oryginalny klient wysyła tu 0.
</p>

<p>
W czasie istnienia sesji po każdej zmianie listy kontaktów na serwerze, również jeśli została
ona dokonana w obrębie innej sesji mulilogowania, serwer wysyła informacje o nowej wersji za
pomocą pakietu:
</p>

<div class="c">
<pre>#define GG_USERLIST100_VERSION 0x005c
	
struct gg_userlist100_version {
	int version;		<i>/* numer wersji listy kontaktów */</i>
};</pre>
</div>

<p>
Należy zwrócić uwagę na fakt, że pakiet z informacją o nowej wersji listy kontaktów może przyjść
przed pakietem <tt>GG_USERLIST100_REPLY</tt> z informacją o akceptacji listy kontaktów.
</p>

<hr />

<a name="ch1.16"></a>
<h3>1.16. Indeks pakietów</h3>

<p>
Pakiety wysyłane:
</p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td><b>Wartość</b></td><td><b>Etykieta</b></td><td><b>Znaczenie</b></td></tr>
<tr class="tabf2"><td><tt>0x0002</tt></td><td><tt>GG_NEW_STATUS</tt></td><td>Zmiana stanu przed GG 8.0</td></tr>
<tr class="tabf2"><td><tt>0x0007</tt></td><td><tt>GG_PONG</tt></td><td>Pong</td></tr>
<tr class="tabf"><td><tt>0x0008</tt></td><td><tt>GG_PING</tt></td><td>Ping</td></tr>
<tr class="tabf2"><td><tt>0x000b</tt></td><td><tt>GG_SEND_MSG</tt></td><td>Wysłanie wiadomości przed GG 8.0</td></tr>
<tr class="tabf2"><td><tt>0x000c</tt></td><td><tt>GG_LOGIN</tt></td><td>Logowanie przed GG 6.0</td></tr>
<tr class="tabf"><td><tt>0x000d</tt></td><td><tt>GG_ADD_NOTIFY</tt></td><td>Dodanie do listy kontaktów</td></tr>
<tr class="tabf"><td><tt>0x000e</tt></td><td><tt>GG_REMOVE_NOTIFY</tt></td><td>Usunięcie z listy kontaktów</td></tr>
<tr class="tabf"><td><tt>0x000f</tt></td><td><tt>GG_NOTIFY_FIRST</tt></td><td>Początkowy fragment listy kontaktów większej niż 400 wpisów</td></tr>
<tr class="tabf"><td><tt>0x0010</tt></td><td><tt>GG_NOTIFY_LAST</tt></td><td>Ostatni fragment listy kontaktów</td></tr>
<tr class="tabf"><td><tt>0x0012</tt></td><td><tt>GG_LIST_EMPTY</tt></td><td>Lista kontaktów jest pusta</td></tr>
<tr class="tabf2"><td><tt>0x0013</tt></td><td><tt>GG_LOGIN_EXT</tt></td><td>Logowanie przed GG 6.0</td></tr>
<tr class="tabf"><td><tt>0x0014</tt></td><td><tt>GG_PUBDIR50_REQUEST</tt></td><td>Zapytanie katalogu publicznego</td></tr>
<tr class="tabf2"><td><tt>0x0015</tt></td><td><tt>GG_LOGIN60</tt></td><td>Logowanie przed GG 7.7</td></tr>
<tr class="tabf2"><td><tt>0x0016</tt></td><td><tt>GG_USERLIST_REQUEST</tt></td><td>Zapytanie listy kontaktów na serwerze przed Nowym Gadu-Gadu</td></tr>
<tr class="tabf2"><td><tt>0x0019</tt></td><td><tt>GG_LOGIN70</tt></td><td>Logowanie przed GG 8.0</td></tr>
<tr class="tabf"><td><tt>0x001f</tt></td><td><tt>GG_DCC7_INFO</tt></td><td></td></tr>
<tr class="tabf"><td><tt>0x0020</tt></td><td><tt>GG_DCC7_NEW</tt></td><td>Informacje o chęci nawiązania połączenia DCC</td></tr>
<tr class="tabf"><td><tt>0x0021</tt></td><td><tt>GG_DCC7_ACCEPT</tt></td><td>Zaakceptowanie połączenia DCC</td></tr>
<tr class="tabf"><td><tt>0x0022</tt></td><td><tt>GG_DCC7_REJECT</tt></td><td>Odrzucenie połączenia DCC</td></tr>
<tr class="tabf"><td><tt>0x0023</tt></td><td><tt>GG_DCC7_ID_REQUEST</tt></td><td></td></tr>
<tr class="tabf2"><td><tt>0x0024</tt></td><td><tt>GG_DCC7_DUNNO1</tt></td><td></td></tr>
<tr class="tabf"><td><tt>0x0025</tt></td><td><tt>GG_DCC7_ABORT</tt></td><td></td></tr>
<tr class="tabf2"><td><tt>0x0028</tt></td><td><tt>GG_NEW_STATUS80BETA</tt></td><td>Zmiana stanu przed Nowym Gadu-Gadu</td></tr>
<tr class="tabf2"><td><tt>0x0029</tt></td><td><tt>GG_LOGIN80BETA</tt></td><td>Logowanie przed Nowym Gadu-Gadu</td></tr>
<tr class="tabf"><td><tt>0x002d</tt></td><td><tt>GG_SEND_MSG80</tt></td><td>Wysłanie wiadomości</td></tr>
<tr class="tabf2"><td><tt>0x002f</tt></td><td><tt>GG_USERLIST_REQUEST80</tt></td><td>Zapytanie listy kontaktów na serwerze przed Gadu-Gadu 10</td></tr>
<tr class="tabf"><td><tt>0x0031</tt></td><td><tt>GG_LOGIN80</tt></td><td>Logowanie</td></tr>
<tr class="tabf"><td><tt>0x0038</tt></td><td><tt>GG_NEW_STATUS80</tt></td><td>Zmiana stanu</td></tr>
<tr class="tabf"><td><tt>0x0040</tt></td><td><tt>GG_USERLIST100_REQUEST</tt></td><td>Zapytanie listy kontaktów na serwerze</td></tr>
<tr class="tabf"><td><tt>0x0046</tt></td><td><tt>GG_RECV_MSG_ACK</tt></td><td>Potwierdzenie odebrania wiadomości przez klienta</td></tr>
<tr class="tabf"><td><tt>0x0059</tt></td><td><tt>GG_TYPING_NOTIFY</tt></td><td>Powiadomienie o pisaniu</td></tr>
<tr class="tabf"><td><tt>0x0062</tt></td><td><tt>GG_OWN_DISCONNECT</tt></td><td>Rozłączenie zdalnego klienta</td></tr>
</table>

<p>
Pakiety odbierane:
</p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td><b>Wartość</b></td><td><b>Etykieta</b></td><td><b>Znaczenie</b></td></tr>
<tr class="tabf"><td><tt>0x0001</tt></td><td><tt>GG_WELCOME</tt></td><td>Liczba do wyznaczenie hashu hasła</td></tr>
<tr class="tabf2"><td><tt>0x0002</tt></td><td><tt>GG_STATUS</tt></td><td>Zmiana stanu przed GG 6.0</td></tr>
<tr class="tabf2"><td><tt>0x0003</tt></td><td><tt>GG_LOGIN_OK</tt></td><td>Logowanie powiodło się przed Nowym Gadu-Gadu</td></tr>
<tr class="tabf"><td><tt>0x0005</tt></td><td><tt>GG_SEND_MSG_ACK</tt></td><td>Potwierdzenie wiadomości</td></tr>
<tr class="tabf2"><td><tt>0x0007</tt></td><td><tt>GG_PONG</tt></td><td>Pong</td></tr>
<tr class="tabf2"><td><tt>0x0008</tt></td><td><tt>GG_PING</tt></td><td>Ping</td></tr>
<tr class="tabf"><td><tt>0x0009</tt></td><td><tt>GG_LOGIN_FAILED</tt></td><td>Logowanie nie powiodło się</td></tr>
<tr class="tabf2"><td><tt>0x000a</tt></td><td><tt>GG_RECV_MSG</tt></td><td>Przychodząca wiadomość przed GG 8.0</td></tr>
<tr class="tabf"><td><tt>0x000b</tt></td><td><tt>GG_DISCONNECTING</tt></td><td>Zerwanie połączenia</td></tr>
<tr class="tabf2"><td><tt>0x000c</tt></td><td><tt>GG_NOTIFY_REPLY</tt></td><td>Stan listy kontaktów przed GG 6.0</td></tr>
<tr class="tabf"><td><tt>0x000d</tt></td><td><tt>GG_DISCONNECT_ACK</tt></td><td>Zerwanie połączenia po zmianie stanu na niedostępny</td></tr>
<tr class="tabf"><td><tt>0x000e</tt></td><td><tt>GG_PUBDIR50_REPLY</tt></td><td>Odpowiedź katalogu publicznego</td></tr>
<tr class="tabf2"><td><tt>0x000f</tt></td><td><tt>GG_STATUS60</tt></td><td>Zmiana stanu przed GG 7.7</td></tr>
<tr class="tabf2"><td><tt>0x0010</tt></td><td><tt>GG_USERLIST_REPLY</tt></td><td>Odpowiedź listy kontaktów na serwerze przed nowym Gadu-Gadu</td></tr>
<tr class="tabf2"><td><tt>0x0011</tt></td><td><tt>GG_NOTIFY_REPLY60</tt></td><td>Stan listy kontaktów przed GG 7.7</td></tr>
<tr class="tabf"><td><tt>0x0014</tt></td><td><tt>GG_NEED_EMAIL</tt></td><td>Logowanie powiodło się, ale powinniśmy uzupełnić adres e-mail w katalogu publicznym</td></tr>
<tr class="tabf2"><td><tt>0x0016</tt></td><td><tt>GG_LOGIN_HASH_TYPE_INVALID</tt></td><td>Dany rodzaj hashowania hasła jest nieobsługiwany przez serwer</td></tr>
<tr class="tabf2"><td><tt>0x0017</tt></td><td><tt>GG_STATUS77</tt></td><td>Zmiana stanu przed GG 8.0</td></tr>
<tr class="tabf2"><td><tt>0x0018</tt></td><td><tt>GG_NOTIFY_REPLY77</tt></td><td>Stan listy kontaktów przed GG 8.0</td></tr>
<tr class="tabf"><td><tt>0x001f</tt></td><td><tt>GG_DCC7_INFO</tt></td><td></td></tr>
<tr class="tabf"><td><tt>0x0020</tt></td><td><tt>GG_DCC7_NEW</tt></td><td>Informacje o chęci nawiązania połączenia DCC</td></tr>
<tr class="tabf"><td><tt>0x0021</tt></td><td><tt>GG_DCC7_ACCEPT</tt></td><td>Zaakceptowanie połączenia DCC</td></tr>
<tr class="tabf"><td><tt>0x0022</tt></td><td><tt>GG_DCC7_REJECT</tt></td><td>Odrzucenie połączenia DCC</td></tr>
<tr class="tabf"><td><tt>0x0023</tt></td><td><tt>GG_DCC7_ID_REPLY</tt></td><td></td></tr>
<tr class="tabf"><td><tt>0x0025</tt></td><td><tt>GG_DCC7_ABORTED</tt></td><td></td></tr>
<tr class="tabf"><td><tt>0x0027</tt></td><td><tt>GG_XML_EVENT</tt></td><td>Odebrano wiadomość systemową</td></tr>
<tr class="tabf2"><td><tt>0x002a</tt></td><td><tt>GG_STATUS80BETA</tt></td><td>Zmiana stanu przed Nowym Gadu-Gadu</td></tr>
<tr class="tabf2"><td><tt>0x002b</tt></td><td><tt>GG_NOTIFY_REPLY80BETA</tt></td><td>Stan listy kontaktów przed Nowym Gadu-Gadu</td></tr>
<tr class="tabf"><td><tt>0x002c</tt></td><td><tt>GG_XML_ACTION</tt></td><td></td></tr>
<tr class="tabf"><td><tt>0x002e</tt></td><td><tt>GG_RECV_MSG80</tt></td><td>Przychodząca wiadomość</td></tr>
<tr class="tabf2"><td><tt>0x0030</tt></td><td><tt>GG_USERLIST_REPLY80</tt></td><td>Odpowiedź listy kontaktów na serwerze przed Gadu-Gadu 10</td></tr>
<tr class="tabf"><td><tt>0x0035</tt></td><td><tt>GG_LOGIN_OK80</tt></td><td>Logowanie powiodło się</td></tr>
<tr class="tabf"><td><tt>0x0036</tt></td><td><tt>GG_STATUS80</tt></td><td>Zmiana stanu</td></tr>
<tr class="tabf"><td><tt>0x0037</tt></td><td><tt>GG_NOTIFY_REPLY80</tt></td><td>Stan listy kontaktów</td></tr>
<tr class="tabf"><td><tt>0x0041</tt></td><td><tt>GG_USERLIST100_REPLY</tt></td><td>Odpowiedź listy kontaktów na serwerze</td></tr>
<tr class="tabf"><td><tt>0x0044</tt></td><td><tt>GG_USER_DATA</tt></td><td>Dodatkowe informacje o liście kontaktów</td></tr>
<tr class="tabf"><td><tt>0x0059</tt></td><td><tt>GG_TYPING_NOTIFY</tt></td><td>Powiadomienie o pisaniu</td></tr>
<tr class="tabf"><td><tt>0x005A</tt></td><td><tt>GG_OWN_MESSAGE</tt></td><td>Własne wiadomości z innych klientów</td></tr>
<tr class="tabf"><td><tt>0x005B</tt></td><td><tt>GG_OWN_RESOURCE_INFO</tt></td><td>Informacje o innych połączeniach na naszym numerze</td></tr>
<tr class="tabf"><td><tt>0x005C</tt></td><td><tt>GG_USERLIST100_VERSION</tt></td><td>Informacje o nowej wersji listy kontaktów</td></tr>
</table>

<hr />

<a name="ch2"></a>
<h2>2. Usługi HTTP</h2>

<a name="ch2.1"></a>
<h3>2.1. Format danych</h3>

<p>
Komunikacja z <tt>appmsg.gadu-gadu.pl</tt> metodą <tt>GET</tt> HTTP/1.0
została opisana w poprzednim rozdziale, pozostałe pakiety używają 
<tt>POST</tt> dla HTTP/1.0, a w odpowiedzi 1.1. Mają one postać:
</p>

<div class="http">
<pre>POST <b>ŚCIEŻKA</b> HTTP/1.0
Host: <b>HOST</b>
Content-Type: application/x-www-form-urlencoded
User-Agent: <b>AGENT</b>
Content-Length: <b>DŁUGOŚĆ</b>
Pragma: no-cache

<b>DANE</b></pre>
</div>

<p>
Gdzie <tt><b>AGENT</b></tt> to nazwa przeglądarki (na przykład <tt>Mozilla/4.0
(compatible; MSIE 5.0; Windows 98)</tt> lub inne, wymienione w rozdziale
<a href="#ch1.2">1.2</a>), <tt><b>DŁUGOŚĆ</b></tt> to długość bloku
<tt><b>DANE</b></tt> w znakach.
</p>

<p>
Jeśli będzie mowa o wysyłaniu danych do serwera, to chodzi o cały powyższy
pakiet, opisane zostaną tylko: <tt><b>HOST</b></tt>, <tt><b>ŚCIEŻKA</b></tt>
i <tt><b>DANE</b></tt>. Pakiet jest wysyłany na port 80. Gdy mowa o wysyłaniu
pól zapytania, mowa o <tt><b>DANE</b></tt> o wartości:
</p>

<div class="http">
<pre>pole1=wartość1&amp;pole2=wartość2&amp;...</pre>
</div>

<p>
Pamiętaj o zmianie kodowania na CP1250 i zakodowaniu danych do postaci URL
(na przykład funkcją typu <tt>urlencode</tt>).
</p>

<p>
Odpowiedzi serwera na powyższe zapytania mają mniej więcej postać:
</p>

<div class="http">
<pre>HTTP/1.1 200 OK
Server: Microsoft-IIS/5.0
Date: Mon, 01 Jul 2002 22:30:31 GMT
Connection: Keep-Alive
Content-Length: <b>DŁUGOŚĆ</b>
Content-Type: text/html
Set-Cookie: <b>COOKIE</b>
Cache-control: private

<b>ODPOWIEDŹ</b></pre>
</div>

<p>
Nagłówki nie są dla nas ważne. Można zauważyć tylko to, że czasami serwer
ustawia <tt><b>COOKIE</b></tt> np. &bdquo;<tt>ASPSESSIONIDQQGGGLJC=CAEKMBGDJCFBEOKCELEFCNKH; path=/</tt>&rdquo;. Pisząc dalej, że serwer &bdquo;odpowie wartością&rdquo; mowa
tylko o polu <b>ODPOWIEDŹ</b>. Kodowanie znaków w odpowiedzi to CP1250.
</p>

<hr />

<a name="ch2.2"></a>

<h3>2.2. Tokeny</h3> 

<p>
Prawdopodobnie ze względu na nadużycia i wykorzystywanie automatów
rejestrujących do polowań na &bdquo;złote numery GG&rdquo;, wprowadzono konieczność
autoryzacji za pomocą tokenu. Każda operacja zaczyna się od pobrania tokenu
z serwera, wyświetlenia użytkownikowi, odczytaniu jego wartości i wysłania
zapytania z identyfikatorem i wartością tokenu. Pobranie tokenu wygląda 
następująco:
</p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td width="20%"><b>Pole nagłówka</b></td><td width="80%"><b>Wartość</b></td></tr>
<tr class="tabf"><td><tt>HOST</tt></td><td><tt>register.gadu-gadu.pl</tt></td></tr>
<tr class="tabf"><td><tt>ŚCIEŻKA</tt></td><td><tt>/appsvc/regtoken.asp</tt></td></tr>
</table>

<p>
Nie są wysyłane żadne parametry. Przykład:
</p>

<div class="http">
<pre>GET /appsvc/regtoken.asp HTTP/1.1
Connection: Keep-Alive
Host: register.gadu-gadu.pl
</pre>
</div>

<p>
Serwer w odpowiedzi odeśle:
</p>

<div class="http">
<pre><b>SZEROKOŚĆ WYSOKOŚĆ DŁUGOŚĆ
IDENTYFIKATOR
ŚCIEŻKA</b></pre></div>

<p>
Gdzie <tt><b>SZEROKOŚĆ</b></tt> i <tt><b>WYSOKOŚĆ</b></tt> opisują wymiary
obrazka z wartością tokenu, <tt><b>DŁUGOŚĆ</b></tt> mówi ile znaków zawiera
token, <tt><b>IDENTYFIKATOR</b></tt> jest identyfikatorem tokenu (tylko do
niego pasuje wartość tokenu), a <tt><b>ŚCIEŻKA</b></tt> to ścieżka do skryptu
zwracającego obrazek z wartością tokenu. Przykładowa odpowiedź:
</p>

<div class="http">
<pre>115 30 6
e05622e7fcc844b3d582671e0458f0b1
http://register.gadu-gadu.pl/regRndPictNew.php</pre></div>

<p>
Możemy teraz pobrać metodą GET z podanej ścieżki obrazek z tokenem, doklejając
do ścieżki parametr <tt><b>tokenid</b></tt> o wartości będącej identyfikatorem
uzyskanym przed chwilą. Adres obrazka z wartością tokenu dla powyższego
przykładu to:
</p>

<div class="example">
<pre>http://register.gadu-gadu.pl/regRndPictNew.php?tokenid=e05622e7fcc844b3d582671e0458f0b1</pre>
</div>

<p>
Pobrany obrazek (w tej chwili jest w formacie GIF, ale prawdopodobnie może
się to zmienić na dowolny format obsługiwany domyślnie przez system Windows)
najlepiej wyświetlić użytkownikowi, prosząc o podanie wartości na nim
przedstawionej. Będzie ona niezbędna do przeprowadzenia kolejnych operacji.
</p>

<hr />

<a name="ch2.3"></a>

<h3>2.3. Rejestracja konta</h3>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td width="20%"><b>Pole nagłówka</b></td><td width="80%"><b>Wartość</b></td></tr>
<tr class="tabf"><td><tt>HOST</tt></td><td><tt>register.gadu-gadu.pl</tt></td></tr>
<tr class="tabf"><td><tt>ŚCIEŻKA</tt></td><td><tt>/appsvc/fmregister3.asp</tt></td></tr>
</table>

<p></p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td width="20%"><b>Wysyłamy pole</b></td><td width="80%"><b>Znaczenie</b></td></tr>
<tr class="tabf"><td><tt>pwd</tt></td><td>hasło dla nowego numeru</td></tr>
<tr class="tabf"><td><tt>email</tt></td><td>e-mail na który będzie przesyłane przypomnienie hasła</td></tr>
<tr class="tabf"><td><tt>tokenid</tt></td><td>identyfikator tokenu</td></tr>
<tr class="tabf"><td><tt>tokenval</tt></td><td>wartość tokenu</td></tr>
<tr class="tabf"><td><tt>code</tt></td><td>hash liczony z pól <tt>email</tt> i <tt>pwd</tt>. Algorytmu szukaj w źródłach libgadu w <tt>lib/common.c</tt></td></tr>
</table>

<p>
Przykład:
</p>

<div class="http">
<pre>POST /fmregister.php HTTP/1.1
Host: register.gadu-gadu.pl
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/4.7 [en] (Win98; I)
Content-Length: 99
Pragma: no-cache
		
code=283395733&amp;email=abc&#64;xyz.pl&amp;pwd=sekret&amp;tokenid=e05622e7fcc844b3d582671e0458f0b1&amp;tokenval=SEKYCA</pre>
</div>

<p>
Jeśli wszystko przebiegło poprawnie, serwer odpowie:
</p>

<div class="http">
<pre>reg_success:<b>UIN</b></pre>
</div>

<p>
Gdzie <tt><b>UIN</b></tt> to nowy numer, który właśnie otrzymaliśmy.
</p>

<p>
Jeśli został podany nieprawidłowy token, serwer odpowie:
</p>

<div class="http">
<pre>bad_tokenval</pre>
</div>

<p>
W przypadku zbyt długiego hasła, serwer odpowie:
</p>

<div class="http">
<pre>error3 </pre>
</div>

<p>
Jeśli podano niepoprawny adres e-mail, odpowiedź serwera jest pusta.
</p>

<hr />

<a name="ch2.4"></a>
<h3>2.4. Usunięcie konta</h3>

<p>
Nowe Gadu-Gadu zaprasza użytkownika na stronę https://deleteaccount.messenger.gadu-gadu.pl
na której użytkownik może usunąć swoje konto.
</p>

<hr />

<a name="ch2.5"></a>
<h3>2.5. Zmiana hasła</h3>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td width="20%"><b>Pole nagłówka</b></td><td width="80%"><b>Wartość</b></td></tr>
<tr class="tabf"><td><tt>HOST</tt></td><td><tt>register.gadu-gadu.pl</tt></td></tr>
<tr class="tabf"><td><tt>ŚCIEŻKA</tt></td><td><tt>/fmregister.php</tt></td></tr>
</table>

<p></p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td width="20%"><b>Wysyłamy pole</b></td><td width="80%"><b>Znaczenie</b></td></tr>
<tr class="tabf"><td><tt>fmnumber</tt></td><td>numer</td></tr>
<tr class="tabf"><td><tt>fmpwd</tt></td><td>stare hasło</td></tr>
<tr class="tabf"><td><tt>pwd</tt></td><td>nowe hasło</td></tr>
<tr class="tabf"><td><tt>email</tt></td><td>nowe adres e-email</td></tr>
<tr class="tabf"><td><tt>tokenid</tt></td><td>identyfikator tokenu</td></tr>
<tr class="tabf"><td><tt>tokenval</tt></td><td>wartość tokenu</td></tr>
<tr class="tabf"><td><tt>code</tt></td><td>hash liczony z pól <tt>pwd</tt> i <tt>email</tt></td></tr>
</table>

<p>
Jeśli wszystko przebiegło poprawnie, serwer odpowie:
</p>

<div class="http">
<pre>reg_success:<b>UIN</b></pre>
</div>

<p>
W przypadku nieprawidłowego starego hasła, serwer odpowie:
</p>

<div class="http">
<pre>not authenticated</pre>
</div>

<p>
W przypadku zbyt długiego nowego hasła, serwer odpowie:
</p>

<div class="http">
<pre>error1</pre>
</div>

<hr />

<a name="ch2.6"></a>
<h3>2.6. Przypomnienie hasła pocztą</h3>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td width="20%"><b>Pole nagłówka</b></td><td width="80%"><b>Wartość</b></td></tr>
<tr class="tabf"><td><tt>HOST</tt></td><td><tt>register.gadu-gadu.pl</tt></td></tr>
<tr class="tabf"><td><tt>ŚCIEŻKA</tt></td><td><tt>/fmsendpwd.php</tt></td></tr>
</table>

<p></p>

<table class="tab" border="0" cellspacing="1" cellpadding="2" width="100%">
<tr class="tabh"><td width="20%"><b>Wysyłamy pole</b></td><td width="80%"><b>Znaczenie</b></td></tr>
<tr class="tabf"><td><tt>userid</tt></td><td>numer</td></tr>
<tr class="tabf"><td><tt>tokenid</tt></td><td>identyfikator tokenu</td></tr>
<tr class="tabf"><td><tt>tokenval</tt></td><td>wartość tokenu</td></tr>
<tr class="tabf"><td><tt>code</tt></td><td>hash liczony z pola <tt>userid</tt></td></tr>
</table>

<p>
Jeśli się udało, serwer odpowie:
</p>

<div class="http">
<pre>pwdsend_success</pre>
</div>

<hr />

<a name="ch3"></a>
<h2>3. Połączenia między klientami</h2>

<a name="ch3.1"></a>
<h3>3.1. Identyfikator połączenia</h3>

<p>
Połączenia bezpośrednie pozwalają przesyłać pliki lub prowadzić rozmowy
głosowe bez pośrednictwa serwera. Początkowe wersje Gadu-Gadu potrafiły
przesyłać bezpośrednio również wiadomości tekstowe, ale funkcjonalność
ta została zarzucona.
</p>

<p>
Dla każdego połączenia musimy zdobyć od serwera 8 bajtowy identyfikator.
Aby pobrać identyfikator należy użyć pakietu:
</p>

<div class="c">
<pre>#define GG_DCC7_ID_REQUEST 0x0023

struct gg_dcc7_id_request {
	int type;		<i>/* rodzaj transmisji */</i>
};</pre>
</div>

<p>
Pole <tt>type</tt> oznacza rodzaj transmisji:
</p>

<div class="c">
<pre>#define GG_DCC7_TYPE_VOICE 0x00000001	<i>/* rozmowa głosowa (już nieużywane) */</i>
#define GG_DCC7_TYPE_FILE 0x00000004	<i>/* przesyłanie plików */</i>
</pre>
</div>

<p>
Na co serwer odpowie:
</p>

<div class="c">
<pre>#define GG_DCC7_ID_REPLY 0x0023

struct gg_dcc7_id_reply {
	int type;	<i>/* rodzaj transmisji */</i>
	long long id;	<i>/* przyznany identyfikator */</i>
};</pre>
</div>

<hr />

<a name="ch3.2"></a>
<h3>3.2. Przesyłanie plików</h3>

<p>
Aby powiadomić odbiorcę o chęci przesłania pliku, należy wysłać do serwera
następujący pakiet:
</p>

<div class="c">
<pre>#define GG_DCC7_NEW 0x0020

struct gg_dcc7_new {
	long long id;		<i>/* identyfikator połączenia */</i>
	int uin_from;		<i>/* numer nadawcy */</i>
	int uin_to;		<i>/* numer odbiorcy */</i>
	int type;		<i>/* rodzaj transmisji */</i>
	char filename[255];	<i>/* nazwa pliku */</i>
	long long size;		<i>/* rozmiar pliku */</i>
	char hash[20];		<i>/* hash SHA1 (już nieużywane 00 00 00) */</i>
};</pre>
</div>

<p>
Odbiorca po otrzymaniu tego samego pakietu <tt>GG_DCC7_NEW</tt>, może
zaakceptować plik wysyłając pakiet:
</p>

<div class="c">
<pre>#define GG_DCC7_ACCEPT 0x0021

struct gg_dcc7_accept {
	int uin;		<i>/* numer przyjmującego połączenie */</i>
	long long id;		<i>/* identyfikator połączenia */</i>
	long long offset;	<i>/* offset przy wznawianiu transmisji */</i>
};</pre>
</div>

<p>
Jeśli plik został już częściowo odebrany i chcemy wznowić przesyłanie,
w polu <tt>offset</tt> wystarczy podać ile bajtów już mamy, a odebrane
dane dopisać na końcu pliku.
</p>

<p>
Jeśli odbiorca chce odrzucić plik, wysyła pakiet:
</p>

<div class="c">
<pre>#define GG_DCC7_REJECT 0x0022

struct gg_dcc7_reject {
	int uin;	<i>/* numer odrzucającego połączenie */</i>
	long long id;	<i>/* identyfikator połączenia */</i>
	int reason;	<i>/* powód rozłączenia */</i>
};</pre>
</div>

<p>
Dla pola <tt>reason</tt> znane są wartości:
</p>

<div class="c">
<pre>#define GG_DCC7_REJECT_BUSY	0x00000001	<i>/* połączenie bezpośrednie już trwa, nie umiem
						   obsłużyć więcej */</i>
#define GG_DCC7_REJECT_USER	0x00000002	<i>/* użytkownik odrzucił połączenie */</i>
#define GG_DCC7_REJECT_HIDDEN	0x00000003	<i>/* użytkownik ojest ukryty i nie możesz  
						   mu wysłać pliku*/</i>
#define GG_DCC7_REJECT_VERSION	0x00000006	<i>/* druga strona ma wersję klienta nieobsługującą
						   połączeń bezpośrednich tego typu */</i>
</pre>
</div>

<p>
Przed akceptacją pliku przez odbiorcę, nadawca może przerwać żądanie
wysyłając pakiet:
</p>

<div class="c">
<pre>#define GG_DCC7_ABORT 0x0025

struct gg_dcc7_abort {
	long long id;		<i>/* identyfikator połączenia */</i>
	int uin_from;		<i>/* numer nadawcy */</i>
	int uin_to;		<i>/* numer odbiorcy */</i>
};</pre>
</div>

<p>
Odbiorca w takim przypadku otrzyma pakiet:
</p>

<div class="c">
<pre>#define GG_DCC7_ABORTED 0x0025

struct gg_dcc7_aborted {
	long long id;		<i>/* identyfikator połączenia */</i>
};</pre>
</div>

<hr />

<a name="ch3.3"></a>
<h3>3.3. Połączenie bezpośrednie</h3>

<p>
Po zaakceptowaniu pliku, obie strony zaczynają nasłuchiwać na losowo wybranym
porcie z zakresu 4096..32767 i wysyłają pakiet <tt>GG_DCC7_INFO</tt>
z informacjami potrzebnymi do połączenia.
</p>

<div class="c">
<pre>#define GG_DCC7_INFO 0x001f

struct gg_dcc7_info {
	int uin;		<i>/* numer nadawcy */</i>
	int type;		<i>/* sposób połączenia */</i>
	long long id;		<i>/* identyfikator połączenia */</i>
	char info[32];		<i>/* informacje o połączeniu */</i>
	char cookie[32];	<i>/* losowa informacja */</i>
};</pre>
</div>

<p>
Pole <tt>type</tt> określa sposób połączenia:
</p>

<div class="c">
<pre>#define GG_DCC7_TYPE_P2P    0x00000001	<i>/* połączenie bezpośrednie */</i>
#define GG_DCC7_TYPE_SERVER 0x00000002	<i>/* połączenie przez serwer */</i>
</pre>
</div>

<p>
Pole <tt>info</tt> zawiera tekstową reprezentację adresu IP, spację i numer
portu. Pole <tt>cookie</tt> jest tekstową reprezentacją liczby wyznaczanej
w następujący sposób:
</p>

<div class="c">
<pre>// Gadu-Gadu 8.x i późniejsze
int cookie = <b>adres</b> + <b>port</b> * rand();

// Gadu-Gadu 7.x
int cookie = 0x7FFF * rand() + rand();
</pre>
</div>

<p>
Adres do obliczeń jest zapisany w sieciowej kolejności bajtów (np. wynik
funkcji <tt>inet_addr()</tt>), port w lokalnej.
</p>

<p>
Przykładowa zawartość pól <tt>info</tt> i <tt>cookie</tt>:
</p>

<div class="example">
<pre>0000   31 30 2e 30 2e 30 2e 32 20 32 32 35 36 33 00 00  10.0.0.2 22563..
0010   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0020   31 37 36 34 36 38 34 38 34 00 00 00 00 00 00 00  176468484.......
0030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................</pre>
</div>

<p>
Po udanym połączeniu na podany adres, wysyłamy pakiet powitalny:
</p>

<div class="c">
<pre>struct gg_dcc7_welcome_p2p {
	long long id;	<i>/* identyfikator połączenia */</i>
};</pre>
</div>

<p>
Druga strona powinna odpowiedzieć tym samym. Teraz już możemy albo wysyłać
albo odbierać plik.
</p>

<hr />

<a name="ch3.4"></a>
<h3>3.4. Połączenie przez serwer</h3>

<p>
Obie strony połączenia łączą się również z <tt>relay.gadu-gadu.pl:80</tt> aby
uzyskać listę serwerów które mogą pośredniczyć w wymianie plików. Struktura
żądania:
</p>

<div class="c">
<pre>#define GG_DCC7_RELAY_REQUEST 0x0a

struct gg_dcc7_relay_req {
	int type;	<i>/* 0x0a */</i>
	int len;	<i>/* długość całego pakietu */</i>
	long long id;	<i>/* identyfikator połączenia */</i>
	short req_type;	<i>/* typ żądania (patrz niżej) */</i>
	char family	<i>/* 0x02, prawdopodobnie rodzina adresów (AF_INET=2) */</i>
	char unknown;   <i>/* 0x00 */</i>
};</pre>
</div>

<p>
Gdzie <tt>req_type</tt> może przyjąć wartości:
</p>

<div class="c">
<pre>#define GG_DCC7_RELAY_TYPE_PROXY    0x01 <i>/* adresy proxy, na które sie łączyć */</i>
#define GG_DCC7_RELAY_TYPE_SERVER   0x08 <i>/* adres serwera, na który spytać o proxy */</i></pre>
</div>

<p>
Serwer odpowiada:
</p>

<div class="c">
<pre>#define GG_DCC7_RELAY_REPLY 0x0b

struct gg_dcc7_relay_reply {
	int type;	<i>/* 0x0b */</i>
	int len;	<i>/* długość całego pakietu */</i>
	int count;	<i>/* prawdopodobnie ilość pośredniczących serwerów */</i>
	struct {
		int ip;		<i>/* adres ip serwera */</i>
		short port;	<i>/* port serwera */</i>
		char family;	<i>/* prawdopodobnie rodzina adresów (AF_INET=2) */</i>
	} proxies[];
};</pre>
</div>

<p>
Pobieranie IP serwera(ów) pośredniczących w Gadu-Gadu 10.x następuje przed
i po wysłaniu <tt>GG_DCC7_INFO</tt> wg schematu:
</p>

<ul>
<li>wysłanie <tt>GG_DCC7_RELAY_REQUEST</tt> z <tt>req_type</tt> równym <tt>GG_DCC7_RELAY_TYPE_SERVER</tt> na <tt>relay.gadu-gadu.pl:80</tt></li>
<li>opcjonalnie: wysłanie <tt>GG_DCC7_RELAY_REQUEST</tt> z <tt>req_type</tt> równym <tt>GG_DCC7_RELAY_TYPE_SERVER</tt> na <tt>relay.gadu-gadu.pl:443</tt></li>
<li>wysłanie <tt>GG_DCC_INFO</tt> z typem <tt>GG_DCC7_TYPE_P2P</tt> (patrz dalej)</li>
<li>wysłanie <tt>GG_DCC7_RELAY_REQUEST</tt> z <tt>req_type</tt> równym <tt>GG_DCC7_RELAY_TYPE_PROXY</tt> na adres serwera otrzymany w pierwszym <tt>GG_DCC7_RELAY_REQUEST</tt></li>
<li>opcjonalnie: jw tylko na port 443</li>
</ul>

<p>
Może się zdarzyć, że żaden z serwerów nie odpowie na pierwsze żądanie, wtedy
jako adres drugiego żądania bierzemy znowu <tt>relay.gadu-gadu.pl</tt>.
</p>

<p>
Po uzyskaniu adresu serwera pośredniczącego należy wysłać pakiet
<tt>GG_DCC7_INFO</tt> (<a href="#ch3.3">opisany wcześniej</a>) z polem
<tt>type</tt> równym <tt>GG_DCC7_TYPE_SERVER</tt> i polem <tt>info</tt>
w postaci:
</p>

<div class="http">
<pre>GG<b>id</b>CH<b>rand</b></pre>
</div>

<p>
Gdzie <b><tt>id</tt></b> to tekstowa reprezentacja identyfikatora połączenia,
a <b><tt>rand</tt></b> to losowa wartość z zakresu 0..9999. Gadu-Gadu 7.x
zamiast <tt>CH</tt> mogło wysłać również <tt>SH</tt>.
</p>

<p>
Pole <tt>cookie</tt> pozostaje puste.
</p>

<p>
Przykładowa zawartość pól <tt>info</tt> i <tt>cookie</tt>:
</p>

<div class="example">
<pre>0000   47 47 31 31 30 32 30 38 38 36 30 38 34 33 39 31  GG11020886084391
0010   43 48 36 39 36 32 00 00 00 00 00 00 00 00 00 00  CH6962..........
0020   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................</pre>
</div>

<p>
Po połączeniu do serwera pośredniczącego wysyłamy pakiet powitalny:
</p>

<div class="c">
<pre>struct gg_dcc7_welcome_server {
	int welcome;	<i>/* 0xc0debabe */</i>
	long long id;	<i>/* identyfikator połączenia */</i>
};</pre>
</div>

<p>
Serwer powinien odpowiedzieć tym samym. Teraz już możemy albo wysyłać albo
odbierać plik.
</p>

<hr />

<a name="ch3.4"></a>
<h3>3.4. Rozmowy głosowe</h3>

<p>Połączenia głosowe są realizowane za pomocą protokołu SIP.</p>

<hr />

<a name="ch4"></a>
<h2>4. Autorzy</h2>

<p>
Lista autorów tego tekstu znajduje się poniżej. Ich adresy e-mail <b>nie
służą</b> do zadawania pytań o podstawy programowania albo jak się
połączyć z serwerem i co zrobić dalej. Jeśli masz pytania dotyczące protokołu,
napisz na listę dyskusyjną
<a href="http://lists.ziew.org/mailman/listinfo/libgadu-devel">libgadu-devel</a>.
</p>

<ul>
	<li><b>Wojtek Kaniewski</b> (wojtekka%irc.pl): pierwsza wersja opisu,
	poprawki, utrzymanie wszystkiego w porządku.</li>
	<li><b>Robert J. Woźny</b> (speedy%atman.pl): opis nowości w protokole
	GG 4.6, poprawki.</li>
	<li><b>Tomasz Jarzynka</b> (tomee%cpi.pl): badanie timeoutów.</li>
	<li><b>Adam Ludwikowski</b> (adam.ludwikowski%wp.pl): wiele poprawek,
	wersje klientów, rozszerzone wiadomości, powody nieobecności.</li>
	<li><b>Marek Kozina</b> (klith%hybrid.art.pl): czas otrzymania
	wiadomości.</li>
	<li><b>Rafał Florek</b> (raf%regionet.regionet.pl): opis połączeń
	konferencyjnych.</li>
	<li><b>Igor Popik</b> (igipop%wsfiz.edu.pl): klasy wiadomości przy
	odbieraniu zakolejkowanej.</li>
	<li><b>Rafał Cyran</b> (ajron%wp.pl): informacje o remote_port,
	rodzaje potwierdzeń przy ctcp, GG_LOGIN_EXT.</li>
	<li><b>Piotr Mach</b> (pm%gadu-gadu.com): ilość kontaktów, pełna
	skrzynka, pusta lista, maska audio, usługi HTTP, GG_LOGIN_EXT.</li>
	<li><b>Adam Czyściak</b> (acc%interia.pl): potwierdzenie wiadomości
	GG_CLASS_ACK.</li>
	<li><b>Kamil Dębski</b> (kdebski%kki.net.pl): czas w stanach
	opisowych.</li>
	<li><b>Paweł Piwowar</b> (alfapawel%go2.pl): format czasu.</li>
	<li><b>Tomasz Chiliński</b> (chilek%chilan.com): nowości w 5.0.2.</li>
	<li><b>Radosław Nowak</b> (rano%ranosoft.net): uzupełnienie statusu
	opisowego, wersja 5.0.3.</li>
	<li><b>Walerian Sokołowski</b>: pierwsza wersja opisu protokołu
	bezpośrednich połączeń.</li>
	<li><b>Nikodem</b> (n-d%tlen.pl): flagi rodzaju użytkownika.</li>
	<li><b>Adam Wysocki</b> (gophi%ekg.chmurka.net): poprawki, utrzymanie 
	wszystkiego w porządku, GG_XML_EVENT.</li>
	<li><b>Marcin Krupowicz</b> (marcin.krupowicz%gmail.com): informacja na 
	temat tego, że pakiet GG_LOGIN_OK nie zawsze jest zerowej długości.</li>
	<li><b>Jakub Zawadzki</b> (darkjames%darkjames.ath.cx): nowości w
	7.x i 8.x.</li>
	<li><b>Krystian Kołodziej</b> (krystiankolodziej%gmail.com): znaczenie
	GG_DISCONNECT_ACK, nowy pakiet GG_LOGIN80_FAILED</li>
	<li><b>Adrian Warecki</b> (bok%kokosoftware.pl): Przykładowe pakiety GG_XML_ACTION</li>
	<li><b>Piotr Latosiński</b> (piotr.latosinski%gmail.com): Opis pakietów GG_USER_DATA i GG_RECV_MSG_ACK</li>
	<li><b>Tomek Nagisa</b> (kaworu%k2t.eu): Opis pakietów &quot;pisaka&quot;, GG_TYPING_NOTIFY oraz multilogowania.</li>
	<li><b>Maciej Muszkowski</b> (maciek.muszkowski%gmail.com): Poprawiony opis połączeń bezpośrednich/relay w GG 8.x/10.x</li>
</ul>

</div>
</center>

</body>
</html>