aboutsummaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/examples.html445
-rw-r--r--doc/examples/SoundRecorder/include/debug.h24
-rw-r--r--doc/examples/SoundRecorder/include/soundbuffers.h39
-rw-r--r--doc/examples/SoundRecorder/include/soundcard.h31
-rw-r--r--doc/examples/SoundRecorder/include/soundmixer.h23
-rw-r--r--doc/examples/SoundRecorder/src/main.c296
-rw-r--r--doc/examples/SoundRecorder/src/soundbuffers.c86
-rw-r--r--doc/examples/SoundRecorder/src/soundcard.c49
-rw-r--r--doc/examples/SoundRecorder/src/soundmixer.c104
-rw-r--r--doc/examples/cgi-bin/index.cgi1137
-rw-r--r--doc/examples/cgi-bin/simple.cgi14
-rw-r--r--doc/examples/cgi-bin/simple1.cgi125
-rw-r--r--doc/examples/cgi.c100
-rw-r--r--doc/examples/demo.c66
-rw-r--r--doc/examples/foo-cert.pem86
-rw-r--r--doc/examples/packetmounter.c236
-rw-r--r--doc/functions.html355
-rw-r--r--doc/info.html25
-rw-r--r--doc/security.html67
19 files changed, 0 insertions, 3308 deletions
diff --git a/doc/examples.html b/doc/examples.html
deleted file mode 100644
index 5cd8bbfe..00000000
--- a/doc/examples.html
+++ /dev/null
@@ -1,445 +0,0 @@
1<center><H3><font color='007700'>libwebserver examples</font></H3></center><BR><BR>
2
3<!-- Johannes E. Schindelin -->
4<center><A name=helloworld><B><font color='000077'><a href=/hello><H3>Hello World</H3></a></font></B></center>
5<small> <B>used functions:</B><BR>
6<a href='/?help=functions#web_server_init'>web_server_init</a><BR>
7<a href='/?help=functions#web_server_addhandler'>web_server_addhandler</a><BR>
8<a href='/?help=functions#web_server_run'>web_server_run</a><BR>
9</small><BR>
10
11This example starts the server with one handler for all requests pointing to hello_world()
12that prints the content-type with the end of the header "\r\n\r\n" and one simple printf with Hello world<BR><BR>
13
14<TABLE width='100%' bgcolor='CFCFCF' border=0><TR><TD>
15<CODE><PRE>
16#include "web_server.h"
17#include &lt;stdio.h&gt;
18
19
20void hello_world() {
21 printf("Content-type: text/plain\r\n\r\n");
22 printf("Hello, World!\r\n");
23}
24
25int main(int argc,char** argv) {
26 struct web_server server; // server handler
27 if(!web_server_init(&server,80,"help.log",0)) { // initialize and start the server at port 80, logging to help.log
28 fprintf(stderr,"can't open listen socket\n");
29 return 1;
30 };
31
32 web_server_addhandler(&server,"* *",hello_world,0); // add handler for all requests
33 while(1) {
34 web_server_run(&server); // run server
35 };
36}
37</PRE></CODE>
38</TD></TR></TABLE>
39<HR><BR>
40
41<center><A name=logfile><B><font color='000077'><a href='/log'><H3>logfile</H3></a></font></B></center>
42<small> <B>used functions:</B><BR>
43<a href='/?help=functions#web_server_init'>web_server_init</a><BR>
44<a href='/?help=functions#web_server_addhandler'>web_server_addhandler</a><BR>
45<a href='/?help=functions#web_server_run'>web_server_run</a><BR>
46<a href='/?help=functions#web_client_addfile'>web_client_addfile</a><BR>
47</small><BR>
48
49This example uses the function <a href='/?help=functions#web_client_addfile'>web_client_addfile</a> to send a file to client
50<BR><BR>
51<TABLE width='100%' bgcolor='CFCFCF' border=0><TR><TD>
52<CODE><PRE>
53#include "web_server.h"
54#include &lt;stdio.h&gt;
55
56void logfile() {
57 printf("Content-type: text/plain\r\n\r\n");
58 web_client_addfile(server.logfile); // add help.log file to output
59 printf("End of log\n");
60};
61
62
63main() {
64 struct web_server server; // server handler
65 if(!web_server_init(&server,82,"help.log",0)) { // initializate
66 fprintf(stderr,"can't open listen socket\n");
67 };
68
69 web_server_addhandler(&server,"* /log",logfile,0); // add handler for http://host/log requests
70 while(1) {
71 web_server_run(&server); // run server
72 };
73};
74</PRE></CODE>
75</TD></TR></TABLE>
76<HR><BR>
77
78
79<center><A name=imageup><B><font color='000077'><a href='/image'><H3>Image Uploader</H3></a></font></B></center>
80<small> <B>used functions:</B><BR>
81<a href='/?help=functions#web_server_init'>web_server_init</a><BR>
82<a href='/?help=functions#web_server_addhandler'>web_server_addhandler</a><BR>
83<a href='/?help=functions#web_server_run'>web_server_run</a><BR>
84<a href='/?help=functions#clientinfo'>ClientInfo</a><BR>
85</small><BR>
86
87
88This example uses the struct <a href='/?help=functions#clientinfo'>ClientInfo</a> for fetching the input from the client
89using the Query("img") to send the image <BR>
90and multipart for fetching the uploaded file<BR>
91
92
93<BR><BR>
94<TABLE width='100%' bgcolor='CFCFCF' border=0><TR><TD>
95<CODE><PRE>
96#include "web_server.h"
97
98#include &lt;stdlib.h&gt;
99
100struct image {
101 char *data;
102 size_t size;
103} image={NULL,0};
104
105void imageout() {
106 if(strlen(ClientInfo->Query("img"))) {
107 if(image.data!=NULL) {
108 printf("Content-type: image/jpeg\r\n\r\n");
109 fwrite(image.data,image.size,1,stdout);
110 };
111 return;
112 };
113 printf("Content-type: text/html\r\n\r\n");
114 printf("&lt;HTML&gt;\n");
115 printf("&lt;BODY bgcolor='EFEFEF'&gt;\n");
116 printf("&lt;form action='/' enctype='multipart/form-data'&gt;\n");
117 printf("&lt;input type=file name=image&gt;&lt;BR&gt;\n");
118 printf("&lt;/form&gt;\n");
119 if(strlen(ClientInfo->MultiPart("image").data)) {
120 printf("%s&lt;BR&gt;&lt;img src='/?img=%s.jpg'&gt;\n",ClientInfo->MultiPart("image").filename,ClientInfo->MultiPart("image").filename);
121 free(image.data);
122 image.data=malloc(ClientInfo->MultiPart("image").size+1);
123 memcpy(image.data,ClientInfo->MultiPart("image").data,ClientInfo->MultiPart("image").size);
124 image.size=ClientInfo->MultiPart("image").size;
125 }else {
126 free(image.data);
127 image.data=NULL;
128 };
129 printf("&lt;/BODY&gt;\n");
130 printf("&lt;/HTML&gt;\n");
131};
132
133
134
135main() {
136 struct web_server server;
137 if(!web_server_init(&server,80,"teste.log",0)) {
138 fprintf(stderr,"can't open listen socket\n");
139 };
140 web_server_addhandler(&server,"* /",imageout,0);
141 while(1) {
142 web_server_run(&server);
143 };
144};
145</PRE></CODE>
146</TD></TR></TABLE>
147<HR><BR>
148
149
150<center><A name=auth><B><font color='000077'><a href='/auth'><H3>Authentication</H3></a> </font></B></center>
151<small> <B>used functions:</B><BR>
152<a href='/?help=functions#web_server_init'>web_server_init</a><BR>
153<a href='/?help=functions#web_server_addhandler'>web_server_addhandler</a><BR>
154<a href='/?help=functions#web_server_run'>web_server_run</a><BR>
155<a href='/?help=functions#web_client_HTTPdirective'>web_client_HTTPdirective</a><BR>
156</small><BR>
157
158Here we're using the <a href='/?help=functions#web_client_HTTPdirective'>web_client_HTTPdirective</a> to set up the server response
159
160<BR><BR>
161user: "username", pass: "password"
162<BR>
163<TABLE width='100%' bgcolor='CFCFCF' border=0><TR><TD>
164<CODE><PRE>
165#include "web_server.h"
166#include &lt;stdio.h&gt;
167#include &lt;string.h&gt;
168
169
170void urlauthenticate() {
171 if(!strlen(ClientInfo->user) || !strlen(ClientInfo->pass) &&
172 strcmp(ClientInfo->user,"username") || strcmp(ClientInfo->pass,"password")) { // you can read things from a auth file
173 web_client_HTTPdirective("HTTP/1.1 401 Authorization Required");
174 printf("WWW-Authenticate: Basic realm=\"This site info\"\r\n");
175 printf("Content-type: text/html\r\n\r\n");
176 printf("&lt;BODY&gt;\n");
177 printf("&lt;font color='FF0000'&gt;Access denied&lt;/font&gt;\n");
178 printf("&lt;/BODY&gt;\n");
179 return;
180 }
181 printf("Content-type: text/html\r\n\r\n");
182 printf("&lt;BODY bgcolor='EFEFEF'&gt;\n");
183 printf("You entered in your area\n");
184 printf("&lt;/BODY&gt;&lt;/HTML&gt;\n");
185};
186
187
188main() {
189 struct web_server server; // server handler
190 if(!web_server_init(&server,83,"help.log",0)) { // initialize
191 fprintf(stderr,"can't open listen socket\n");
192 };
193
194 web_server_addhandler(&server,"* /auth",urlauthenticate,0);
195 while(1) {
196 web_server_run(&server); // run server
197 };
198};
199</PRE></CODE>
200</TD></TR></TABLE>
201<HR><BR>
202
203
204<CENTER><A name=ssl><B><font color='000077'><H3>openssl for (https)</H3></font></B></CENTER>
205<small> <B>used functions:</B><BR>
206<a href='/?help=functions#web_server_HTTPdirective'>web_server_useSSLcert</a><BR>
207<a href='/?help=functions#web_server_init'>web_server_init</a><BR>
208<a href='/?help=functions#web_server_run'>web_server_run</a><BR>
209</small><BR>
210
211Here we setup a server and we use the <a href='/?help=functions#web_server_useSSLcert'>web_server_useSSLcert</a> to use specific certificate file
212and we start the server with the flag WS_USESSL for secure connections (libwebserver compiled w/ openssl)<BR><BR>
213
214See also the packetmounter example in the example directory.
215<BR>
216<TABLE width='100%' bgcolor='CFCFCF' border=0><TR><TD>
217<CODE><PRE>
218
219
220#include "web_server.h"
221
222int main()
223 struct web_server serverssl;
224 web_server_useSSLcert(&serverssl,"foo-cert.pem"); // Certificate file
225 if(!web_server_init(&serverssl,443,"help.log",WS_USESSL)) {
226 fprintf(stderr,"Cannot open port\n");
227 };
228 while(1) {
229 web_server_run(&serverssl);
230 };
231};
232</PRE></CODE>
233</TD></TR></TABLE>
234All the rest is the same as without SSL.
235<HR><BR>
236
237
238<center><A name=outgif><B><font color='000077'><a href='/gif'><H3>Gif generator</H3></a></font></B></center>
239<small> <B>used functions;</B><BR>
240<a href='/?help=functions#web_server_init'>web_server_init</a><BR>
241<a href='/?help=functions#web_server_addhandler'>web_server_addhandler</a><BR>
242<a href='/?help=functions#web_server_run'>web_server_run</a><BR>
243<a href='/?help=functions#web_client_gifsetpalette'>web_client_gifsetpalette</a><BR>
244<a href='/?help=functions#web_client_gifoutput'>web_client_gifoutput</a><BR>
245<a href='/?help=functions#clientinfo'>ClientInfo</a><BR>
246</small><BR>
247
248This example draws an circle at x,y requested by client, and outputs with function <a href='/?help=functions#web_client_gifoutput'>web_client_gifoutput</a>
249
250
251<BR><BR>
252<TABLE width='100%' bgcolor='CFCFCF' border=0><TR><TD>
253<CODE><PRE>
254#include "web_server.h"
255#include &lt;stdio.h&gt;
256#include &lt;math.h&gt;
257
258
259#define GIFSIDE 320
260char gifdata[GIFSIDE*GIFSIDE];
261void outgif() {
262 float i;
263 int x,y,xc,yc;
264 int color;
265 web_client_gifsetpalette("EGA");
266 if(*ClientInfo->Query("img")!=0) {
267 printf("Content-type: image/gif\r\n\r\n");
268 if(!strcmp(ClientInfo->Query("img"),"circle")) {
269 xc=atoi(ClientInfo->Query("x"))%GIFSIDE;
270 yc=atoi(ClientInfo->Query("y"))%GIFSIDE;
271 color=(rand()%15)+1;
272 for(i=0;i<6.28;i+=0.01) {
273 x=(int)(GIFSIDE+(xc+cos(i)*10))%GIFSIDE;
274 y=(int)(GIFSIDE+(yc+sin(i)*10))%GIFSIDE;
275 gifdata[x+(y*GIFSIDE)]=color;
276 };
277 };
278 web_client_gifoutput(gifdata,GIFSIDE,GIFSIDE);
279 };
280 printf("&lt;center&gt;Generated a circle (click inside the image)&lt;BR&gt;\n");
281 printf("Pressed x=%s,y=%s&lt;BR&gt;\n",ClientInfo->Query("x"),ClientInfo->Query("y"));
282 printf("&lt;form&gt;&lt;input type=image border=0 src='/gif?img=circle&x=%s&y=%s'&gt;&lt;/form&gt;&lt;/CENTER&gt;\n",ClientInfo->Query("x"),ClientInfo->Query("y"));
283};
284
285
286main() {
287 struct web_server server; // server handler
288 memset(gifdata,0,GIFSIDE*GIFSIDE);
289 if(!web_server_init(&server,83,"help.log",0)) { // initialize
290 fprintf(stderr,"can't open listen socket\n");
291 };
292
293 web_server_addhandler(&server,"* /gif",outgif,0);
294 while(1) {
295 web_server_run(&server); // run server
296 };
297};
298</PRE></CODE>
299</TD></TR></TABLE>
300<HR><BR>
301
302
303
304<CENTER><A name=cookie><B><font color='000077'><a href=/cookie><H3>Cookies</H3></a></font></B></CENTER>
305<small> <B>used functions;</B><BR>
306<a href='/?help=functions#web_server_init'>web_server_init</a><BR>
307<a href='/?help=functions#web_server_addhandler'>web_server_addhandler</a><BR>
308<a href='/?help=functions#web_server_run'>web_server_run</a><BR>
309<a href='/?help=functions#clientinfo'>ClientInfo</a><BR>
310<a href='/?help=functions#web_client_setcookie'>web_client_setcookie</a><BR>
311</small><BR>
312
313This example fetchs an client input and set's an cookie for 15 minutes "+15M" using function <a href='/?help=functions#web_client_setcookie'>web_client_setcookie</a>
314
315<BR><BR>
316<TABLE width='100%' bgcolor='CFCFCF' border=0><TR><TD>
317<CODE><PRE>
318#include "web_server.h"
319#include &lt;stdio.h&gt;
320
321
322void cookie() {
323 if(strlen(ClientInfo->Post("user")))
324 web_client_setcookie("username",ClientInfo->Post("user"),"+15M");
325 printf("Content-type: text/html\r\n\r\n");
326 printf("&lt;form method='POST'&gt;\r\n");
327 printf("&lt;input type='text' name='user' value='%s'&gt;\r\n&lt;BR&gt;",ClientInfo->Cookie("username"));
328 printf("&lt;input type='submit' name='send' value=' GO! '&gt;\r\n&lt;BR&gt;");
329 printf("&lt;/form&gt;\r\n");
330}
331
332int main(int argc,char** argv) {
333 struct web_server server; // server handler
334 if(!web_server_init(&server,80,"help.log",0)) { // initialize
335 fprintf(stderr,"can't open listen socket\n");
336 return 1;
337 };
338
339 web_server_addhandler(&server,"* /*",cookie,0); // add handler for all requests
340 while(1) {
341 web_server_run(&server); // run server
342 };
343}
344
345</PRE></CODE>
346</TD></TR></TABLE>
347<HR><BR>
348
349<center><A name=checkbox><B><font color='000077'><a href=/checkbox><H3>Checkbox</H3></a></font></B></center>
350<small> <B>used functions;</B><BR>
351<a href='/?help=functions#web_server_init'>web_server_init</a><BR>
352<a href='/?help=functions#web_server_addhandler'>web_server_addhandler</a><BR>
353<a href='/?help=functions#web_server_run'>web_server_run</a><BR>
354<a href='/?help=functions#clientinfo'>ClientInfo</a><BR>
355</small><BR>
356
357This example uses a especific case from <a href='/?help=functions#clientinfo'>ClientInfo</a> query and post, using the '#' as prefix of varname returning the number of occurences
358
359
360<BR><BR>
361<TABLE width='100%' bgcolor='CFCFCF' border=0><TR><TD>
362<CODE><PRE>
363
364#include "web_server.h"
365#include &lt;stdio.h&gt;
366
367
368void checkbox() {
369 int i=0;
370 char *txt[]={"one","two","three","four","five"};
371 printf("Content-type: text/html\r\n\r\n");
372 printf("&lt;form method='QUERY'&gt;\r\n");
373
374 for(i=0;i<5;i++) {
375 printf("&lt;input type='checkbox' name='number' value='%s'&gt;\r\n&lt;BR&gt;",txt[i]);
376 };
377 printf("&lt;input type='submit' name='send' value=' SEND '&gt;\r\n&lt;BR&gt;");
378 printf("&lt;/form&gt;\r\n");
379
380 printf("You have choosen &lt;font color='FF0000'&gt;%d&lt;/font&gt; numbers: \r\n",ClientInfo->Query("#number"));
381 for(i=0;i&lt;ClientInfo->Query("#number");i++) {
382 printf("&lt;b>%s&lt;/b&gt;,\r\n\r\n",ClientInfo->Query("number"));
383 };
384 printf("...&lt;BR&gt;\r\n\r\n");
385
386}
387int main(int argc,char** argv) {
388 struct web_server server; // server handler
389 if(!web_server_init(&server,80,"help.log",0)) { // initialize
390 fprintf(stderr,"can't open listen socket\n");
391 return 1;
392 };
393
394 web_server_addhandler(&server,"* /*",checkbox,0); // add handler for all requests
395 while(1) {
396 web_server_run(&server); // run server
397 };
398}
399
400</PRE></CODE>
401</TD></TR></TABLE>
402<HR><BR>
403
404<center><A name=confexample><B><font color='000077'><a href=/confexample><H3>Config example</H3></a></font></B></center>
405<small> <B>used functions;</B><BR>
406<a href='/?help=functions#web_server_init'>web_server_init</a><BR>
407<a href='/?help=functions#web_server_addhandler'>web_server_addhandler</a><BR>
408<a href='/?help=functions#web_server_run'>web_server_run</a><BR>
409<a href='/?help=functions#web_client_addfile'>web_client_addfile</a><BR>
410<a href='/?help=functions#clientinfo'>ClientInfo</a><BR>
411</small><BR>
412
413
414<BR><BR>
415<TABLE width='100%' bgcolor='CFCFCF' border=0><TR><TD>
416<CODE><PRE>
417#include "web_server.h"
418#include &lt;stdio.h&gt;
419
420
421void confexample() {
422 printf("Content-type: text/html\r\n\r\n");
423 printf("&lt;PRE&gt;");
424 web_client_addfile(server.conffile); // add help.cfg file to output
425 printf("&lt;/PRE&gt;");
426 printf("ClientInfo->Conf(\"PERSONAL_CONF\",\"PORT\")=%s&lt;BR&gt;\n",ClientInfo->Conf("PERSONAL_CONF","PORT"));
427 printf("ClientInfo->Conf(\"PERSONAL_CONF\",\"IP\")=%s&lt;BR&gt;\n",ClientInfo->Conf("PERSONAL_CONF","IP"));
428 printf("ClientInfo->Conf(\"LIBWEBSERVER\",\"PORT\")=%s&lt;BR&gt;\n",ClientInfo->Conf("LIBWEBSERVER","PORT"));
429
430}
431
432int main(int argc,char** argv) {
433 struct web_server server; // server handler
434 if(!web_server_init(&server,80,"help.cfg",WS_USEEXTCONF)) { // initialize
435 fprintf(stderr,"can't open listen socket\n");
436 return 1;
437 };
438
439 web_server_addhandler(&server,"* *",confexample,0); // add handler for all requests
440 while(1) {
441 web_server_run(&server); // run server
442 };
443}
444</PRE></CODE>
445</TD></TR></TABLE> \ No newline at end of file
diff --git a/doc/examples/SoundRecorder/include/debug.h b/doc/examples/SoundRecorder/include/debug.h
deleted file mode 100644
index 4863d578..00000000
--- a/doc/examples/SoundRecorder/include/debug.h
+++ /dev/null
@@ -1,24 +0,0 @@
1/* by Luis Figueiredo (stdio@netc.pt)
2 *
3 *
4 * date: Sat Mar 30 14:16:05 GMT 2002
5 *
6 * DEBUG macros
7 *
8 */
9
10#ifndef _DEBUG_H_
11#define _DEBUG_H_
12
13#ifdef HAVE_CONFIG_H
14#include "config.h"
15#endif
16
17#ifdef DEBUG
18 #define IFDEBUG(x) x
19#else
20 #define IFDEBUG(x)
21#endif
22
23
24#endif
diff --git a/doc/examples/SoundRecorder/include/soundbuffers.h b/doc/examples/SoundRecorder/include/soundbuffers.h
deleted file mode 100644
index 6624b21b..00000000
--- a/doc/examples/SoundRecorder/include/soundbuffers.h
+++ /dev/null
@@ -1,39 +0,0 @@
1/* by Luis Figueiredo (stdio@netc.pt)
2 *
3 * file: sound_buffers.h
4 *
5 * description: Holds sound data structures and functions
6 *
7 * date: 13:14,29-14-2002
8 */
9
10#ifndef _SOUND_BUFFERS_H_
11#define _SOUND_BUFFERS_H_
12
13#include <stdio.h>
14#include <fcntl.h>
15#include <stdlib.h>
16#include <string.h>
17
18struct sound_buf {
19 char *id;
20 unsigned char *data;
21 unsigned int data_i;
22 unsigned int play_i;
23 unsigned int startloop,endloop;
24 unsigned char volume;
25 unsigned char channels;
26 int mode;
27 struct sound_buf *next;
28};
29
30
31struct sound_buf *sbuf_init();
32struct sound_buf *sbuf_add(struct sound_buf *list,char *id);
33struct sound_buf *sbuf_select(struct sound_buf *list,char *id);
34int sbuf_delete(struct sound_buf *list,char *id);
35
36
37
38
39#endif
diff --git a/doc/examples/SoundRecorder/include/soundcard.h b/doc/examples/SoundRecorder/include/soundcard.h
deleted file mode 100644
index 272cf904..00000000
--- a/doc/examples/SoundRecorder/include/soundcard.h
+++ /dev/null
@@ -1,31 +0,0 @@
1/* by Luis Figueiredo (stdio@netc.pt)
2 *
3 * file: soundcard.h
4 *
5 * description: handlers soundcard setup
6 *
7 * date: 17:00,13-00-2002
8 */
9
10#ifndef _SOUNDCARD_H_
11#define _SOUNDCARD_H_
12
13#include <fcntl.h>
14#include <sys/soundcard.h>
15#include <stdio.h>
16#include <sys/ioctl.h>
17
18#include "debug.h"
19
20struct soundcard_setup {
21 int rate;
22 char channels;
23 int fmt;
24};
25
26int soundcard_init(const char *, struct soundcard_setup *);
27
28
29
30
31#endif
diff --git a/doc/examples/SoundRecorder/include/soundmixer.h b/doc/examples/SoundRecorder/include/soundmixer.h
deleted file mode 100644
index f071a4e0..00000000
--- a/doc/examples/SoundRecorder/include/soundmixer.h
+++ /dev/null
@@ -1,23 +0,0 @@
1/* by Luis Figueiredo (stdio@netc.pt)
2 *
3 * file: soundmixer.h
4 *
5 * description: Sound mixer using (soundbuffers.c)
6 *
7 * date: 17:13,13-13-2002
8 */
9
10#ifndef _SOUNDMIXER_H_
11#define _SOUNDMIXER_H_
12
13#include <stdio.h>
14#include <unistd.h>
15
16
17#include "soundbuffers.h"
18
19#define _SDMAX 44100 // quarter second *2 *2
20
21void sound_process(int soundfd,struct sound_buf *list);
22
23#endif
diff --git a/doc/examples/SoundRecorder/src/main.c b/doc/examples/SoundRecorder/src/main.c
deleted file mode 100644
index f1967da6..00000000
--- a/doc/examples/SoundRecorder/src/main.c
+++ /dev/null
@@ -1,296 +0,0 @@
1/* by Luis Figueiredo (stdio@netc.pt)
2 *
3 * file: main.c
4 *
5 * description: Programa main
6 *
7 * date: 16:47,13-47-2002
8 */
9
10
11#include "soundcard.h"
12#include "soundbuffers.h"
13#include "soundmixer.h"
14#include "web_server.h"
15#include <signal.h>
16
17#define ADJUST_VOLUME(s, v) (s = (s*v)/128)
18
19int PORT=80;
20struct sound_buf *SoundBuf;
21
22void outgif() {
23 char *nam;
24 struct sound_buf *sbuf=NULL;
25 char gif[640*40+1];
26 int x=0,y=0;
27 int i,h=20;
28 short d;
29 nam=malloc(strlen(ClientInfo->request)-3);
30 memcpy(nam,ClientInfo->request+1,strlen(ClientInfo->request)-4);
31 nam[strlen(ClientInfo->request)-5]=0;
32 sbuf=sbuf_select(SoundBuf,nam);
33 if(sbuf!=NULL) {
34 if(sbuf->data_i>_SDMAX) {
35 if(gif!=NULL) {
36 memset(gif,0,640*40);
37 for(i=0;i<1280;i++) {
38 x=i/2;
39 //y=(*((unsigned short *)sbuf->data+((i*4)%640))%20)+10;
40 d=((sbuf->data[((i*((sbuf->data_i-1280)/2560))*2)+1]<<8)|sbuf->data[((i*((sbuf->data_i-1280)/2560))*2)]);
41 y=d/(32767/20)+20;
42 //fprintf(stderr,"y=%d\n",y);
43 //gif[x+y*640]=10;
44 if(h>y) {
45 for(h=20;h>y;h--) gif[x+h*640]=10;
46 } else {
47 for(h=20;h<=y;h++) gif[x+h*640]=10;
48 };
49
50 };
51 printf("Cache-control: no-cache\r\n");
52 printf("Content-type: image/gif\r\n\r\n");
53 web_client_gifoutput(gif,640,40,0);
54 };
55 };
56 };
57 free(nam);
58 return;
59};
60void dlbuf() {
61 char *nam;
62 struct sound_buf *sbuf=NULL;
63 nam=malloc(strlen(ClientInfo->request)-3);
64 memcpy(nam,ClientInfo->request+1,strlen(ClientInfo->request)-4);
65 nam[strlen(ClientInfo->request)-5]=0;
66 sbuf=sbuf_select(SoundBuf,nam);
67 printf("Content-type: x-form/application\r\n\r\n");
68 if(sbuf!=NULL) {
69 fwrite(sbuf->data,sbuf->data_i,1,stdout);
70 };
71
72};
73
74void index_html() {
75 struct sound_buf *sbuf=NULL;
76 char *id;
77 char *tmp;
78 int i;
79 unsigned char *soundout=NULL;
80 short src1,src2;
81 int dst_sample;
82 const int max_audioval =((1<<(16-1))-1);
83 const int min_audioval =-(1<<(16-1));
84 int bigger=0;
85
86 printf("Cache-control: no-cache\r\n");
87 printf("Content-type: text/html\r\n\r\n");
88 printf("<HTML>\n");
89 printf("<BODY>\n");
90 printf("<center>Sound Recorder (webgui)</center>\n");
91 if(*ClientInfo->Post("sbufnew")!=0) {
92 if(*ClientInfo->Post("sbufname")!=0) {
93 if(!sbuf_select(SoundBuf,ClientInfo->Post("sbufname"))) {
94 sbuf=sbuf_add(SoundBuf,ClientInfo->Post("sbufname"));
95 if(ClientInfo->MultiPart("sbufdata").size>0) {
96 sbuf->data=malloc(ClientInfo->MultiPart("sbufdata").size);
97 memcpy(sbuf->data,ClientInfo->MultiPart("sbufdata").data,ClientInfo->MultiPart("sbufdata").size);
98 sbuf->data_i=ClientInfo->MultiPart("sbufdata").size;
99 };
100 } else {
101 printf("<FONT color='FF0000'>Sound buffer exists</font>\n");
102 };
103
104 }else {
105 printf("<FONT color='FF0000'>Sound buffer name is empty</font>\n");
106 };
107 };
108 if(*ClientInfo->Post("sbufvol")!=0) {
109 sbuf=SoundBuf->next;
110 while(sbuf!=NULL) {
111 tmp=malloc(strlen(sbuf->id)+5);
112 snprintf(tmp,strlen(sbuf->id)+5,"%s.vol",sbuf->id);
113 sbuf->volume=atoi(ClientInfo->Post(tmp))%129;
114 free(tmp);
115 sbuf=sbuf->next;
116 }
117 };
118 if(*ClientInfo->Post("sbufch")!=0) {
119 sbuf=SoundBuf->next;
120 while(sbuf!=NULL) {
121 tmp=malloc(strlen(sbuf->id)+4);
122 snprintf(tmp,strlen(sbuf->id)+4,"%s.ch",sbuf->id);
123 sbuf->channels=atoi(ClientInfo->Post(tmp))%3;
124 free(tmp);
125 sbuf=sbuf->next;
126 }
127 };
128
129 printf("<form method='POST' enctype='multipart/form-data'>\n");
130
131 printf("Sound Buffer:<BR>\n");
132 printf("Name:<input type=text name='sbufname' size=5 maxlength=10><BR>\n");
133 printf("Data:<input type=file name='sbufdata'><BR>\n");
134 printf("<input type=submit name='sbufnew' value=' New '><BR>\n");
135
136 printf("<table width=100%% cellpadding=2 cellspacing=0 bgcolor='AAAAAA'>\n");
137 printf("<TR><TD colspan=7 align=center><font face='Helvetica' size=6 color='FFFFFF'> Sound Buffers </font></TD></TR>\n");
138 sbuf=SoundBuf->next;
139 i=0;
140 while(sbuf!=NULL) {
141 if(*ClientInfo->Post("sbufprocess")!=0) {
142 if(atoi(ClientInfo->Post(sbuf->id))==5) {
143 sbuf->mode=0;
144 sbuf->play_i=0;
145 if(sbuf->data_i>bigger) {
146 bigger=sbuf->data_i;
147 soundout=realloc(soundout,bigger);
148 };
149 for(i=0;i<sbuf->data_i;i+=4) {
150 // LEFT
151 src1=((sbuf->data[i+1]<<8) | sbuf->data[i]);
152 ADJUST_VOLUME(src1,sbuf->volume);
153 src2=((soundout[i+1]<<8) | soundout[i]);
154 dst_sample=src1+src2;
155 if ( dst_sample > max_audioval ) {
156 dst_sample = max_audioval;
157 } else if ( dst_sample < min_audioval ) {
158 dst_sample = min_audioval;
159 }
160 soundout[i]=dst_sample &0xFF;
161 dst_sample>>=8;
162 soundout[i+1]=dst_sample & 0xFF;
163 // RIGHT
164 src1=((sbuf->data[i+1+2]<<8) | sbuf->data[i+2]);
165 ADJUST_VOLUME(src1,sbuf->volume);
166 if(sbuf->channels==2) {
167 src2=((soundout[i+1+2]<<8) | soundout[i+2]); // join left to right
168 } else {
169 src2=((soundout[i+1]<<8) | soundout[i]); // separate
170 };
171 dst_sample=src1+src2;
172 if ( dst_sample > max_audioval ) {
173 dst_sample = max_audioval;
174 } else if ( dst_sample < min_audioval ) {
175 dst_sample = min_audioval;
176 }
177 soundout[i+2]=dst_sample &0xFF;
178 dst_sample>>=8;
179 soundout[i+2+1]=dst_sample & 0xFF;
180 };
181
182 } else {
183 sbuf->mode=atoi(ClientInfo->Post(sbuf->id));
184 tmp=malloc(strlen(sbuf->id)+5);
185 snprintf(tmp,strlen(sbuf->id)+5,"%s.vol",sbuf->id);
186 sbuf->volume=atoi(ClientInfo->Post(tmp))%129;
187 free(tmp);
188 sbuf->play_i=0;
189 };
190 };
191 if(sbuf->mode!=4) {
192 printf("<TR><TD bgcolor='EFEFEF'><font face='Verdana'>%s</font></TD><TD>",sbuf->id);
193 printf("<select name='%s'>",sbuf->id);
194 printf("<option value='0' %s>none</option>\n",(atoi(ClientInfo->Post(sbuf->id))==0)?"selected":"");
195 printf("<option value='1' %s>play</option>\n",(atoi(ClientInfo->Post(sbuf->id))==1)?"selected":"");
196 printf("<option value='2' %s>record</option>\n",(atoi(ClientInfo->Post(sbuf->id))==2)?"selected":"");
197 printf("<option value='3'>reset</option>\n");
198 printf("<option value='4'>delete</option>\n");
199 printf("<option value='5'>mixfrom</option>\n");
200 printf("<option value='6'>mixto</option>\n");
201 printf("</select>\n");
202 printf("</TD><TD>%dm:%ds</TD>",(sbuf->data_i/44100/2/2)/60,(sbuf->data_i/44100/2/2%60));
203 printf("</TD><TD>\n");
204 printf("<select name='%s.ch'>\n",sbuf->id);
205 printf("<option value='1' %s>Mono</option>\n",(sbuf->channels==1)?"selected":"");
206 printf("<option value='2' %s>Stereo</option>\n",(sbuf->channels==2)?"selected":"");
207 printf("</select></TD>");
208
209 printf("</TD><TD>Volume:<BR>\n");
210 printf("<input type=text name=%s.vol size=3 maxlength=3 value='%d'></TD>",sbuf->id,sbuf->volume);
211 printf("<TD width=100%%> <input type=image width=100%% height=40 src='/%s.gif' border=0></TD>\n",sbuf->id);
212 printf("<TD><a href='/%s.raw'>Download</a></TD></TR>\n",sbuf->id);
213 }
214 if(sbuf->mode==3) {
215 sbuf->data_i=0;
216 sbuf->play_i=0;
217 free(sbuf->data);
218 sbuf->data=NULL;
219 sbuf->mode=0;
220 };
221
222 id=sbuf->id;
223 sbuf=sbuf->next;
224 if(atoi(ClientInfo->Post(id))==4) {
225 sbuf_delete(SoundBuf,id);
226 }
227 i++;
228 };
229 // mix to (6)
230 sbuf=SoundBuf->next;
231 while(sbuf!=NULL) {
232 if(atoi(ClientInfo->Post(sbuf->id))==6) {
233 free(sbuf->data); // free previous
234 sbuf->data=malloc(bigger+1);
235 memcpy(sbuf->data,soundout,bigger);
236 sbuf->data_i=bigger;
237 sbuf->mode=0;
238 sbuf->play_i=0;
239 sbuf->volume=128;
240 };
241 sbuf=sbuf->next;
242 };
243 if(i) printf("<TR><TD align=center valign=center>.</TD><TD><input type=submit name='sbufprocess' value=' Process '></TD><TD align=center valign=center>.</TD><TD><input type=submit name='sbufch' value='Set'></TD><TD><input type=submit name='sbufvol' value='Set'></TD><TD>.</TD><TD>.</TD></TR>\n");
244
245 printf("</TABLE>\n");
246 printf("</form>\n");
247
248
249
250
251
252
253};
254
255
256
257
258
259
260
261
262
263
264int main() {
265 struct web_server server;
266 int soundfd;
267 struct soundcard_setup SoundSetup;
268 signal(SIGPIPE,SIG_IGN);
269
270 SoundBuf=sbuf_init();
271
272
273 SoundSetup.rate=44100;
274 SoundSetup.channels=2;
275 SoundSetup.fmt=16;
276
277 soundfd=soundcard_init("/dev/dsp",&SoundSetup);
278 if(soundfd<1) {
279 return 0;
280 };
281
282
283 while(!web_server_init(&server,PORT,NULL,0))PORT++;
284 printf("http://localhost:%d\n",PORT);
285
286 web_server_addhandler(&server,"* /*.gif",outgif,WS_LOCAL);
287 web_server_addhandler(&server,"* /*.raw",dlbuf,WS_LOCAL);
288 web_server_addhandler(&server,"* /*",index_html,WS_LOCAL);
289
290 while(1) {
291 sound_process(soundfd,SoundBuf);
292 web_server_run(&server);
293 };
294
295
296};
diff --git a/doc/examples/SoundRecorder/src/soundbuffers.c b/doc/examples/SoundRecorder/src/soundbuffers.c
deleted file mode 100644
index de021945..00000000
--- a/doc/examples/SoundRecorder/src/soundbuffers.c
+++ /dev/null
@@ -1,86 +0,0 @@
1/* by Luis Figueiredo (stdio@netc.pt)
2 *
3 * file: sound_buffers.c
4 *
5 * description: Sounddata procedures
6 *
7 * date: 13:23,29-23-2002
8 */
9
10#include "soundbuffers.h"
11
12
13/*
14 * init list
15 */
16struct sound_buf *sbuf_init() {
17 struct sound_buf *head;
18 head=malloc(sizeof(struct sound_buf));
19 head->next=NULL;
20 head->data_i=0;
21 head->data=NULL;
22 head->id=NULL;
23 return head;
24};
25
26struct sound_buf *sbuf_select(struct sound_buf *list,char *id) {
27 struct sound_buf *temp=list;
28 while(temp->next!=NULL) {
29 if(temp->next->id!=NULL) {
30 if(!strcmp(temp->next->id,id)) {
31 return temp->next;
32 };
33 };
34 temp=temp->next;
35 };
36 return NULL;
37};
38
39
40/*
41 * next prototipe go to select_buffer
42 */
43struct sound_buf *sbuf_add(struct sound_buf *list,char *id) {
44 struct sound_buf *temp=list;
45 while(temp->next!=NULL) {
46 if(temp->next->id!=NULL) {
47 if(!strcmp(temp->next->id,id)) {
48 return NULL;
49 };
50 temp=temp->next; // Next buffer
51 };
52 };
53 // id is new lets create this buffer
54 temp->next=malloc(sizeof(struct sound_buf));
55 // lets copy the new id
56 temp->next->id=malloc(strlen(id)+1);
57 strncpy(temp->next->id,id,strlen(id));
58 temp->next->id[strlen(id)]=0;
59 // zero the rest;
60 temp->next->data=NULL;
61 temp->next->data_i=0;
62 temp->next->play_i=0;
63 temp->next->mode=0;
64 temp->next->volume=128;
65 temp->next->next=NULL;
66 return temp->next;
67};
68
69int sbuf_delete(struct sound_buf *list,char *id) {
70 struct sound_buf *temp=list;
71 struct sound_buf *t;
72 while(temp->next!=NULL) {
73 if(temp->next->id!=NULL) {
74 if(!strcmp(temp->next->id,id)) {
75 t=temp->next;
76 temp->next=temp->next->next;
77 free(t->data);
78 free(t->id);
79 free(t);
80 return 1;
81 };
82 };
83 temp=temp->next;
84 };
85 return 0;
86};
diff --git a/doc/examples/SoundRecorder/src/soundcard.c b/doc/examples/SoundRecorder/src/soundcard.c
deleted file mode 100644
index 14b581b2..00000000
--- a/doc/examples/SoundRecorder/src/soundcard.c
+++ /dev/null
@@ -1,49 +0,0 @@
1/* by Luis Figueiredo (stdio@netc.pt)
2 *
3 * file: soundcard.c
4 *
5 * description: handlers soundcard setup
6 *
7 * date: 17:00,13-00-2002
8 */
9
10#include "soundcard.h"
11
12
13
14
15
16
17int soundcard_init(const char *dev, struct soundcard_setup *ss) {
18 int ret;
19 int soundfd;
20 soundfd=open(dev,O_RDWR|O_NONBLOCK);
21 if(soundfd <1) {
22 perror("open");
23 return -1;
24 }
25 IFDEBUG(fprintf(stderr,"soundcard.c: Setting soundcard:\n"));
26 IFDEBUG(fprintf(stderr,"soundcard.c: rate: %d\n",ss->rate));
27 ret=ioctl(soundfd,SNDCTL_DSP_SPEED,&ss->rate);
28 if(ret==-1) {
29 perror("ioctl");
30 return-1 ;
31 };
32 IFDEBUG(fprintf(stderr,"soundcard.c: channels: %d\n",ss->channels));
33 ret=ioctl(soundfd,SNDCTL_DSP_CHANNELS,&ss->channels);
34 if(ret==-1) {
35 perror("ioctl");
36 return -1;
37 };
38 IFDEBUG(fprintf(stderr,"soundcard.c: fmt %d\n",ss->fmt));
39 ret=ioctl(soundfd,SNDCTL_DSP_SETFMT,&ss->fmt);
40 if(ret==-1) {
41 perror("ioctl");
42 return -1;
43 };
44 IFDEBUG(fprintf(stderr,"Sound card setup sucessfull\n"));
45 return soundfd;
46};
47
48
49
diff --git a/doc/examples/SoundRecorder/src/soundmixer.c b/doc/examples/SoundRecorder/src/soundmixer.c
deleted file mode 100644
index 4532d06c..00000000
--- a/doc/examples/SoundRecorder/src/soundmixer.c
+++ /dev/null
@@ -1,104 +0,0 @@
1/* by Luis Figueiredo (stdio@netc.pt)
2 *
3 * file: soundmixer.c
4 *
5 * description: Sound mixer using (soundbuffers.c)
6 *
7 * date: 17:13,13-13-2002
8 */
9
10
11#include "soundmixer.h"
12
13
14int SDMAX=_SDMAX;
15#define ADJUST_VOLUME(s, v) (s = (s*v)/128)
16
17int soundout_i=-1;
18void sound_process(int soundfd,struct sound_buf *list) {
19 int soundin_i;
20 struct sound_buf *sbuf;
21 unsigned char soundin[_SDMAX+1];
22 unsigned char soundout[_SDMAX+1];
23 int playit=0;
24 int i;
25 short src1,src2;
26 int dst_sample;
27 const int max_audioval =((1<<(16-1))-1);
28 const int min_audioval =-(1<<(16-1));
29 soundin_i=read(soundfd,soundin,_SDMAX);
30 sbuf=list->next;
31 while(sbuf!=NULL) {
32 if(soundin_i>0) {
33 if(sbuf->mode==2) {
34 sbuf->data=realloc(sbuf->data,sbuf->data_i+soundin_i);
35 memcpy(sbuf->data+sbuf->data_i,soundin,soundin_i);
36 sbuf->data_i+=soundin_i;
37 };
38 };
39 if(sbuf->mode==1 && soundout_i==-1) {
40 for(i=0;i<SDMAX && (sbuf->play_i+i)<sbuf->data_i;i+=4) {
41 // LEFT
42 src1=((sbuf->data[sbuf->play_i+i+1]<<8) | sbuf->data[sbuf->play_i+i]);
43 ADJUST_VOLUME(src1,sbuf->volume);
44 src2=((soundout[i+1]<<8) | soundout[i]);
45 dst_sample=src1+src2;
46 if ( dst_sample > max_audioval ) {
47 dst_sample = max_audioval;
48 } else if ( dst_sample < min_audioval ) {
49 dst_sample = min_audioval;
50 }
51 soundout[i]=dst_sample &0xFF;
52 dst_sample>>=8;
53 soundout[i+1]=dst_sample & 0xFF;
54 // RIGHT
55 src1=((sbuf->data[sbuf->play_i+i+1+2]<<8) | sbuf->data[sbuf->play_i+i+2]);
56 ADJUST_VOLUME(src1,sbuf->volume);
57 if(sbuf->channels==2) {
58 src2=((soundout[i+1+2]<<8) | soundout[i+2]); // join left to right
59 } else {
60 src2=((soundout[i+1]<<8) | soundout[i]); // separate
61 };
62 dst_sample=src1+src2;
63 if ( dst_sample > max_audioval ) {
64 dst_sample = max_audioval;
65 } else if ( dst_sample < min_audioval ) {
66 dst_sample = min_audioval;
67 }
68 soundout[i+2]=dst_sample &0xFF;
69 dst_sample>>=8;
70 soundout[i+2+1]=dst_sample & 0xFF;
71
72 };
73 sbuf->play_i+=SDMAX;
74 if(sbuf->play_i>sbuf->data_i){
75 if(sbuf->mode==1) {
76 sbuf->mode=0; // end,stop it
77 }
78 if(sbuf->mode==3) {
79 sbuf->play_i=0;
80 };
81 }
82 playit=1;
83 };
84 sbuf=sbuf->next;// next buffer
85 };
86 if(playit) {
87 soundout_i=0;
88 playit=0;
89 };
90 if(soundout_i<SDMAX && soundout_i!=-1) {
91 i=write(soundfd,soundout+soundout_i,SDMAX-soundout_i);
92 if(i>0) {
93 soundout_i+=i;
94 };
95 } else {
96 memset(soundout,0,SDMAX);
97 soundout_i=-1;
98 };
99
100}
101
102
103
104
diff --git a/doc/examples/cgi-bin/index.cgi b/doc/examples/cgi-bin/index.cgi
deleted file mode 100644
index 4f23614b..00000000
--- a/doc/examples/cgi-bin/index.cgi
+++ /dev/null
@@ -1,1137 +0,0 @@
1#!/usr/bin/perl
2# Footnet software experimental de football para a net (cgi)... por Luis Figueiredo (stdio@netc.pt)
3#
4#
5#
6
7#use strict;
8my %POST;
9my %QUERY_STRING;
10my %COOKIE;
11my %img;
12my $stdindata;
13my $softversion="Foot ball net V0.5 (alpha)\n";
14
15
16## CONFIG DATABASE
17$dbname="footaid";
18$dbdriver="mysql";
19$dbuser="footaid";
20$dbpass="sqlpass";
21
22
23# convert images to hex strings 'unpack("h*",..);'
24$f1=shift;
25if($f1 eq "--conv") {
26 $file1 = shift;
27 open($ff,"< $file1") or die "Cannot find file $file1\n";
28 while(<$ff>) {
29 $data.=$_;
30 };
31 $newdata=unpack("h*",$data);
32 print $newdata;
33 exit;
34};
35if($f1 eq "--initdb") {
36 print "Will create on database $dbname\n";
37 $db=DBI->connect("dbi:$dbdriver:dbname=$dbname","$dbuser","$dbpass");
38 $db->do("create table userinfo (userid varchar(14) unique not null,password varchar(14),nome varchar(32),email varchar(160),phone varchar(13),lid integer,lldate integer default '0')");
39 $db->do("create table msg (id integer unique not null,useridto varchar(14) not null,useridfrom varchar(14) not null,data integer,subject varchar(40),mensagem text,lida varchar(1) default '0')");
40 $db->do("create table forum (id integer unique not null,useridfrom varchar(14) not null, subject varchar(40),message text,date integer,replyto integer default '-1')");
41 $db->do("create table noticia (id integer unique not null,useridto varchar(14) not null,noticia text,date integer,rdate integer,lida varchar(1) default '0')");
42 $db->do("create table equipa (equipaid varchar(60) unique not null,userid varchar(14) unique,jogdisp integer default '12')");
43 $db->do("create table jogador (nome varchar(32) unique not null,equipaid varchar(60) not null,vel integer default '0',forc integer default '0',agi integer default '0',efi integer default '0',exp integer default '0',golosm integer default '0',fel integer default '500',tipo integer default '2',doing integer default '0',ordenado integer default '10')");
44 $db->do("create table conta (id integer unique not null,userid varchar(14) unique not null,value integer)");
45 $db->do("create table treino (jogid varchar(160) unique not null,treino varchar(5),date integer,fdate integer)");
46 $db->do("create table pos (id integer unique not null,namepos varchar(60))");
47 $db->do("insert into pos values('0','Guarda Redes');");
48 $db->do("insert into pos values('1','Defesa');");
49 $db->do("insert into pos values('2','Médio');");
50 $db->do("insert into pos values('3','Avançado');");
51 $db->do("create table doing (id integer not null,dowhat varchar(60))");
52 $db->do("insert into doing values('0','Nada');");
53 $db->do("insert into doing values('1','Treino');");
54 $db->do("insert into doing values('2','Jogar');");
55 $db->do("insert into doing values('3','Lesionado');");
56 exit;
57};
58
59
60
61while(<STDIN>) {
62 $stdindata.=$_;
63};
64#print STDERR "stdindata is $stdindata\n";
65if($ENV{QUERY_STRING}) {
66 my (@varsdata)=split(/&/,$ENV{QUERY_STRING});
67 foreach (@varsdata) {
68 my ($name,$value)=split(/=/,$_);
69 $value =~ s/\+/ /g;
70 $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
71 $QUERY_STRING{$name}=$value;
72 };
73
74};
75if($ENV{REQUEST_METHOD} =~ m/POST/ && $ENV{CONTENT_TYPE} =~ m/application\/x-www-form-urlencoded/i) {
76 my (@varsdata)=split(/&/,$stdindata);
77 foreach (@varsdata) {
78 my ($name,$value)=split(/=/,$_);
79 $value =~ s/\+/ /g;
80 $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
81 $POST{$name}=$value;
82 };
83
84};
85if($ENV{HTTP_COOKIE} || $ENV{COOKIE}) {
86 #print STDERR "$ENV{HTTP_COOKIE}\n";
87 my $cookie=$ENV{HTTP_COOKIE} || $ENV{COOKIE};
88 my(@cookiedata)=split(/; /,$cookie);
89 foreach(@cookiedata) {
90 $_ =~ /(.*?)=(.*)/;
91 $COOKIE{$1}=$2;
92 };
93};
94sub mydate {
95 my $format=shift;
96 my($time) = @_;
97 my(%mult) = ('s'=>1,
98 'm'=>60,
99 'h'=>60*60,
100 'd'=>60*60*24,
101 'M'=>60*60*24*30,
102 'y'=>60*60*24*365);
103 my($offset);
104 if (!$time || (lc($time) eq 'now')) {
105 $offset = 0;
106 } elsif ($time=~/^\d+/) {
107 $offset=($time-time);
108 } elsif ($time=~/^([+-]?(?:\d+|\d*\.\d*))([smhdMy]?)/) {
109 $offset = ($mult{$2} || 1)*$1;
110 } else {
111 $offset=($time-time);
112 }
113 my(@MON)=qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/;
114 my(@LMON)=qw/January February March April May June July August September October November December/;
115 my(@WDAY) = qw/Sun Mon Tue Wed Thu Fri Sat/;
116 my(@LWDAY) = qw/Sunday Monday Tuesday Wednesday Thursday Friday Saturdat/;
117 my($sec,$min,$hour,$mday,$mon,$year,$wday) = gmtime(time+$offset);
118 $year+=1900;
119 $format =~ s/\%Y/$year/eg;
120 $format =~ s/\%a/$WDAY[$wday]/eg;
121 $format =~ s/\%A/$LWDAY[$wday]/eg;
122 $format =~ s/\%m/sprintf("%02d",$mon+1)/eg;
123 $format =~ s/\%d/sprintf("%02d",$mday)/eg;
124 $format =~ s/\%H/sprintf("%02d",$hour)/eg;
125 $format =~ s/\%M/sprintf("%02d",$min)/eg;
126 $format =~ s/\%S/sprintf("%02d",$sec)/eg;
127 $format =~ s/\%b/$MON[$mon]/eg;
128 $format =~ s/\%B/$LMON[$mon]/eg;
129 $format =~ s/\%Z/GMT/g;
130 $format =~ s/\%g/time()+$offset/eg;
131 return $format;
132}
133sub cookie {
134 my $name=shift;
135 my $value=shift;
136 my $expire=shift;
137 if($value eq "") {
138 print "Set-Cookie: $name; path=$ENV{SCRIPT_NAME}; ";
139 } else {
140 print "Set-Cookie: $name=$value; path=$ENV{SCRIPT_NAME}; ";
141 };
142 if($expire) {
143 print "expires=".mydate("%a, %d-%b-%Y %H:%M:%S %Z",$expire);
144 };
145 #print " secure";
146 print "\n"; # end cookie
147};
148
149
150
151
152
153
154#Inside images ;)
155# packed imgs 'h*';
156$img{title}=<<'EOL';
1577494648393164f108c007e00002020401478c5789042788461ac80946c8492658cd58c82336c4644fa88119a7ae07e32b56ea0958c74478e96b2e896f1cd98238882724494649c7297cd7a33ac31244b7c718e94888e87148e7414aa54035e91d5ae83b4cd99337c77837b46f10680e18ab2a34b8e117a85d28e753835a2037a90032c48c59d7b03ac83775c7303ca89f06c75948c9197da8752ac60478e86d88d7ca3ababcb346aa6da7b41d356a41f48f38ca697be71298e72688e7398bea0e82f79539c87968e57a7a5be36aa65950f75aa7aa1549aa3a38e8524d553d07c75178893915faa237f5078f541127f76c88a84f47f91a89d82d77f94388d81158c84558d83247c49236d40a7ddddcd8d82746c4823265441ca87f47d7d138d93e76c4a12fd8806ea76068f95084f4b339d75347f62d89d81d77f93689b45d58881329d7065678ab27778120e79d57d76b3ab84e52e7a75ececcc2b8de04c8b027f77a49d74e73772018656128da6288f76e3abb5e5187c43ba80f58d74159d87c68d87336a83858fd0688dc0c7efefcf030313d87e33276972f37976158b85e9e9c96697d1d34725a77b730d5e62d395743655b1687571488d33d957631988720689a3292949478380194f43e55813264ac4515151e56745ac4c12fa5fb1578131ec8d4215a6e1282848856d16a3a3837a82d5a96b01b4a57155a7d3ba81267f7c739f6db3cc0f12d95444f853734f88960a8cb16780a1979401e986407982432554c1a99513fe79466f82858f74f38f73c48f7514776542f4b6653a88433a69c2c463e3ee6ac5e8aa426879f177c7e1d98d029970146fb1458f8727a96183d4a815269270d49a35e4b9f5fd7b056529c69b8582ab72d6a766808994819d9473ab90749b71148d856769d3c09b8076bb83866fa0858b77f0ab8765ab86e5d455354cc9923cc8233cca32e5d84306ca55a7a787997e82e59bd5db84b24b9273bc82357e76f59c83456db2f9bf8685c98673a484846bc6e1e5d1c1e9c793ecdc82f3e69524c7e40bbac0bb71078bb383bf95fa9993043b58743b69533fc8b34fcb538cc6048ec2a4acc194ffffff12efe0d41646560277964786027494d40500129f4010a000ff00c2000000004f108c000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b7efc0a34b8e1d4ab4b9e3d8a35bae5dcab5bbe7d0b36bce9d4bb6bdebd8b37beeddcbb7bfefd0c38b0f1e4cb8b1f3e8c39b2f5eccb9b3f7e0d3ab4f9e4dbab5fbe8d3bb6fdecdbbb7ffe0e3cefb8f1f4ebcb9f3f8e3dbaf5fcebdbbf7f0f3ebcf0beb441b2651c2898bdf288fbe7742840820a32e80e18742286c0296452470d1c806154c1321e133745811440aa0c270110f7c9136c603c8814b09191c5042ca1b704035814908e2e2cb395c32e5ca3e5031c44821a0d35dce8d2c409e4a3b5c50714016f8d3140c0424d173cd0ad871e5001c44f11a0c22c45966c58748b28bc141b4c2cb4c221489b8c89534c3888c31001248c8493881e6a81d40c9d40e0472e0b38d9b34e9b3421b7621e7ef9e7230c7230b3c9145c1af242a982a42e0082060840a1880e02388541d453c1a7802a8842a9882240501739f4b8f26c8336d8736e8b3653d3ef814e09ef54e1994e29d4e3915e495562485ceabb679f568921c89b8499766a948cc08c212104002f4e29bc82bd0611bc427cc54e66c9d4cc957ed9a76e9c720a0ea0ab301a6822aa8eb0bae246f1e7bf152a9052bf5cb2fa02490db5fa0229e4a96438f064821a5839068aacd3605b005c60b14b96b0914609044c9357c51dd073605e3ab0e303e3295ca3056f16d4925a4538e6bab5cba44ad3034aca4239e42319a8495c4592c891aa8a2308b2eac145249054490cbcfc0a8893c6c31f40052db984b8157e2d872e997af1e7c5305b4de7c8b3eef185b1aa8a8c72dcb5f2527f6eb815b06032ca033ce034c75814a04e3bbc5c91f6cd1f7c12f8ce369c24e9c923efc0b27dae23cc9b224398fb7ccecd3ffccb40d1ce0d547a9338a9bc4008983bc8c3839c5e37891a93549433dbd27ba7e4d2a75d482308577845c9b8e653b01b2f6403228622bb6222880fafbe8f5e7af50806fdbe8422af2fb85c4841a58110c2aac14e4831df4f3c07d2f4c713dce1b747180de2f6be2fec322367c1a48c974534fc40310ed24619642fdb4ed0958da2569213b035c0c281e0074c11909b3528efb372e14f63b804947e0e4930d613dee405b40a201a6972c10300707abf34ae415921dd983877063140184326e85e53fe97f4842d93412e63d586f8b7eebfe5532c73eb2fdbae208eb32dac8d79248f50e2127c0778e0578bfbd99fc041efffb1a1a969133846c23c815989c938071ea8bcd58cc01f331844cd483020a1079680c50e20b18f0c80e40546ba358cb1a673b311883ed0809bf4eece530248c0f478b903e568012b50d1c500a7f58f2c93c70c7051124650624ded6f6d1f73484a0c46542599290125c8c38cf866aa8bf540a2480101080490a40e16ff8d1ce849c5b8a8a4ba3d44ee4f78badf1e5031c541a44d8b6ced902832784e0cd13a7a74e3e24209fe814efd2413116f5bfcb71fb26434c294c4c42f0322470c5031de7740850c2a815c0318902a11d888082d37b3815a9ee499a447df18e1264236de812430a1cab2f3df975e246e0ee052cc163171a93e142304b4578f0c70d5ef8e28a1012a005006fc48f88578c2812278cb9d369082ba34d18123fb84aa2e98b9848013d296ccd9da42e4554a35e0449619802a292892150493fc9bbbe88e1e205fcd3ee1812ff4d54045617ba25854cb71a8c38327e7c0998ae459041964c008a191a270c24a14dcb4110ca9a15fc574528dd4a708331236c17634650dfc97882ce3ab378c626ba75a3e124ec17e0578a38818fce20508b0801f58f3f71adb57834a0a72b520fd619d09b7c3453720865424490a35a8ab38521a45a664cc502d39ca08aadfcba6eea3206522885981ba855ce395a09877ca3836f2bfe564241248a25134809cb58c62040b90eb2f5989611a68a6bc15e0128434a14088efd251022e93a3dd9432a8a61c73512220450442109083c255dc98f9788218ba660d0d146f809d55cc24d0d68630a00123f0f506f021f80880ca2d7a0de1044cc02080fa00412a34c4e96f29c21c1c51d6bc197106d8c69210e607f0b225bf4746d0e302643752b39d58cbde5a9a8b70e846aa19b922fa1251ac1697139711d0860240ca5f7450a204083381ae128d4e6d64eb9d20f7c40a91901fd2440b14269f226960119d486e220f55c04467613b8638234910f8380b2441ef4d58442804429b2c06f0730fe2444812ed88a0e6e041a3e6b269c9edd693da3246be15a484c5260e2557e1d1996c93c5cecde58c8b1259518ac2ee103bc3074a81352762ef346e039063329b24646b8093ae1a2830c10cf1058a0cf181076842834c6ba72c10f92b9c112fd78732cc8f0c70ad152e3ce4445cb933848512b3b8e5cc8360a58380d0caba3ed13af6ead38b1844400d5d48c5e037076dbea4670553f69e9c32d3a904b00529865433a1b1908d5ca02bc065a47f2c2dd01bc26650c5a0b967406135216e24a98d4c357b9332500a3ba0ca065048130eade09e657bcf40b62fd64a005006688b71d8b6a809adc070903c932e0ebe917d89d68d3a84f855614ec2c44a4d801c993bb248ee55f7bcb5c7af809de9a6210778bb006be273742c0ae667779591d09748c2461106c1532dcc7ce89134076c1f66f420ad0d092841efca0df0b2c206818388a534eb5c2fd311ab324f8e0b64450437514108c198e674542cb9ee968a32e0f2691f47b26d9e984ca4d71aec60542298fb388f4d7accc320b875de27d350c50ef20494dc5505f02748b71dd1982c43c1b047817b1a1289de302bb8d1ebf886c712d888bbcdb11ea8108640a10d0d3841830df0a5c9c781d486886bbaee70094cc532676b33dcbbecc0b8c87d02a7803836981638950f0820347e842219e950b73542516777afcdf7a7f369c0eb18129caf9421fa87ea78bb328e08684e7ca638550f0a1232845c01ed75ced1184e688099bf8e53216086460230c10e08d286122a0c334e4f927c1084c7f91990b43cf12d86db744aef0a70228d186f3b0a0050c32cdd5f563cb0f1970c30e51d8095432e91fc0a64a7fe4b4bc692562c316ceb2ebe10b7eeb7ff7e6b7d01a10bb7240240635c24d21ae7a08be7de7a11e004404400d35b0460b034b04b0d01c439d28d2c311b5d187d7676bd7ef77b0170170630d103e7d11e36a42d30fb49e7f00795fa0317320fc09e5b15a15260d62a41d18d185109d7700d117008e0250910440f50f37630d013401201a02d01e3b324f0026c21f00f80358ae7be0f28e086706707b07b00d36b0f40c03818554d62468e62c18b381b5510ef0e11148c109107b02655287b7d11234be3e42040f11cd3105795320320c40c21930188a30838930a30930a38ef868968b68c11ef0700227448fd7848c015e0fa51d0c24d24d21a78a98795a11428a58c587b0f405b0c10460d011887a8260a30c035a8b31d88ef02164161b5e11d88f887b0a588100a2d110303d0b23de3560d70f11bd3fe0e20be04c8cc0320c21a30ac8ac8ba8ca8841fa87760b8d18d11fa5650b77f68a58d012d0b245d01d0e45dc03109209989b44e8f804c8911630630e982657b0f507b0710e01bc8dc8c03f40c316e06e06506762d8e11316700df0c105b06b8670e00e11a05b42950770560c606d0f118f0d97d97ad0de0e508009c82f8242825a11158d217f89f8af8316745c112d0df87d86b8d014d4f205104f0ef0d147849113403114e89efb4f09e97711c30af09e8428ae0d854201f8710674242f401495f8811c091218e07498e05766765103b8a684d60096b87b0509b42e50ad0fb86d0cb4e118f0b599d09509d09d0800ad0c21242420719124f50911920549d218492488e0987c49c117763164270095b0d011b54f05104e3784b50270811a100c8211d97b59c598f0a47711af0c30b89739630810e30065324d01669710974699911c60221849150250248700650bd77009765795b05a9e11be3909b094f0406d11950789720f599d0cf0419b213d04207b9420f509b98697116d0c60560f21d69c99e990a9c112503d6876050ff8779c01603ef09206e0523e790f8611340c40f29389e0958ef9789889611a89b89c30010d50630b70810b25e018b99b99b9b40ae0b40811fb92211502f93f9500250f38d11910250dc3650ac96b0d777a9730e50b098594f0817d1172080a720e10d301a62a6b219420307e0b73e30ee9611c60fb9878e213f9b1a5f97f9b116c7af9527ac9c10d01d14e405235056224d9411c405607d9311ea9fa990add9411670630a89410d60d10d10a602e9011b7321a41ab40af571156004091a021c60150c20c20b1a8e0e114407c79c7dc33c055a7a9770d00c60dc04f07925d4e1190ad307204d3b70b05b21570013b749f59f561a64a7708e7e2171ab4ad4a3f9f4ac1101825ac77df03c0d01df0b50c10725469140cb9311efa10e2aa10cf72110b990a80ab70720511018b56810d50c30d10d60410b3a111b74030a6aba0af54c0511040e6ae50770221560560c4ac4aa70150500e11b58d585a9c773c07d0e11d00d006d0b5ad5a2d0f11c0ad50d3036a76ac21b70e30b704654c0d5019541171a5603aa909f21fb96aa8aa1500d0150d11f98faa009df0d015226227b9974b4051a1115f0c602e656078a3119d0c0a7209ea4d3411460710440a56c70d500107282e72117f4ba0e30195bfaf9a211560e6a909a095aa6aa7701daa70daa6da5a96b02bae116d0920d204165d05105e0b69c11aea36a3cae30030c219f4d1b7ca3b0195af5ae0974710460c10930b10360682f70d206efe03106d095a640cca64099907a0da50bc4a2f9d11e98eaaa0b399910bb9fda24ba84a05640640d000d93101d0f20ed87006d05f0ffaf10770cc0c6088a111c0aeba26ad50cea4b5b10df0a307253d08222fa350d10411d1bba07ca12b4c032bf5052b72b92bb2bd2bf2baca3aa6aa5bad0030b770b7b1dae11ae8a58f985b0b0be116e0d20400829dc06e08e04e0f1136a4d3e30570a1bc1ba6049b03669bd9ac6bae01a8c10a30b00b102147600503108e0920d00ffa77074b87bf21d2a7ab8aad4a5f9327050616c00b00df07c7e00810630c30840cbb060bf06a06a07a06a0bf0fb6639ae81706da6b0d01f50b4064824b34a7f47f4a053d02704ab58efb510f20400ef05e08e05f0c20770de0ad02e6376db4ebae8b2ca09b923801a43ed2360830bc3b50a703d026bd30c70611a60d50fc579b22bb40b9bd9bf9b4501ab3ab5ab6408ab8ab87b9202e8121c40040cc0b7b83b4dad11d89810e00f083a8718d117a4400d168e02f9c20f111db1db24bc2149b49b1d5db003689b32b420f4072be9bc00450f70e168e095a56064056087bb50a0cd21632d6ac7b37aa201bb2bbc003c0ff8c5863abbb840060ebb0cb7a02cbbf0840db06cbe8941c7b0910d01265fdae9a7f4b733fb270523e40ef0a1c4f0a8b2f98008009d0e10cf0f105604e0c8b211570b60a0546a22c24a9746f0149c03188372b30450b30360ef788d110d572c92c22bee8d2c930f2c13c33c53c63c93c920bc322163274acc00daf6cc11b3a01045cf080d09dad117605107f8d1cc20800cf0f11570b73fda030805c2193aac01d5fac03621185a93cb509e0e40f219a0632320d0c0dacaac11a3a010a9c010c70f08bcbccbdcbfda642211cf0750750a6cf10800e6c311cb821ac7392341ab01b15360d7cb30f700fb8e070b9111d523682c02b44a11184b5237bc360360221fc039c59cd6c11cc1179a99c4ccc070d0e11050e40cd7c07cf0e10b63e11923fcbaccc2107033690dd602bc4112d9bc32d7e219a00fcc403206aa3fcd112e77fc4ccb60d010d3149f50249349311a6c76cc20fbc1110fa6efb940d32ce01782d203601e85abb4a81190d1bc02bba0ae0d0dbc36382217f09a0abcc4058a4e053b5fcc50d10cd0010dd0c70c705c7bd7a702fbcf02fadd066be11ab9f508e31b2c21ac0990130130336d60a603b0611e4082bb15f2130304d14d34d79ca1182076574dd10b1dd01bc73f84602607113b9160d8721162265d77c6f038ad01fe53106e0920150d00fdb6ac511d5df5d82c89b6116b5e76121aa04d0f3dabc78a65bb11070ed0ed0cd0c503500108d0b604b9c11feab60c70922b3a45dd11f4008d699140149c21d5d3bdfac82c711b1597276d194f3d632e0699d911070070820c50cd0cd0350dd0e10d01b10727618260087ec76113ad16ef03117104f414928a75d140211d32a69d00b4a770ad0a8d3114bdac0fc5f8d611d722212037f0340ded5f0120e11b9ded0c504cd3507508d0f10e11b56922a602e764df1106812df40242c21c90a50a50c8d1d5df551105329dd211f4533ded3405f051b9119902fd4fd6cd20db017607d6b304537d0e0e1ddc1d211ba897c12d3114e303bfb94ace5043a01180ee5d1d53b0af0e3093d711940587121a267c39121200161fd1cdc9d4cddd07fde1129ac3069afac79af113f8bc8a30c21a80a8070e13082033e911cd6e21b557128c30b0f3e5e0d1171e24e91edd0d01c767d686e053911b6042e6d4322260dc8aa8411dc06d0eb9c60b7bcf0f5931113eeffac06d739e309110ddf11da0096ec40b05081fd4303f0b8e3f0c50b2064ed11c303b0840ac0bf08208406fae11e62f4eac89e0c218a035e80e336410b0e611a3ed21b46a939c578e88ec11610070a8ea8eb8ebb6c01cf9803bcdb00618a116fb2119d2843bc8e9e311a6971a77e0ebad0e20f2ed0135e55efac8fb4c017018e221b46da01e56606201d4e11fae430070b8eed0a00cd0900e11db0fbb6a0ac006079e840f11072830b159e0930f32f9ea8060e55e89e5ae5416949ae1e50d4254eaefaecdecdeed04beb016d86e0df0250a30c9b75cd21453554372e621ce31167effaad0ad0f59b5911170e0f079e79af7ec31a403de1e5552cfec115e45efe4c8ea00e8ee110cb0cbbf0d2f060828d114f7c43eecb218a08a060e0f013091da41ee002002f1e52d4d1143061062fc8e856c01150f4da77f4de03e21f72d04b43511b2e7abe2ede071f01183f55e06da9c299a31934b554de2000d498eb8e2be3f0a0020fb112cbb2fd2fd2ff11e7c78213c7a3f9e0aec90a1f65ebad741212ee006f2e5ac6b1152f1bec8ed01c200d0c20c077e0f03d5fb21e43d7c17ff70c6a31f51f9d0b5956ef012fe55ee6da60af08100deb315401126c3e5524f66f76fb8ea00e11e4cb6fc2fbf0f1101485317f78250ec904bf93fe6d97f6411b00af5c37123af08f28f64fd0176c800c6eb70cf06e9e21930eebcdc7a32bf51ef1fca559e2e49f8f09f085f67f8207bfd10810810c313a01b0bb27937f32f724fa0076f5ef55574fc11aafb6fbf00609eee119e0dec360ab5ab509fb21f600f067f77fc4e9411b0edf0ef00139e8c11a6ffc0e14489051e2cf7436edc350115223c48e18f870b8c7020405341d3e74098057c6947e42d5ab1392ff484f856ee863d69d462eb319f85a14e40f0e5624141a3040c081e6e052a0274d1564c8c59ba6430a828488215aecb7af1f4d5535bf09021e1c3aae7429723dd486146fb684f6ed816626bd6b76783b175e624908439e2d6a37116459a1134e510cdd02c4153d1828edaa274ec616c267c6c579f236663a98fc62b47bd3920f80a88d372efc15d9443d1a3ecc9d38fcff65ca66db262e7e35951cc6dea6325ff393d025cee4792624abbd603f5e3e2c01e0c1e98249bfc0e80394296e7071d1d1d5af4f7ec7a0a5bbe5112bb90e92cd8b150a0822af148bb07ada75cab777a88bc68d8b48933f447bb99c97afce0d9fcf3f3b6abe484934e01062d00625bc76795181cde25b814bae587855c68832e8bdc8896c8860a3ce01ebbdeebe6e23582d231db12f2db6ee938eec390619a160c34a2930314fc68360d1c5d2421f8b0e28c38349981ecbf7a03688f953018d07a1f0b109ba109fac0af62bc68523192041f7280c183fcf8b6ea90036425a29f660914e794d210537dc4085b4d4996387895a24cef0c7837e6bb1e60324f4e0b3cbd62b318221f6c3a0e74e245cbde93f3cf022b608111913bcc33f33639dcee042e2c4483058c4260872a3d8c8c58e48e16f0e72fcb1634324e2b6a5582d8061ee040262698281fc0df9c601aa9b54b988b019a1011978cc140d0432537129d77a2db4d3be54d053ab8a3fc937848bda70c63f43283401d33955b1e74b1a86a0279cde0ec544f3354b90f5fc3970858498536f3b46bed40471531d2f64936b0e1d24b86e6d8d343a9281ae0ee3253b5d35ea9062841ca9418d8828d061265402423712047732e3283f38dd164c88b4e9775e136eb9840d844219fcad9670b171e51b7318fcad086d60f1ce4212c0b635b92abef1c65b1e012efc2a882ac0b89120cea0808966a73abda9054f3622ff12484616f4e49956fcc5679d5867aed09e834ea3df751145e6b966d0e7a78e2a0e588b8638b127f4025118555ea61aca66e1ee09266124a6afa01c6320a67dfca75134c0a52e22420800c4e84221b445efc899f0037791b1891b9fc0ade26f8a3ec9968405ce63e6ceeb10f6dda914ccc9660d147c8e82822b8032e3ea0e327fe8f3367f9367546227687c3273662facf3bf0ee8f0a9f75e56fc14a3eaf5e483154eaffca10d3c8040ae0f0ea0a80e03135fe1e60d6c949be58dbdf968dc19db103a14ac887780432e25d567961138c0d12e2460997c91329159b59d5eac0cc066c80efa97f1879d7e247b702dd434f0b894d8738b1043d6cd1a100133b8edac26e8908ce0d1411400208d6c63e70f1c10bb34c0914c0d40f3421e36b8baadff887093ac9528b6881274918c13204026e818f19d45fbcf5ffaf71260d192047430065800e740a812a311fd503b1cf8b34de2d7f28f3cb00a0c737f9ce042cf0e78706d0a2cdd9300307fb9b4c07684b0d10702e2580a3223887190468e03118704c4d3cf84e004293037cc867c76ab01ab534d16a1a816c831e33c5892c90c3087b82853048d283b4719a045833ceda506e005234850160614903c0b6045ea1c10b689b091e90e2481621670d48e745def147c248d1508690074105f2f7ca740238ef8f10222a0093130f41213981796893ca98150ee1f3aa4b0111cb10e12eb846638296d89b862f50f28a0c81e386e8f8c92f499a4704a33d9271712e0268b38c14e064227c3b412c00608c5223608db4c30f15f28e0378a040a18c20020989a7986de1028be990e61250e844c0c1029750d60202a0d00086b0eb9f202a831c9031059cf1639768f3cf16c0ef068410a000d069681c5af2522011aa2b10138c3d59a30130e0469838c1044fc347cb76d13918c8e5ee05e200d270a3450f74042b089128af19274aa8c4aae09e925692b43ccf674b79054051f60b0844329cf0400b04c827909a8490052df2293922c2086c82f5ae2570011c107b8aa8e08c07ef10234e047ab30c1c204e9b50934d3d00f904c2d11c1b8d17422c71eb89b8f342bdc83049320aa20592438911839b08e447b6854ac1250b5866ae5c2061cc7c908ca15047c40cf1a15e2695822a8164236470521f8684fc0c94688514a0250474104a0b25692112c013d892b4810c00c1c60a901f4d18e0e20a30fb251810368c1c61aa66f44c60591bb233ae7542b3ed3049750aa2d20054ec54829aa276f124256823852dc4caeed620dc8bf6ba6e303168880440c983da519f1c206da93039179d24e67c052d33cb084a51082034e7b0d0510b41a17c5864c4f61448a5cd4630b108eee5570b00c1857170e48d2841a0b55107077f70f38ee61261b59beff5cf2021171204e8b20b36f7c10cc170051c07b004ac3b0c92a51aba3822373e0d1b095e0cf5973462860cd8b2c4290cdada0438d4ae156c0d67a1718964012cc71021401e2071093c477b0a30f8a3124ab01828f3cc1650a3ff6dec910924604fc5b8b54d2c616b850c608107602431a79bc08d0437bf1930e08477abb08d10516bcbdd3ceb8f31ed5e5e990d47612438377c518e1ff8fcb9e558c3d0d54e145b230501f583919f092a35463044b4ad474d7b50dc0ebd40ca1052af824c200f87340b1e035ee6859b0cef0e86c52abe1d508a467b32d59024ca0a20fdad9f7ba7ed33f9ffc18e1471ad0d88e6e6e00e8c1043f8832df70820a85e0a787aef4b87c159e713c8d003e0b4c022d096084042e11fa87545584ad0e3301020e016f7851e00fbd59681aa2d6068bdce400b632c297734f5a7c399826180ba501f1de040410ae10ac71072b50c562c2995cc140810ac16092f4979994076e9ee2bd90dc658094910050c9b510a047ee74f34a0df0e04608305b02a7d28614b81647b70db4fd0c81630285413706dde15196b5984feef44cb5ed0e8a7bdb1210c8d7bfbff0486a283850e40fa3b410a14aef78a2532a19371f0c03db0a04b1a30d68ab73cd1e2a3525e662ed4e2b45c9e1dc8664baca1bfd211d0860fbe7388f2f1dd8c6c6610aef8e2e916c0769b0ca979d93866f606ce58e380ec37eb00b200efd5a0c104d760a8e6474ab2dfc07d83380a7c018ee92366b0a70aa351252ee38fd352910e8b766dd2d3f6b44428640c870c30461328118d2ba21da32f30519117ed4339e1d142a0d00e0610a1071ab1758107414a06e8c23512dde40d14a994016e593c0c70eef59fbf75e82f02090e5e03f8e6ff012f78e6f9169e058d00c9b508e9be78f33b50f33f3be70143ff360c0040042dbd28e78e2b5c8138a0094b61811a8e04680eb87bb43a7b840c400604e3e7b9928281301dbc2b083243803828308a6b38835a512c08dd1b10800d70b14530e10869d1ce288e35825426211d2fd02b0c532c332c2cb9f8230f205802e84b85c38389789200f36182000828ef202003fbbcb3b8af3cf3d18e70728c18f03d2cf7824b5e21db50043ce93304404b5050c5a360cb9b704b2880cd209ab5c0ac3a28a086106224f17e3f3cf3404c04414c14424c24434c34444c44454c54464c64474c74484c84494c944a4ca44b4cb44c4cc44d4cd44e4ce44f4cf4405c05415c15425c25435c35445c45455c55465c65475c75485c85495c954a5ca54b5cb54c5cc54d5cd54e5ce54f5cf5406c06416c16426c26436c36446c46456c56466c66476c76486c86496c964a6ca64b6cb64c6c264048d64e6ce6ce6cc6407c07c554f6427c27427417447c47cc4437467c674f6457487c87c444774a7ca7cd64974c7cc7caa1b74e7ca74d7cf7ef40849b8e7c184f7c08438c384f80a74340678b40008b4067034028c284484a8c384774730050000d8cd8400005073098477ca84194d74a74738684e84e8cb48f8409c67c19479c47ca7cc8449449405069c09c794c9cb6ca7434899ce9c884b9467cc941a4964b74678e9c9946700ac69c1a46ac564e7c39c3acd8cb405ac5ac6a4ba426ce7c8ac994aacaacba4face5c1848a4dac9a4eac0acfac3bcc542843a4da4d8c4ac2b43b44bc8b4954984e946b4008f9c7b43749bcdbc75409499c8aca947749100508acb40050910284eb45c455469439c8a459477c0488ac0484cc5c4bc4254b94c8ce94f8c6747cc1bc594b7cbc41d4054aac58c68c784cb4ef6741b4dac18c1d47dcd4ccb4b749c4bb4d84acc67cb402b40487dcdd4b4c8dca74910ad4e844c4674d8cf64edc3e4844fd4a7cfbc0ec0c437c2e4e644e49ec64ce6ca206849a4678a288dc5d4bbccd427c5b47b4ddc9ec1fc34ce6cd688acd68cbc0e44942ecd843e42f48fc044e6c9dc9cc7bc5f4e8c6f48ecb7c8f4ef4f3cd64af4da4bd4aacbf47fc7ec20ddfcefc40d3f00480785fc070ea4205df4274cfc8e4505b0d0e0040205ea46e4ad4908cf40087fcb05115db860dbf4f40aa40ecbfc1ec274a0540d11d71d3b0005ad41050a491d00d67c6151f481dd1d7a880501580d0e477cc15e152252a0f1d2b4738ee40d430590d22572d09832d7b4bef1dd84a1df0d01d725c2d48882d7bc1c4a9c51512d30dc25135588d255e428c61d13d43538880da25335e7443553d43520d7057355bc6b471d83dc25d0da35984dfcc35935705e3de3df1df3553d0ec63514da74cd4c3d245c25ee449444d445e7c64d835e05e8c0f4945984a4d835bec2c4900decc4509cd4dc35ea4f4804874db4804831d7bc15df35b94940205940aac65d24509c74dee40a4a5d64528cb55ad4fec6d4d5dd5dca4f1d30506d065165b7ce55c5dacc365a4de7456d7c4d4d66d655e7485dbf495536d965a6de7435d9cc555665d65d5d05d77c075d6d17d27547df7844d4756753805ec67587d4805ac875a7d48c98ca75c7dc75d7dd7925e7de75f7df7508d08518d18528d28538d38548d48558d58568d68578d78588d88598d985a8d84c08000b3
158EOL
159$img{redball}=<<'EOL';
160749464839316020002007e0000dcf6572eb90a9e1b4bae8babbe9bdbbe9bcb9e3b6b6e7aaa0e39799da7f72df5567cf465bdd829fe9cbc2f4d6d2f3d5d1ffc1d0fbcdcfe5c8cdefb2c9e2b5b7ebafa6e4a8a3ed91a0e49995dc6179c94151f0d2d5fdded6fedfd5fadcd3f6d8d2f1d3dee4c6ccedb0cbe6b9b8efa2b6e7aba4e0a4a2e89c90e1959ed98d81dd5369da8e85fddfd6f1e2e7f5e6e8f6e7e5fcded0f8cacde1c3c7eaada5e2a6a3eb9e91e3979edb8f8cd38885da6f67c24a4adb8f88f8e9eafcedeafeefececbebae4b7b8ecafa3ec90a1e4989fdc819dd4898adc7185db6177c1484bc2767bf3f4fcf6f7f3f5d7d1fdcfcae5b8b8eda0b6e5a9a4ed91a1e5999fdd819dd58a8bdd7288d57a73d26760c3494ffffff1fec0dfe6c8cdeeb0cae6b9b8eea1b6e6a9a4ee91a1e59a9fdd8296dd637ec25851e69a96dd6274d56b69ce364beabcb8d47a76dc6274d46a6fc25857d87d7adb7088d37876db6173d36961db5168ca3141e79b9cd1868ad97e77d17773d26861da506ac24944e1a5afde829dd68b8bdf7489d77c77df6575d86d63d06660d85e5cc84f46e6aaaceabdb2e99d91e29692de5460d65c5dcb4256e8aba7e9acafde839dd78c8cd08589d97e75da6073d2696fc35a5ccb4254e2a6a5e3a7a2e79b9eda8e87de6474d76d62df566ec0575bc84f40e2969fdc8099d87d72dc526fc55b5dcd445ac44b4bd1868ada7f78d37974d66c60d85f5ec1585dca4159ce3545db6077df6475d86e6fc45b5bc64d47c83f3cc15859d57b77d07574d36962dd5360d65d5ec0565cc94055c53c3bc44c48ca3241d95f5fc3595dcd435cc64d4ac04746c43c3cc74e4ac14947c73f33ca405fbf3648c54b44d86e66ca3248c34a42dd5468c93046ce344dcc4357c63e38ce3541dc5269c14847c83046cd3541c24949cd354bc54d4dcb415bc74e48cb3342c44b41cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab2312ef4137474696f60457e63756365727964797e2f6277600129f4010a000ff00c200000000020002000080ef00ff90c1840b0a1c388031a2c58801040010308041030700142050b081a1460d0c1c30801142c482041a2858b08123860d82073078e0c1c3c700111248881142a48983182258a068b2854b071f2c54b081f1024c09142760d8a163e60e8c1a321ee0f0d2874f0f1d3874b0f0f0a6ef00214c28091244a88193284e062970c1c54f052b4494f071c1894319022c9c3182154ac41a255cac51c26034c78e0f2c7c29c2b4c7cb8e0f14bc61e2d5cbc7103164c016b2368c41c23d4894cd9b57fe6eddbd7ff60e1c58dcc9143403d44870855b275fa065c2953b865daa953c6adc04732326048f0036861d3a947963d7a1517cb183174ecc1a320be888011104efc70f0f236ecca97337eece967ee0e9c1974fce118c7a0c40901102c3062f189c7c093259472581d78f1f70021880238012588046800178c40124c011431a5431114c012c4078001e5c106202298845648a12b922b80322053242001508802348021c61214802388050001428324380125c3209442290e139052374526980479832e505032410f3880c5880f341032050e583289441990a0a90e064851b9072d9012e9c7220d0143c105109041001e4471e40014109051c1043441720821a051f788244ac13a0925a89220d92248906149033401f4871f44013349061890244620a011e74428a4a2668a2a0ca2ca4b2ea804fa84188c50620d061041f5041ef610d062c508884182482e78d1f68510b4c297cc12b4923b0d2205d2f842216c9053801150811580153c9016422f886245442f68d27b4e08b4e2abce2cbce1dbc0465cd0d70a063c012548125c01630a0d7cd0090e0f70a265cd2390b1a8012d6032ebcf240972838f192cd044c4126c4144cd0928f183442648829a0c2930b1a00031c8033c0135c41427cf1670e05405142711838d1f781129851878911b0e2a8003594926cc138c8149ccb277cb164451e3b11f6cd1088a187c62398a2974e2484035a412b70d1acc14bc033078a165c5da60c18740266c42c98c1a0cc1ab4b12c813b7cf2dc424ecc33b689136891b64c19380276052d9c82ba8c2bb0c4323cc130d443c094376c0ec68c197c02a8cc148092ca492cb8f24cc43c2df34d0325dc82378e148c22598725a4b23b8537d06339f049d863bd0735a492694737c8734bc735afce4b7de4050400b3
161EOL
162$img{yellowball}=<<'EOL';
163749464839316020002007e0000cccbf61e4da98eed1b9e2e8bae0e9bae1e9b8efd3b5ead6afd1d298d7c971ddbe56c1bf4adccd8ee8e9c1fce4d1fce2d0faefcfe8eacee6e5cce4efb6ecdba5ead4a2e6dd9fd2d494d1cb68c2b944f1fdd5f2fed4ffe9d2fde5d1fbe0dde6e4cbe3ecbae1e5b7eddea3e7d0a1e4d89fd1d09dd0d880dcbd58dac984f0fdd5f1f0e6f3f5e7f4f6e4ffebdfe8e8cce6e1c6ebd9a4e8d1a2e7db90e3d39ddeca8bdbc284d4c966cea149dbca87f4f8e9f7fce9f7feebe4ecb9e0e4b7eddca2e5db90e2d39edfcb8cdcc389d9cc76cfa14accb17af8f3fbfaf6f0faedc7ecdca5e9d4a3e6dc90e3d59ed0dd8cddc58adacd77d5c472d1c16fb9a24ffffffee7e5cce5edb9e0e6b5ebd6a3e8de95d2cc6dc7b253dfb468cfad3ae2e9b7d6c475d3cc6ec8b156d5c779d8ca77d5c275d2ca62dfb360dbbb57ceaa30e3d79bdbc089d8c876d4c172deb160dbb959c1b24adacf78d7c776d4cf64d3c762debf5fcab85bc4b84be2eab0e2d19fcab65cc5bb45ead8acddc784d1c96ec8b35bc4ba43e8d2a4e9d3a1e4d696d3cd63d0c66dc7b05ac3b74fd2d291dcbc5ec9b55cc6bd49c1b44adac18cc5b944d1c76ac2b546cda73bc5b058d7c573dfb264cba53ac2b34cc9bd4bc4b649c1b045cba43bc3b642cca94eb8af37c3b443d0c865cdaa37cfa247cea835c0be36cca537cfae38c0b145cdac30c9a14cc8bb41cba441cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab2312ef4137474696f60457e63756365727964797e2f6277600129f4010a000ff00c200000000020002000080ef00ff90c1840b0a1c388031a2c58801040010308041030700142050b081a1460d0c1c30801142c48202082450b07103460d82012868d0a183470f011e30880122e0c802152c4c906882258a851c2658a861d1028b87142164c09133864d0b173212e0e0a2278e8d1a3278a0e0f0a62f8e1e3a2cf0021448c01c044e061970a1658e03274c88e851a1a30219002a742152b48943172f40a4419260f3478d0c267c199274670b8d0a79a451b222ea0611c481a461d25099029e0177e6ddbb977f6fdfb187071ec2b58b01ce211e1065dac5db2851b46dc2a55be5ebc6103303ccb07101a34b81a54f862d5ad4f964da1266c0992366ec8044302e3440f0d183efcbc8933b6edcc9b3b76a153b6c60b963e640e8820314244080f0a38eff8127469c39c9db1074c127cc1474d120d10d38d131c70e244084448118b0f1c40674f08e19077845348710b920874e1209e1224f050080f2c702105121c70f208050068e4df028de196420b60f1c6891d78f120df10388020480500f002451020f0504802088003002b44025207805802388204701258804044c070050246f0d38512663941c1013c214281214831206e856c1288422a8804b8cf032450700c0e342122421e30c07045032cf0180b9e44a15d56175669c88c6ff060c409061c8013450a4c51a445013c8061090c4490d6a2a054c1d8ce8d7422e8c3220142d4cd1ef39ac0f3c2185c21f38c00aed1d40d098a81194c163842780e1484d1e6c42301414343152cc0040310d20133490bbee153cb12649ac7c618528197052add04484d0e489043401d44ab140d062831534a1340c13600bcd6b1d745269c528941456cb1964d02483120b01feeb13442005ca195432298206f62299c52ca614a9060a688134c31a1f01268a107871b6802c7c02c6c12474aa6ce91b9c14c947236871054cce5c81b64c195c8c56820660e106452998b17687290d7278c7195c1df5091638c1b50b1a089cd7012974eb0a482c05e1b546db5491c6cc1a33d188012984d149c522a0b4ffc829789178891d60d18744d98032e8092f849286f046a05171e8c9298422e741279c91f80a297f1e8872e4050400b3
164EOL
165$img{greenball}=<<'EOL';
166749464839316020002007e0000574c95699de76afd29aa0e99ea1ea9ca1ea97afd49e9cd98f87d67d71d0696ac74e5dbc3c82d378b4e9a0c7e2beb7e0bcb6eda9b5eaa6b5e4a0b3ee92aedd8d9dd6879adf7197d8727cc35b5eb936caebb6cbeab5cae7b1c8e3bdb7eea4b4e3afa2ed99a1e694aedf899ad38499dc7e87d47685de6869c64880df68caebb9caedbdcbe2cdcde2c7cae9b7b6e7a0b3e0a1addc8a9bd4849adf7098d77a85d07483d86f6dc25856b73980d17fcce5c3dfe8c5deebcda2ed98a0e59a86df6584d96f71d2627dc25757b63471cc59deefcddee3dbb7ecad9cd7869adf7298d97b86d17684db6f73d26970db586bca485daa37e7e7e5b5e4ada3ec9aa0e793aedf8c9dd8869bd0837ec35067cc3e6ccd4657b43ba1ea9068cb3c7ecf5e72d16870d9517ec15d6ccb4669c44455b23398db7283d66d72df577fc85b6bca4569c2485cb53183d46c71de557fc65d6dc05a6bc84b53c63e9dd88da2eb9f88d57369c04b54c730acdb81aedb8784dd6168cd3b52c73b9bd48c9cd58399da747fc45f6ccf4f57ca3a50c7376ac54268cf3c55c8395db63382d7607dc0595fb63353b23e54cb3a71dc5c6ccb4151b0385eb53955c83a52c5375bb43152bf2a51c63b55bc375ca9365ab7317cc15452b33858b73354b53253b0375ab53552b5375ea93658b33854c73454b33951ba31cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab2312ef4137474696f60457e63756365727964797e2f6277600129f4010a000ff00c200000000020002000080ef00ff90c1840b0a1c388031a2c58801040010308041030700142050b081a1460d0c1c30801142c48202082450b07103460d82012868d0a183470f011e30880122e0c802152c4c906882258a851c2658a861d1028b87142164c09133864d0b173212e0e0a2278e8d1a3278a0e0f0a62f8e162d2cc0f1f308401127078c30d0b247019224447ca0d0d1c88400146f802942a46903962e4e981cf0d1630b8d1540a419d1c26342d82256a059a26500b0e62750b41c4264a30c59b47de2e5dbc7928f5dc38fa461d2407b44870855b275fa065c29d39763d27ec2c56067971e2024786134b8e1d4ab4b9e3d8a53cbc7103164cc81184604c7880e1a3078791376ef6dcb993776fc2366ec8d043964d80c1150628488001e1478bff134e8c297253fa163d68b1f64a107804174f027c40f18b01181101811118b0f1c40274f0458e442cc125101fb920474d1209d1224f050080f2c702144121c70f2080504f022cd113850081e1564207640186881978e120de17705120480500f002841020f05048020051770f1844f152c68d48f1f78209600218804334c07005022800d34f035c892088041c101302142020e3c21ff5e81680238012588046885032450700c04105045cf903c1051c80614f1e6e215684775c59952c10bdf314421428e91345074451744501381a4242152cb9b8631d6c12b36e14802298804a88213705aef23850848518485023c7a378214382ae5c22d68d0c880247002a78a1d8c04d40d0a449033cc094c3bdc690ab2e153ca1e509a1446185271578327dd04084d0b4890438f0a4c9be30d062c2153491040b1f5cfaad6a197c32094422941416ca1564d0f3c2100ff0deea104420d4c9175c12c80698ae4219caa5015214891e5001c4c5c04871660b170bf114cf1868024f212078a1364527095279c71d44bcd2f71764b175c7c16820260d1c5c323989c89424998027540d14381638b1950a1a088c9700257cdb98862c05d195c4d9548186cb1637a138002488e1e8442b90b4ff8615788128881964a147c2d42322c9422d988d30972f90220a012d5b3c1a4a0222a8cde7ffd0831410100b3
167EOL
168$img{blackball}=<<'EOL';
169749464839316020002006c0000747474545454646464848484b4b4b4d4d4d4c4c4c4a4a4a4e4e4e4f4f4f4050505151515252525353535454545555555656565757575858585949494959595a5a5a5b5b5b5c5c5c5d5d5d5e5e5e5f5f5f5060606161616444444262626363636464646666666565656868686969696a6a6a6b6b6b6c6c6c6767676e6e6e6f6f6f6070707171717272727373737474747676767777777d6d6d6575757979797a7a7a7c7c7c7d7d7d7b7b7b7f7f7f7080808181818282828383838484848585858686868787878989898d8d8d8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff12ef4137474696f60457e63756365727964797e2f6277600129f4010a000f700c200000000020002000070ef08f72838485868788898a8b8880132b2e219c2722271d040c868f143636353431333e2b292724212118999f753a3ea9373830af2d2a272523202e1c0c8c1a3b3c3d3c3b30bf9033a92627af1b1113098c193b3e3f304f3e34c633bc25abcb181ec780163a3c3f3142414f3c3a3735313f2cd6a12f1c19161e020681373a3d304246880102d3addb3a56b699d3b0210141a0153af99347ae8d9b3872f41ed390f00001271c94a153b68d27863c8dd8ed7368f0c1a02b00386444961c68513a17c849235981a244870b04fdf141f2260d0c173278b2d10b461cba57b27970d0718244070b06280a21e26681da163e6885f40a4419a975f2345580d0618aa31efc2e5875a123b6c7a2b1fc61e211cc030bc60a0c080291a2858b87103268265c03e58b061a229924aa651b6205562258a851d2e0fb8fce8b5ca88cac05088ebc09de2040aa2489831a9750b061d266f8e25ac640f5b755f72305050e0802d042a4c908d924372f257b840a8dda1a7a405dcad3ef980126441f7d7cf8b982142644883dc12ab50a001c270f0028a0c70119d948cf9f1e340fda76edae38fdca724781461c70f10801241860e8720270b1460e79e7d612060c102490280c60c18702066820a70a064771450e0e209041040c00ff112f0460a1c6061270a0e60a103871c973dd30d6d88522b758c4011c508106091409f3e5033250214409e130602229831800a3ee80145061c49352886422963e20a0020c4a3998c00c084026a8911069e0430a4620016e83162260c30072c9766b5a527940c1030c39c800060c20a4e20a5aa9422e9104b9ba80000c106041042698e4a57ba44a29e4aa8402000b3
170EOL
171$img{msg}=<<'EOL';
172749464839316410041005a0000000000ffffffcfcfcf6f6f6f0f0f0fdfdfdf7f7f7faeaeae4e4e4eefefef1f1f1fbebebeededed8d8d8d8f8f8f2f2f2fcecece5e5e5efdfdfd9d9d9d2d2d2dcccccc9f9f9f3f3f3f6e6e6e0e0e0e3d3d3ddcdcdc6c6c6ccbcbcbafafafdedede7e7e7eadadad4d4d4d7c7c7cdbdbdbababab9999994f4f4feeeeee1e1e1ebdbdbdececec8c8c8cbbbbbbbfbfbf5f5f5f8e8e8e2e2e2e5d5d5dfcfcfc9e9e9ecdcdcd6d6d6d9c9c9cdddddd0d0d0dacacacffffffffffffffffffffffffffffff12ef4137474696f60457e63756365727964797e2f6277600129f4010a000f300c2000000004100410000609a0cf907834000888c4a010180c159a466350f4861b9101c080558a43050301e088e22fb903826180643ccb4c60c1f08444231a45ccfd085e201819131a1b1c1d155d7e171f102911222b132425264b462d4e172820292a222b2c252d289f4c462e2f2820313a22333c2d2d189e417106262431353633373d13b856a2762836393a3d1424bd43c4c8b0d275bf3d7cc856dec7b2d7d2c6b6dbd4b3cfdbdad553e4e7b4464becede69f31400b3
173EOL
174$img{sair}=<<'EOL';
175749464839316410041005a000093590253c8d163d8e12348b1f2a7a1b21781e1f4013358c1f2c7a1c22781829661420641127521e1e40103d7a1c2378192a661521641228521c194f022b531a164e071d3c04143b0545b624153b011d29024da42e04270e33a22d04270a0b150b3b912a0c150703130e29791b0d15070414040b0202328b1a2e671b0e16080514040c020b20771727651b0e15042f541026521d1c4012113a0f08280b0f160a154e061b3c03113a0f09280c0026080714000000000000000000000000000000012ef4137474696f60457e63756365727964797e2f6277600129f4010a000f300c200000000410041000060660cf90784c2a1f88c4a2796404089641c08050304587044241b06430ae87042221b247241163a275265c2712260a91d017305d0788d16a6c3f14402c4e112225432b44252625472829492a2b274c2d274e2c894f203132423334339c45363738393a3d6bad61400b3
176EOL
177$img{forum}=<<'EOL';
178749464839316410041003e0000ffffff000000efefef4c4c4cdfdfdf151515dbabdbffafff0000ffb70000ff0000b797b70000b7ffffffffffffffffff12ef4137474696f60457e63756365727964797e2f6277600129f4010a000f000c200000000410041000040370f9c94bad702beb55bfdc160404699582e7027a5914624979a0f0e2b0b0441e6f4d9f23c8a7739c9e1f20c1882b90042104462060303f74d3c100653c1ca54a404bbd8a7d759ce2baf5039e25a5e7fb161763b7e73cdb784490cc110a090d7e787b01890a8a887c0e8820580c060c08069c01100b3
179EOL
180$img{home}=<<'EOL';
181749464839316410041006c0000000000acacac989898cececededede8e8e8e4e4e4e9e9e9e0e0e0ecdcdcdeeeeee5e5e5e1e1e1e8d8d8d4d4d4daeaeae6e6e6edddddd0d0d0dbcbcbcfefefe2e2e2e9d9d9d5d5d5dcccccc8c8c8c3c3c3cbebebe7e7e7eedededadadad1d1d1d4c4c4cfbfbfbbbbbbb0f0f0f3e3e3e6d6d6ddcdcdc9c9c9c0c0c0c7b7b7bfdfdfdbdbdbd5c5c5ccbcbcb8b8b8b3b3b3b7d7d7d9b9b9b2b2b2bdbdbdb4b4b4bfafafa3d3d3d0b0b0bcacacafcfcfc7f7f7f5b5b5b1b1b1b8a8a8adadada4a4a4a9a9a9a5a5a5a0a0a0a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012ef4137474696f60457e63756365727964797e2f6277600129f4010a000f700c2000000004100410000708c08f7283848586878f7000038a8b88828001010e819e88859599839f859203089b978d9405060591a583a706080908968d9a070b0c090d0e099481bf001c0117b21319ba9002041cb51116171218191a199d941b1c151d1e171f1ec021222895c3230c1427d52f1627202822292d809305042a2b2d800c282d2e2f269985a80b203004c0915c668b0a1538f1006590068d000d0489088143e60e0585be65e000a3a141bd1c3074f058fbc14038821978f8e1f341e2b66914021410e30840112a0be9ecd9f8a7e0a0400b3
182EOL
183$img{equipa}=<<'EOL';
184749464839316410041002c0000000000dbabdbffafff0000ff0000b7ffffffffffffffffff12ef4137474696f60457e63756365727964797e2f6277600129f401046007000c2000000004100410000300687abcdef0d18941c9a4b1e977bb02409d10a8c5330836a2c8b0016bc1cae9c4932e6fb51fe230001168a80a068407c0801818351bc6e318e9d858a89e46b1abb67595bb2be779856862bbed24936fea8d3839b8242e5ae94413d9308ee7a709000b3
185EOL
186$img{conta}=<<'EOL';
187749464839316410041003e0000656565750a30867a3074893097fa20a86b20b9eb10ba5c10cbcc10dc4d00edbd00fe2e0074994074994074994074994012ef4137474696f60457e63756365727964797e2f6277600129f40104600f000c200000000410041000040a70f9c94100a83b5014ceb9d40c03474416c1808a196d961290b59bf008e50824b85ae9205f423ae8e453ca89a01b958a27a49c87697215a905c24198595f63dd67f0684a8c2c5409b0403b8ab616b743515fb4018e10c9442b50f30a7c32260c4c11881b3b5f1c6788898b7a658400855f4f10087b1f551b9911100b3
188EOL
189$img{jog}=<<'EOL';
190749464839316410041002c0000000000dbabdbffafff0000ff37573700003774994074994012ef4137474696f60457e63756365727964797e2f6277600129f401046007000c200000000410041000030e487abcdef032894964553bccc1cbecd70401083933196a7f50280568fd04a0d1a3ab0ba51e5fe13bc767b3d4be5abe14648c7927941ed561924216a78cdea0cd2c54b4aea77930e608b384797190000b3
191EOL
192$img{bg}=<<'EOL';
193749464839316410041003e0000935902651902c4290237e802243902d7d80219b81296f80268c802934902f50902a3490264390200000000000000000012ef4137474696f60457e63756365727964797e2f6277600c20000000041004100004066018c94badb83bedc17802c51a51c0400241320581385702490640211e654f15512b493ac0c0b29c0d6080e40160bc0f59c7526268665e9049e4a5e43822b089a4e04cba1e41da0101c3a8238b8901a0860820a823cf4da8f40eb31703030c0d168788898711100b3
194EOL
195$img{logo}=<<'EOL';
196749464839316091005007e0000ffffffffffccffff99ffff66ffff33ffff00ffccffffccccffcc99ffcc66ffcc33ffcc00ff99ffff99ccff9999ff9966ff9933ff9900ff66ffff66ccff6699ff6666ff6633ff6600ff33ffff33ccff3399ff3366ff3333ff3300ff00ffff00ccff0099ff0066ff0033ff0000ccffffccffccccff99ccff66ccff33ccff00ccccffcccccccccc99cccc66cccc33cccc00cc99ffcc99cccc9999cc9966cc9933cc9900cc66ffcc66cccc6699cc6666cc6633cc6600cc33ffcc33cccc3399cc3366cc3333cc3300cc00ffcc00cccc0099cc0066cc0033cc000099ffff99ffcc99ff9999ff6699ff3399ff0099ccff99cccc99cc9999cc6699cc3399cc009999ff9999cc9999999999669999339999009966ff9966cc9966999966669966339966009933ff9933cc9933999933669933339933009900ff9900cc99009999006699003399000066ffff66ffcc66ff9966ff6666ff3366ff0066ccff66cccc66cc9966cc6666cc3366cc006699ff6699cc6699996699666699336699006666ff6666cc6666996666666666336666006633ff6633cc6633996633666633336633006600ff6600cc66009966006666003366000033ffff33ffcc33ff9933ff6633ff3333ff0033ccff33cccc33cc9933cc6633cc3333cc003399ff3399cc3399993399663399333399003366ff3366cc3366993366663366333366003333ff3333cc3333993333663333333333003300ff3300cc33009933006633003333000000ffff00ffcc00ff9900ff6600ff3300ff0000ccff00cccc00cc9900cc6600cc3300cc000099ff0099cc0099990099660099330099000066ff0066cc0066990066660066330066000033ff0033cc0033990033660033330033000000ff0000cc000099000066000033000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff12ffb0e45445353414055423e203301000000012ef4137474696f60457e63756365727964797e2f6277600129f4010a000ff00c200000000091005000080ef0059d2318ac80e04385070e1458909022c78c012a3c884172a5c5871b126cd8a1b3a44e8f1d365409325466c0982b46ac39a2b52bc794216a9c894376adc595317adc564c4021b18f35951b283497af40a3078a05f974595055a54b72f44ab479a1d9ae4392156a85f9e6dba14dba559a165be8d6a263a2a53ba6bb2b5ea56ba6bd8b051e25dab06fee752ba7fcab59b673b20ecb281f2fd2cb77de0e3c96307362cf891fb58c395277468891166edca9b337efce93438e1d2ab439e3d6a353ae5daab53be7dea363ce9d2bb63d60d5c4befcddb478ee63a34d7f4de91c3b2fe2efb98f2d4edbd830f5e3cb93374e1d9af178e7d587677eac5bf37fedd9befb4fae8dfbb87be6e7a79f0fae1cf8fdedefcfaf7f9e9cbb74fcedebcfbf3f1f3dfcf25514a3d08e25e450ed4702182392860e2890e38e0648d0e4880a4851258c0e58a166841975a5d78655885498840d88626988228872aa892298c2eb8e26c8b2ac8d2ec8636d8832c873ae8932d8c3ef8e3609b3a09d3e09646198420933265f7954126057555585d39a0508a4d49322496562414159c5949d5669552a8d497915e5916214a529985aa936a95d62557627970989f52a957ab9772d9f59063769967ef917af9b520aa7a0a96ac958e0ab62c99821ac6e3ad8289976e9805e6e1e6801268b9a6a616680a67a1ae7a2a69a4ae9ac92aae96aa93d8855e14efa9978e5545a51da361655c1ea7beda3b6359bacaabadafbe78fb5371cafa745fa7caea3c5da8ca0b9ca3bbc20bac65b4ce4b2d25b9de6bcb27b3c67b6ca5b0ee7b4e64b1ea7b6e69bea637f01f681141784026a40218c123fe122849218802788eb284025a0224fa921f2dbcaeaae9eb405c8a7033cd0da0b283c21b9ad035c80f4caaea4752d905a145ce2318c5322f8c188515585162b51234ac2885332fbc008e697d57db69708527841f5ee6faf1b23ca4ec49d57fc997761570d9dce51371d502c28377373b6c54b4694d089a52c51de4f5d83b0683f4d4ba27cbe1d5c9dc57d6db374733f371ea8dc497774b9d15aeae13550158cf2bc05650864defa0650b2f2b5179534d956481d0ec151e4a9b965c5391b5cc03007d85188b446870e48b0e99d5ea9f1e8935e9937eb9b5e0af8e2a79e59f9e995798950837b3db2cbc7dc31b957c4050067ffca5ef80ce9be2eeea575a659a0223980de5bbb69b6c34b5cfeabc8fd2b3feb2afe7c7a82df2f5cb8b1d72f3db6f8d6feadb5f8c67f9df4f6ba1f891391ba230bbc0e717c0be2e7d0c978aede9e6cc9fcefa214528fd1fb49911deb92af928644801bb551e37c7205110b35004909001246f3d49aee35b04b0530d04d041b8e92e2bc08d10ee250190b4fd2266eb6849026697bb6927812e6b510d56b2619f9000661323f852bc052c951041ca08240a1df496ef14951490ad6efb1f8ddea1d4b6e8da6c3bb2026e9ea668167989ec688926da96c63791ad69ca8f618227ccf292c3c0313a885473151f13c5a01164a81d1bccc05c3857123dab602013721d17f0cfbb60ff85118851454248401ebd119f73b804c2c0f718486cbccf4799a2c51622d738dd53af8029a0e23650188d3ee1bf8da368062f560582942ee636b925292f496ac452a237563465211b880b3212b9c125c916d35650b7495a232000f36584e4a7301bdd8c00757aa24b2446b78899a1f7274c19dfba41650f3213650ffa54e05af6eb4b24c0401a8429d011a6c4221ce1989201c5a8c851e24b4d230a097c372dbc09079d357dcc8d71dfc51303ffef1411a13e373cfb4d72d41549990dc96261b7e892b8b517fc49a254fbbf12bc38d4921ad130974c7e1afe00dd465090449ac08fd42bc7501bbdc2e9755984a42f562802849206730911e24d3a7d0b6400e324c0918331d2501f8602eb9201004b3f4ac83ec4407d8821b4634228809b0620742f04a5eb409ac015a69989a54d7aad44aa5113a2162c78018dd2ce05d09cd51dc001d8191bf2a4659008bc4468739993540142b812340ea22b040b0b120b32c5b3591cec885207507cc37a9be72558191b2037a51f82a334420966e7050a02a14db98a8022006a0919392686bf405a72f264a632a3b9ae3a4e8389e395618689d9ce0d8a717b95a35792be34eff183f72e7dcc89354629be4a08e57323b8a14609775019fcc99a7b0a4e5df9dcc30c5322637418416789c1182cbca40dc2af5e156a92a66682b1a283c3526643b5a21a05374d6cecce8acbe642f296ecbbe55f6966941ba58674ea69e2dc0ce84a34d480621d6d390cae111359a184b376a75966e0191b592896e69587cd4a28ce56188d38d09944c8c3e1699409b8ba97d7203d3ce44a99138cf56aa04f2c09086513d0a08a38a4c90248ae40d8831bc452fb458bf6d0ece8cb18dd107e67818c9d553303d346853aac39e033423c57d880847020bbd82be06730d70fbc66abe2929369a2dec51c6ca18074ba433ba0a5ddb8a05431ad4b586eb6a24cd4efd71c9b168a1a9fccb6ee95a7ddc6e2cf92ba5911dd0384798c018d53d2cc6582b602eb4ac0ff605bcb55ebfa24c1bc8c580f5a99f36ca438922dc4f03a67eaf2390b2487b7eccf1a6b8109ef0ffd4ccb2cd90674d85a122abba37393a95c4c94ad14077e6229f995f4e26db1b98a3a103abe3c4d81689b6743865750b3650f19e5ffad712b15a37b7ea8c25a82ad2b65ad98b35fdbc2f7ca4680c4fa140628438d85dccd3ccea921a63a45ada0058810ab360058595514609e639e8c894dc461020f85564ec4f35868e5e1bf032bb1ee5d29d226b46611ea855b4a1be99a62b501af353232e8fa1b21a629263db8f8ba014ca2a99175a7ffd8e6e9628ce1ef06713be03be88a651e43e63950569fa238ea22ba28ca13203fb604b70268e36ffbce5fecc71eb09d30b14335a6e23fbadba932d8a90ebade49fdc803db2772626d5e68d8263572a49a993bad4db85b07cb40e2dbdc188aeb591550bb5a49a2e55983854021308824a38b5e5f634813239627fbccf84178a14ab824288529e47d409b274b71322e735beac799244b895138a62cf2eb5b273fe2a92d760fc4550565d9d38346f8ac4c398da457cd5584ad7de1c94a8100a1737f94c2f5978326c6b71653f14325fb50bbf1715e8b5eda973e92df2b34c146bdc97ddec9b1b77f9a3da5dcda57a27ecbe45ffc9fa90edbec3faee27ccfee25f7aa01fe0db5c3eff08f1f5be55b35b1d34d591bfde85dd1bd12ad630ea99eb53a77ea6f36a607c5a99e89f0533fce53dcbadfa366815723abc8633a95694a33445ba52c6743b14d070e28e7dc5973e075a60772b59438833181813e5d61ca50349c7257645e910b3126ba6008877651ba7818fb6c20be3f27f23d50ef3a713c15b7d55f23df6ab7af6b015e6c75d06363097c97a515372464a1c57a468a6ba35385a6d66e91ba6418593ee73c78478659a32a42766261532f54487918e5b24cd54f4763d310153b4c24021e55827025ec6223113f67cc31835b7e51c250c61257d61646f7825141568bc5707c07d11c86b61995387157c14ac1258197b58558e87af1f01df7ef444a38da3f78d978e73d31772572182725a5067c760572e7587202cf5dc3f23704df6a722d57d6ac07382c64542672775343742563c39a6ba8394522e14265514e13244d01537f76221d13992115d45e05182512682538183ed5f745214c8ea1314a31bc32752043b7d72076708a619674f5891dc5301dc47655538a6868a27925bb8511a27df3ac1d68b67ea8ce2481ea81963c5423e278e7b866503222876c3976e47e065d21927c72e2416248571b440f5807cc31e5964a57152cf77348e1544248c66796576e456d1e09f57928118d315f7a27216057461dc42b4ef5f33e071e2035180f31d76b84383438c72bb61b7fb5f23696009ad72c35b5a28defb5a078e3866314098758748393ac79d76c78d73984318587f6c39398da8878ec73e51f5d331a1d11b336d6db5f39901249be87d0da0108d05b29851035e75ed5a91dc4335822af7bb24f7172d137f75511000b31008045053a8d19a41ad54a5a72c212b88c2bc4a821e3bb8818bb3326c88288865a79cd30a7a09265607024e95a54b88a39ea2c143486017a8ba5408e12a272b40c33221a8668801ef5180556d42016436fd6891369358929c01dc4080ad89e5869499139c655f8fa2f24a390a39f5c15446d39a899a1b481a3131b13c992812b63928b9687d94d64727682163e774b35415c89640c52d7034974b99034a27f599d6741a85bf7e493c340ef9dc4481643f67353306383ee7ca0ed8851e85533488508d53af1591a447a63e38f15d5692a571f94795d59f49f3253957cb8658333c55ec2a079b6ea42491e89b58a65a69075527444e4608ac0828575183a85788c51420434a74424ba60b3706cb75342493011b79915202b03230d0e28611a175733a6a21409a476b93e72317471b1f2a1b9ca66c74043b8b55f74647db86d76d8743c66ca5243c17716c38d225b9b86323066d933417b56b7709ec68f73216732b0c35ba3de4e4a2967774431526690221000d9d127412e415a651035559dd963ab72687954d294925f7f130a7908c444896f9b53679fc8be2489497258918f66fb6b18f080b2421799ef0a4436639e489016250838186e4eb4358f5a01aa71100ba019a482a01bd632879a5c6939520294420fa53a8685cc5046193721d9a377211fb24869f9cb9f21e193329b9976dc5076cb8a133b47c84c9fa9ec9ee8b264f8c0853a607322bd6016406ca3b89b09102194ca01a44155759e48815624e7123eb4c35c73e73b856725517b5ed40413ca394335314341a20f35459a56da32c4ee49e6b34123180b152541875c681a08a448d2ab050c45c9711b53b381737810d23e7afa714c3a2d20cae68cc8095fc7f44d28ee34586d7941c73ce6ad4b34ce62305508772c583a9ba501100567ac69c6f85848572891650d37717c346c8922723ff2550944bc0bef1bde6f40650c20723823d22201de6923c73923ac4111901f40fe4880af2523358b9632b523050f59319ba5d78609eaa1899aaaf4398d04ea9dfa211005d72aaa3b80d21881179a15d7aa58b983a3159952895ba7c816acf11244214199669fafb66b64196090b273a316229739f5b5182835793935f4275c36fc2b49b6af572c7d29ba6593a7ae051a1c5bbf9148c38264628279db9174698f97cd2cfa1c5eb90e5e05fd78065faf48346d28a87607bc02c9be237b435e961a7d6bbb7c556d8236a0b2e91535d9397ef97088a3ff1df945be57fb360b80b9f82f3a09c975abb0bd475521c6ab9486a5545be6ae54595c45ee85c55897754f437969bdf4c8ef45393f38e7cf6376fd8c9b4493d7fbae5b024df672bbf6cb3804a8808bf58787b9378b7c7317c69f3a493539f48be9353f076fa2152c855b0c3a43a072c7019daaae9053e19466e9370c5499c8ad7e6a949d07d2ad91962ff3ab2bb3ca1a6a9fa163273e8837489737b451ddb466884117531e1ab497ca331e087d30070e531ad6249854a6980d70621c87a54220d3c53fa983c6336837d10842cb064127fd2f02128fd5265444b386265c9395ffac15f7b81c8f4ad7e083f8757933ee90c34e1bfaaeba95f717ca85774816b5764ebc2c1cbb4a6a60587cbe65307e82df995ceba9648f6e433161a3d89fd3c4400a345e53976009d5c7b6e116363e5b64ef0076bb9dab2ab81df133aa183cbe683bb85321805bd8137b114ef8f7b0b99f806c70c65870abb6fb387b88832cf874d206c3916b6758a6616cbbab4be8762cdb95911570171acd6cf22a494b96f855c91b6cb42c88b055087a2cd866a32c8e63cfbf7b563da7e190a15497f929561243a90bb76a18acb77541ccb616648ce7874c93c0eb31a4e65a09c6b7008075062308a579a381026acb0cf08ee949b0b94790f9ecc599cd13d29973b9ff956ce4c2c5bf8acbdf75fa5ba49146387930b3363a4b95836aebc6a75cf5412cd429721eadbc7016c6ca004b4f2d50b70823823ce3009e3ac326c9ea496c3acaeb80c3dcfebf77f7c4ac2e1389779e9b3eb9ef0b3396c75bb02d8a127c18b9c9fa42ebb5c56b0e234b6e24a5a9b117b1c971180da0e0d9174f2080523823050b2bba9e1cf0796bd72dc7d7b73285bee9bd336c795c0565cd49daaf8b368a97689d09f2de63f09bf83db207405ccc988de32cbe2de6cafcd4bc72d81e39ec9533ee7da3fc89917dae0d1802034f2650d50823ce60133aa95cc54d89aaa705ffb9ccc6c718c2ddf6c59f91d4543daf936cbc9c9ce2cb7b819b2112116ba9b57d5f5907514907d6abc3a661c8f8728bc69b0c5712231d06d0e0d7c64f231d51d1d408d997bb25a1c8b74a3f507da5c582f09114b79a9cdbcbd34c9ec9b9cb7b8fabc879b0244c375bfd514ac32dab91c7fb75ef7315836fbbf57c3a709b2dd1cfeb80565825bc01e733b06d004dca040314bc5054d650f40f7db20100fcabb9417c89f3cf7b45709d8e360c7fdc113ba5d926bc91afc1d877af9891cc555ccb399e5abcb72e452bc64a6a141c16c29788c1b686335bab57bd9b833763c7aa7d01d02b0dadcdcd50a7064d13008d520600f6cabc6cc80496bdb887cf9de6cc0ddd2b82177ac3c8590a2ecd6c339d2e5f8cbb811fd8088389d0900c5f7ee3566c2efeb34c32de1a5185bb9fdf3c2bc67a68361aa74a74f0d5a0503edcc5041db20f40013600520039afdbfcbdb454d9c76d7a39d647a45c69d8f8d4ec4dd7bb47cab7acec295db3cefd0a1d5cde3cf94bae9cef907ef628b2dc9db897bf938213299dbaaeac753d77b29e1efe49eda2308d700eea88726c88b92ef2e65814c60e83d92c98b37ed4d43213ed0217ca0c8a63ec3f97dbe6a366d07dcbfa586efcb81e298d4469e4cba3d7dd12719dafc6988917d5da00d087d14ba70d7d823b2b51b01334484bccd4527f416306d50cbc9a827ae064ec931af8b8fd0653e7b9800684ea7e90937c47d9f969eafad0bf4bae457ec0bdde9e39f65c5879d0c89b8936488845d994126d294d1e6c6ba0a7dddcfdc623c2008d600e742fac2d27e28b50852de0e5a41fcc84cebf47ab58c200923a66c488b4654e827abaa63cfd6665bc06529b27e1ab15628bbacc729f5507e19cef89fb6d52f2e5c0f233b00d04ed4e9d8ec5012e823b5e013100f9ad6249b54488867267a10d01ce61f3e48bb6e81826c38714e8eb1fdfc128ed0444f68748c7221b116cfce50ea3af9e3170bb67cebb018eac9e9f9b0f5a54bae1770b3c2fdadb171162ce51d08d5b869ee4dc7caf6c2a76d3cc20fdb6032cdb65df21073d8998dd3a42ddaa35d457191f3987c1092ac9dd2fe8085a82ba02f53a7ebe6d62a47f1d76fad410b30d03b06c63f29c6180a70bfef40230efefd42dd5bc5a804a30e8bcfe5c559b3efb0cbae1deb86c90c26d9631e1298f8df7ecac89d61faebafcc6d68d2173ba9fb1bb3c9bc9c1d94b88fddbbb6248294dadca0503d509ed74efd09e55ae1dd4e0cd3c67958e945b00dfabc188deceee2d4ecffc0926af5eb2bb0cf4cb19947630c55ce8c64ff5f5a5a3d46bf6f90442f9dc643b3d058776cc3f233edcad6c600334d750001c5ca85191f485ca851a22082b564ca123478ac4951388bc81a44a8617265cb8b192674b812f2a6419915229456e055e840911732a419a2d2a9cc8e216264e81132ec40971f3a84f90138a54d9f0d42b4292319e8c2ab395e350a62156f4e922dae2dd8c1f52352a04b467cf8251be5d69f0b1295d8413c6a4fac6dded48a24fadc5abcacead514184f60a1830ba0244852491497a263d285aab5976dccaa6b1f9ca8a41523e3b833464c5bd6d624ea955796cefc9c24ba26ee962d9ed47cf27332eea17b866dac4177ac42d6af0fc6e9aa9cad67bc2b63764a4c632de1dc1d07e4fcf958b3eba9bb33e469ca8ee53653bee60a34a75f471d33095cf54800658231c59f2f0ffa793738efc17fbab77ade5d7263b7a947afb8b2b3b356e097a6afdc872cdcf3aae7b3caba10b931e0eaffcfb3d89a4c8b25c69aefad23b45b1b02b6f03cb96eb7e8247be8b1a0d32f6abb60a9bb859db4faeb850b200b512086be726986c3ac9b6944b50704a94438d03c4d25bafeca5038b2da7b6dad26d2fb1d61342d14898fb7c48c321d27a84b707f3f0d7462fda8c40c60784bfebc90b345c8834f20430b84b0d52a139af2d5a235999ef56ea864694130135854eecfa380123065021c320e6dbf152390b9bc13cc0a4b24b4e3207d2cd8d4e86e3223936090cfae343fe4a225ebd1d3bbf69c82b238ae145fe1cf159bb49252553cbda83b190c6f6d27f8da5ec743f64564db2d9650ab2a1aeeeace6faebca00fa488138b3fc2d903236d245445bcc5515ac805d1d4d3e41d42375d5b055ac1317d3d1beacd5b8b42965dc4b53e434ac633df225bc47b0116d1ae5b6d4bcb5b9de298ce7b031a6bd64b1c53b53c65429e661b6ee244a49cb209deafa284604845830aeda27ed8d4edc47ebe9c7bac20cdaa258217294b5b8f8bd055d56974ccc21cd7b255aee3e57f545315d4925e6b04e731bb9b6ef43953624d0615b9cc936590f9333176035919e68dbe65c36f900ca4891d15b9e35475735ae7cd8d3be0bb60b93c89fa2d73330a9edf906eb5bbc79d8269f1d3511c477d29da9d403edbb375ad6443a5c2bbfb5b29e329f153a72cbbbc5c17860e6929e2fc554f2e26f098f9881012bc05ddca7435d24971ad8ac3572f64fa57ec69ed15f3eba0f52c97b1abfee4b3e6491bdbf25c556755d372a3e684392dddb6b71e6245aa28172c2fb6d418f437c654bbcda89b040a665e1661702910a0484941ed9d9b1bd023974eb147bd1480317fc792a91cccd983f6b9ffd3f5231ded9dccd2d6713355bf3d79974c7c20624ddcbd1dbc07e52645bde04b3a9d568ef096af3325b5c41ca868de5001758ee02b850deae419ccb7133011d8e84fc1115ef8559baad110977172af127e97f695947ece500b4c1f60e67129ddab4571126791c406febd0dfd4477a3df9ef8473fb22d7fcd7c912d4954e41885505f001d58715101c65d2a5d37488043d75beae5d6a3018fc843e25b5266d6ffa0d9482e23e2bdd01bf592b0a0cee5353bb718e4460aa6a1bbe57ef3f0afee583049b1ef0187da7354ba556a2c26592b66593ed4be8694cd95f48d81a3f75029d3a4300ea7e5326150ecb4a454b612ffeb69b3f91edea65f1306da208dbbd0afbe24d0c76dcfe57b9241ab178470be12888e583c194ab636cc227d11507e5af22ea8bac62a47bcdc6290cce5da03e25691edcbe82a64fcdd804971a79da0fa629c44df6ef766adf08ea698f331e69e13bac0d04a807abb61a4b0e73d45168c2a4264d8949ca925aef42177873422af8af304b4366ea041fb195a09f7fea625111465d238e11f037d25f5ddcb8cbc74682944064501ace7794b32198466832a8e7334933b8dd39ce7de44c091d48974f2e6dcd9c1a6a4994b681c31e139f8005ea13de683733dde6e4786bc4eae2437f31a1cded610550ef1907fb9e8283b2ac52de50d2b5d490f9ab6568cb080000129f4010a000ff00c2e0000000281005000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b7efc0a34b8e1d4ab4b9e3d8a35bae5dcab5bbe7d0b36bce9d4bb6bdebd8b37beeddcbb7bfefd0c38b0788ca401ba048cda402b26568fc6650d7512f4ebc997377edadad538e0d50d47becc75ef859518d55f5b65cdf8b4ffe1e7cfa02f5ed4f5b9f9ef8357be2efdfbf8f4a7ef53b68e517ba8777f587558e70f1f70adc7dacf79ed479c957c28e700428a0676efd67f0ad7ac957550b070eb751e58e95684f1770165765c78af9a01000042276626d718ca7d12e7af500a2c881366662a68cd118180027508780eb8036f889dc8a1a02be502750028f9b7b2ce8b2429a4a56f36d724249ded19000699525633a5382ad8252e822ee826e8929df8102b2302480e159226b9e6246566776f14944237c2a88f2aa09729933e384720a45aa07560058e46916b2002a8c1aa8026e865e3a09af72922ace9a9b2cb8a9e6a3fd4a0d148f768779e59c8e8a4a20905822279a60afe93aeaeb9ff57a7ae471528712e5961edaf89f7c524854a51c28d92c299ca4c953aca654a94be2b599381d9097ca2a1c25b291f98ae1b0227ba99c9d5a572ee9b8e6abaeeabce6bbb650400129f4010a000ff00c2d1000000371005000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b7efc0a34b8e1d4ab4b9e3d8a35bae5dcab5bbe7d0b36bce9d4bb6bdebd8b37beeddcbb7bfe99ca401ba044cda402b265e73a665cc7511f2e7c197275e2adad536ecc50d379e8c75859514df3eff5b658d78b3fdeddfbfa00f1e73f5b7f5e783479eed7dfaf6f99fdf53b64e38fa2de3f577558d7ce1e759db7dace75ed375c947c28d70041860a46afd57b0ac76c947550b030ea711e48395580f167c064765c686f9a01000002646226c718c97912d76f500a2c78d2a3622a588d108180027507740ea8c26e8d8db861a027e502750024f9a7b2cd8b241964e26b36c7e32399ed090005955626f2a5342ac8e42d8e1ed8e5e7978de8df1b2ff138cd149e16a9a6616166672f1390422782a78b2aa057289f2e28072f905aa03560018226516b2cf19881a98c16d825e2ac8ae7e821a8e999b2ca869e5afed3acc138b767739e4988e7a0a2f8422175a6f9b4be92aaaea9bf56a3ae37d4277d1e4921eca489e78523814a51c28c9eb289ca4b913aba654990be1ba8928dc9f83ca1adb24b781e94ae0bc126bf89b995a47ede8b4e69b6ee9b8e6ab0450400129f4010a000ff00c2c2000000461005000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b7efc0a34b8e1d4ab4b9e3d8a35bae5dcab5bbe7d0b36bce9d4bb6bdebd8b37be63aca401ba040cda402b26567776658c7510f0e3c987173e79dad534e8c50d277e4c75859510d92f5b654df7efb2fbe9d7bfa0eedd12f5b5f1ef73377eadfcf9f4fe87df53b60eb7fa2befe3b7519f8e1d7a8da7dacd71ed271c937c28c70040820e166fd4770ab72c937550b0ffd97d0e3888548ce1578063765c582f9a010000c1a16e16b718c87512c72f500a2c6892e06e1a484d1f7180027506700e98826d828da821a023e502750020f997b2cc8b240924206736b7a32295edf80004915af5b2a5302ab8a42c8a1ec8a5e69c7dd89f1b2bf1288d139a169966ae5d5657ee129c321742a6872aa017279b2e18c62e9c4aa0f4600d76f5116b28f18841a88816c8e4e1a88ad7a820a4e989b2c9829e4abed2a8c12877667f8e3948e6ac92e8022071a6e97e91a6ae99647f55af9e279426791e39e0eba979d745228d3a51c28b9ab279ca4a9d2aaa65489cae0bf79189c9e8fba0a9b23bc71d90aefa8125b489a955a37ade7b0e68b2ee8b4e69b5150400129f4010a000ff00c2b3000000551005000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b7efc0a34b8e1d4ab4b9e3d8a35bae5dcab5bbe7d0b36bce9d4bb6bde4aca401ba04cbda402b265e6b46654c751feedfb187071ec8dad532e4c50d175e0c7585951cc31f5b650d77b1f9e5dfaeffa0ce9db0f5b3fdd773275e6d7cf8f2f38fcf53b6cd37fa29ebeba7517f4e1effd3fdacc7ddd17db927c28b7004f7ef1f52fd3730aa7eb927550b0bfd8790e28d75388e1474062765c48ee9a01000081ee5a16a718c77112b7ee500a2c58522e5a1a380d1e71800275057cfd88426c877d98e0a02fd50275002ce987b2cb8b24f8e36d5336a7632191ede800039d4ec572a53c1aa8642b861eb865e5917dc85f1b27f1184d1296168926eb595647ae1198320702a5832aa0d626972e08862d984aa0b460097ac5d06b24f17801a78416b8a4e0a48ac7682f90e979b2c88e8e3a7ed1a4c11837657b8e2908e5a892d8c12f6d96d93e90a2ae893f54ab9e17045425751e29a0eaae69c70521893a51c28a96b269ca49992a9a654798aefa479085c9d8bbaf95b22b171c9c9eea4124b9799915a276de6bcd67bede7b0eaf810100129f4010a000ff00c294000000741005000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b7efc0a34b8e1d4ab4b9e3d8a35bae5dcab5bbe7d0b36bce6bca401ba048bda402b26566326650c751eecdbb977f6fd28dad530e0c50d073ecb75859518cffe5b65ccf6b0f7e1d7afa0ae5d7fefe5b1f9df63173e2dfbf7f0f977cf53b68db6fa27e7e3a7515f0e9d7dd1fdaed76f1e9b917c28a7004e7af9c5eed27ff997ab917550b07fd7750e18375284e1370061765c38ae9a010000416c56169718c67d02a7ae500a2c4812ab561a28cc1d718002750478fd78026b8d6d88a0a02bd502750028e977b2ca8b24e8a3ea5f269723209dddd800029946a532a5381a98242a821ea825e4976db81f1b23f1080d11921679e5695556376e109432f6c1a48f1aa09625932ef7462c944aa074600572a5906b20f168c0a68016a864ef908ab7282e9cd969b2c78a8e2a3ed0a0c108f664778e19c7e4a492c8812e6996c9fd9f9e9e79fe53a79e071424711e19b360e9a469b7c420853a51c28992b259ca48952a8a654694aeeaa69f71c9c87bae91b21b761b989eda0123bf6989d4a172de5b8d66bade6bcd26610100129f4010a000ff00c245000000c31005000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b7efc0a34b8e1d4ab4b9e3d8a35bae5dcab5bbe7d56959026518a6b590465ca0c60ccaa7faaad6b177e6ddbb5fa5bb6dbb7b020e3c37fa0b2b2a8fddb6da293defdccd934f511d5afcdb60edaef3de0e3cf9377eeed3e28fb66daabce55bc9cb3fa27ebb7af6b0eb51b7be0cd6f07617e1006fdd7a6da78c1f73edd63c551c20d7cd90840ea5606879c5f72c951c0e97a24000044896d482e5028d9285ed97108a001a7866d48706271f50208c51dc5d7c1678a269502e182806718c5108497bdda082ea063ed8361b82edb8d3a674320054a19161886d45832ef852e3882e3905e75c2ab7ca0c7df53714e38a5e69d5949acd87d36c89b568f0278a289915288cf589d6609a2019108c906918da4b7516287163862e09c76f9bedf95766775ea0c1e1a88287086f6df1b9ec11a446e90964ad26585b95ae6277b7e6ac52b7a825a0c9f8dc93844e084a27573be529df9c8650b036eba152b2e5a88f9a516568a8ba85bf9f6f22da77aba1ce759665a4b6389ce95f5a293cd3b4d65b6de5b8d66b6750400129f4010a000ff00c246000000c21005000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b7efc0a34b8e1d4ab4b9e3d8a35bae5db095902651826b590465ca0b6abca27faa8d2b967d6bd7bdda5bb69b37b02edfbb6fa0b2b228fadb6daa83cedd8c5933f51dcd9f9db6cd5a3ceedfb79ef367ceadbc27fb66d2abbe557c1cb2fa23e3b79f0bcdb51a79ecb56ff6613e108cf9fe5d974c1e7fddc6fb551c20c78d9f700e75206775c5e7eb95180e87a240000438d5d38ed5024d9181ed87108a0c0a68a5d3830617de50208c519c5c78166862665c1e082805718c51084877dda042ea023ec8751a8edda893a570320014a09551786d448f1ee812e2842e29c4e4582aa7ca0b79f527d3e2865e59159396cd77936b85b558b0268a2889d42788f579966f8a2009108b945908da4a7116183162822ef8876e97ede91765735ea081e0a48277c76e69f1a9ac10a046d9c863a926481b94aa626777e5a852a76824acb9e89c92804ef70a2457e5199f9b823650b0f5eaad42b2a5a78b9a512567a4ba557f9e6b22ca37aaadbe455664a0b6285ce65b5a19fbd2b0d64b2de4b4d65b2450400129f4010a000ff00c267000000a11005000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b7efc0a34b8e1d4ab433665288550a5d6520951b26a1d2ba9dba653b67dfa167c61b6deadce9d28c67ee7db2caca8ddf5fa5bafdaab6b072e6c75c174eb5fa9576eaaf67ee2e2d5a35fca6dfaef95b5e8a75507de4cba47f9efdbaa5f652e99bd66d9b9547700cebdb4d0feb5e76f6d9b551c28a72d1e7afd45cfd57fbdc78b95120677a240000c18155288d502ec108bd577108a060258e4528dfdf67e50208c513cda721e4802635616f72883718c5108c671dda0e1ea0c26b8b49888d59833247a2200b32f8949586dc28916d8b1618e161964e1522297ca8973fd077361805649541290c56733e98fad3850a48a207974a582fd5936ed8a28e8100a9841f7dac87b0ef7d0e08c16e827ec91e5d9b6e37d4ea0216f9e7a5767ec63f9894c9e9a3eb968e1a32e28ba13a46a471764a25a8708a2a6b1d83c118a36e7a92151edf83f1a8650b09569a742b2b24526859a51c4e5aeaa251f1d652aaad629a7be15f5e2aaae08fbe35552099b51bace2bcc63bece3b21504000129f4010a000ff00c2880000008010f4000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b760cca8550a1d18ca496b2f9bb686652844396b20b167a6ca7d653ba55faf4b59a2c2654599d45fa95badca759022dab16fa85e0c3ae5bb6dac6bbe0408ea4c6fddb9973f6afcf9b53bd8c57ef3b8a2bcbcf676add9554f0d18c5f59ae7d3b308517e5967f7e2d9430a4e4ebcfcfaf845776d4b2fd5177cd86650020bd87efda00000864dd78f1873ad512e9515e938ff14834948ca0172a1e680a57bb567b2400a2000f0278249480268670ee7a02c6dfd98a2400b22b80497850a02222281b16881ea073aa8a3605e2ea70322714668a286874ee8dd1180e988fe198816f782a1915af4e2618ce9e714a98822e8d5a797f9a7ba50270a581b1f691aa84fd99c39b82d9886adb934af7932d9a35a9062b9fa198c0e2727af9d3948a4ed68cdc8c2ce9e0ec988ee49e5f8d826907af73962a9e9d6702094366829e6af7218a4ef8976c76e19ac9289ca13932f6eaaca6f4a62b787a8707eca14158fadb9ab2152a9b7332a6fb61b6ce1b8c62b0060400129f4010a000ff00c2b90000005f00f4000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc89b23b26518a3702b2f9da4668ab995902ece9da8a65d3a79e5b2dca655ae0d65aa0b85155a5f1db66de5b9e5528c33d65db2a8be62a7dea5b28d8a3010ab2ba17fd63e7c1862f4e6d06b07adc2aa41ffe5df7efe5765bc737024d75e974f9e006548fe97d39337fc0868b7ffedefdfecbe6da556ffd1c57665002aa5778fda0008e7935c72f967d9d51cd951fd1289f92863138ca8f6c99c6202475bd47b2400a200090a5853138a1e66106d740aa67f588a240052a9833168ff902c1a08ba94821ea013298432d482697a2a07b3e48a2058146d87d9f7ad1789e97821ed722209b46c482ef76e1d7b328822ac8752691f1975a50210248ba9d631298ee589f21a8cc1780a5a9d32e733ab9d2d89a5a999a97860617c62e903138446c62c5b8c24d9806b928ab43edd878a49a62e7d8e0a3e1c610ae8e2e48c865a97af7446e837ea70e97a69a696a9199669a6a2c446a97c127277a66ba439389a5a94bed4c91a7d2a869befa0c60b2ce0bc6504000129f4010a000ff00c2fa0000001e00a4000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e2bca401ba0409da402b26561b2565897514e8c3992756bc44dad53cc8950d66fc4975859510a38e5b654af1b6e3d9a75fa06ddab7e5bdd1bf1376fcaaf6fdecdb377f53b60bb1fa23dfb357511e8b98fdcdddae87cedc19d33b01e002ab47a96c74eff57fd29d375161fcf677ffe533c3f62d8db3b593f2c5540000ce76abfed18667970e2c500a2ca79f1c4ee9874a13718002750a60ddd78f518f2de72e9023b502750020c9d6b2c08b2448216b4706f6a02685bd380008812ea4bf9530f9f7a1208aed08a2ea892d189c1b2bc1678a178ae5d863e94d2696eb168c02564f9a77f9a0142b8bfd57c3229c1aa0f1600d4aa41e5b28c1c74e9c78e508e1e5985a17a52494b9c8b2cd726e89bbd6989167746a6f5e7845ea9c62280f146176297b95967ed87c599f6e66912a69ed78eddf96291742267d0a51c28f8a82b8ca4e8df9e9654c8c7e4ac295799928f8a499827a9211907e3a8e19a139e852a76aaeba800b6ca2becad5504000129f4010a000ff00c2fb0000001d0024000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb87192b214ca209f5b218ca859cbc49591e55e7ff6061c3890b15b67dc0b16149891b0e51656583e1a7da594eeb88b2f5eccb243f6ef97d25f7eeba89136e2d5af47fc4d7dca97edbba827bebc5506b969d93357baadf931ff56cc206308fd0cd62de8c5c953066c55854fe2dbcb9fdc7eaa52b1f5c65aafe3c651100086fa9cd7570a0d3dd53ce00a22bf9799cd1ab46dd1800d51bcebbcb9f9f135a70d9021a50275002ea196b24c7b2cf700eb45fda68f9183a5f700838f06b49e953ed1b780ab78d5c781668b25d77b1b29b917699288dd88426a4b1e46ca918af9062e1675e9a0f2a689e517a2ad8a0aa0d0600b32b4fc5b26b9772d1876ddb7c0619642d684af82a188b2497056499a5296891753e56d463824669a5ad7ed9f5f5ed85a119466985bd49d562670a567d538cc5b9821d621a17bf951c20b887a68cac98be1a965c78a660ae2117781e7d720977a2ab29c8e56f96d94a331a8312368967ae9e7a0a68a9750400129f4010a000ff00c28c0000008c0003000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4578ca401ba0485da402b2656aa7da8ca2cea2ca957b27deaf53d234b67d2c6851446fc27d5165658adbb60fa5b27b757c6cd9b57758d5cb87fa916eb75bce95ab28503165b68fa95bdb55751c55c37ba43e1cf87aa1e65299f29dca769543600c9b334d8cd654726da76ba0b0dc2815bae8acaf0bbd1d66da8ce6ca220008bdf43732e04e716f2e6c10458d62ec4377b67b793010ab22773b0f1e0d79a1f6d28cf6c60ab2086170e51ec7507fee945a32eae3e10b6700be9df153e6d6772f2fbcb6b3faf6f5152d156ca8563a9c57e5d600608341e7f65263ed57c5df65b907a20387f9172ad1831e97a28a710068641b6dac46bbdb6dbdc6cc5a722e8819598b1ef5dfda02c5b8e2a16626853a948379a8aed7863ed83dde6851f841a061260920a4603ae846197271d6ae5a6a4a0519db73a167650b0906597f1b24022754a51cfd19e52251a9855d969d125976615f0ee8a5ec6f6635502c7765d9a7ee9c76f9e7ef9086c410100129f4010a000ff00c29c0000007c00d1000080ef00ff90c184070e5365809590a5518a1a5978f0758595150b2a5cb88133a6cd8c1b3a7cf80234a8c387011ea214d0d124ca2b2a5a8c790336acc994376e5bb9909550249e0fac346121b525ca944b8a1d3a8490ed4c99335602040172a057994baa5dba85592ec29a39163cb205f12bc69006866d3b863d68c5ac4312f4b218022b09a46dcaadbb873f2b5656d01e247a15ba00dab002fa1e3c959dedc65e6dbe751b47750082b88b2b562aa89f62c39d01018df936754005139f2b9e3db633bf5d9e03eef4ab10447164d4bb6f546bdaca13639c33eab61c2494796bd4c98b2eb6d7dfa3e8a652439d9d5c3af9eccbb9517e491575c0600a2200479e0e11e9f1f4ea0db2cd0c2474f0f0fce5fe25ddd4b7f76b2c2c93081dde3ffdd1f93dba766e1c946108e7402a5b45e65dde492585311c6cd51801265aa927f5502e35383515611e6894d25a91f6d9951c0e452917862e158bda6e49b60119872eb889d144ed5706d5814905036e8435b55e1060a1e8a3609135e6905026e1b83110524e29135e4db1295503925639e497616d4985669a5e69c5679e5e7906a4910100129f4010a000ff00c2fe0000007900f0000080ef00ff90c1840b0a1c388031a2c58c0b1a3c7801b1e53187d6264cb8813361c985153a2ce8a1b2a541941d2a7c398211a9c49a2f428cf7f2f2ea4692391ec469b2f664c791390a9429e3f6e8438325720dd84173ae45a70f763d189336ec41a057aefc2a559966dda523b20de9253a27d48065ce8d0be3166058aa5bbab5e9569b6f48954da215cab6dde7c6bb57e2cdcb089fef5ab365fe0ecb745f6f5ba877f60e29c1582844bc7bde0e3c27fae749c779ee255cd2baa15193a5179e5ca9fd6a60c89b37562c98d5b368cd4947d63d7b903be4dda57bfe9bf8d7b750e58f960729e7727ecbd9c33b16ecfc73bce5c2d71ad5dadcd437e2bba59717cc4c58b2386dd1e5cb1ffed8d97165e15bb7dd1fda987c6ee9655e7efef8dc64f5ebefdf87497f564102d4402a410100129f4010a000ff00c2fe0000007900f0000080ef00ff90c1840b0a1c388031a2c58c0b1a3c7801b1e53187d6264cb8813361c985153a2ce8a1b2a541941d2a7c398211a9c49a2f428cf7f2f2ea4692391ec469b2f664c791390a9429e3f6e8438325720dd84173ae45a70f763d189336ec41a057aefc2a559966dda523b20de9253a27d48065ce8d0be3166058aa5bbab5e9569b6f48954da215cab6dde7c6bb57e2cdcb089fef5ab365fe0ecb745f6f5ba877f60e29c1582844bc7bde0e3c27fae749c779ee255cd2baa15193a5179e5ca9fd6a60c89b37562c98d5b368cd4947d63d7b903be4dda57bfe9bf8d7b750e58f960729e7727ecbd9c33b16ecfc73bce5c2d71ad5dadcd437e2bba59717cc4c58b2386dd1e5cb1ffed8d97165e15bb7dd1fda987c6ee9655e7efef8dc64f5ebefdf87497f564102d4402a410100129f4010a000ff00c2fe0000007900f0000080ef00ff90c1840b0a1c388031a2c58c0b1a3c7801b1e53187d6264cb8813361c985153a2ce8a1b2a541941d2a7c398211a9c49a2f428cf7f2f2ea4692391ec469b2f664c791390a9429e3f6e8438325720dd84173ae45a70f763d189336ec41a057aefc2a559966dda523b20de9253a27d48065ce8d0be3166058aa5bbab5e9569b6f48954da215cab6dde7c6bb57e2cdcb089fef5ab365fe0ecb745f6f5ba877f60e29c1582844bc7bde0e3c27fae749c779ee255cd2baa15193a5179e5ca9fd6a60c89b37562c98d5b368cd4947d63d7b903be4dda57bfe9bf8d7b750e58f960729e7727ecbd9c33b16ecfc73bce5c2d71ad5dadcd437e2bba59717cc4c58b2386dd1e5cb1ffed8d97165e15bb7dd1fda987c6ee9655e7efef8dc64f5ebefdf87497f564102d4402a410100129f4010a000ff00c2fe0000007900f0000080ef00ff90c1840b0a1c388031a2c58c0b1a3c7801b1e53187d6264cb8813361c985153a2ce8a1b2a541941d2a7c398211a9c49a2f428cf7f2f2ea4692391ec469b2f664c791390a9429e3f6e8438325720dd84173ae45a70f763d189336ec41a057aefc2a559966dda523b20de9253a27d48065ce8d0be3166058aa5bbab5e9569b6f48954da215cab6dde7c6bb57e2cdcb089fef5ab365fe0ecb745f6f5ba877f60e29c1582844bc7bde0e3c27fae749c779ee255cd2baa15193a5179e5ca9fd6a60c89b37562c98d5b368cd4947d63d7b903be4dda57bfe9bf8d7b750e58f960729e7727ecbd9c33b16ecfc73bce5c2d71ad5dadcd437e2bba59717cc4c58b2386dd1e5cb1ffed8d97165e15bb7dd1fda987c6ee9655e7efef8dc64f5ebefdf87497f564102d4402a410100129f4010a000ff00c2000000009100f4000080ef0059d2318ac80e04385070e1458209853c184c6061b283179934b8017122468c17363456317264c1902b4e84b8525322c59c095a44285135e7c79813125c4871566d43872d3e2c886315a6c9892d121d7913516ec69a4b369c3aac846540a913a235aae379e349903f622c8940fb60df813b7e4df9433ca3d1aa6172dcb87218edc0936d7605d8a4f9aed2a86576b569c5f069568765eaedebb399a042c521031d3b50bd26c8bb6142dda987dd6f4b9167070ebb04d3b6c0db552775ccf712f66e84a1cea59a361f256bbf8b47b5aa0710b54cd97b3e461ae6732c6bbc9546661a07b7b0f4beb39396598c18ffd7b595163d6cc655b0e6b471aa7c26551afc6f53e68b324d4aabd423e695b313fcf9e7957de3da61829ccc061231f4c27faf5eef73d5785946d3555e451640e676f926ce5c6fddc400a677f97402108ab1c6eadc6af138bf5d720e1427d45c7508fed767c536eadc5b591757d57eb9d4589b7b0a1508d7585537539761c1e66a1a6bc8c652e485a146eeda71c566fc5e479508a5178416e5226d44a16773a38f2a47132d84e1758ed396713435266cb955505592621400207395f826d67d6e28655a9545a72b147469e5b128493a79fe59703e1907ea447d09f0619f4627cd504000129f4010a000ff00c2000000003400f4000080ef0059d2318ac80e04385070e1458909022c78c012a3c884179113184c60664565ca0674b88153e0ce8c11368456b194e7cb8615469c2902b56346843116dcb963372ecd9f0b3af449d2f2efcc844b46742a02786053a04b8a257a03b1a4c5831ba25dba333be45daa091e7c8af53c2141b327ca9d2b863aac49942f5abc8ab136abdd807512bc9b70fb6c50a313eee5cab530354baa5fbe95f876736a4eba2d4ea489c2b8acc5cb834ef59a8597a66d9c973794abf338e2d5aa4f37954ac8b96c49c0ad6e5caa48507ce1c0832aed4b569ce2e4bb21de2eed06f4e7da993dca442923563063c6bd1f94ab9c727957d94d4a476d97d4316ca5c61e56a9243befe6e1fbb32b8e2872ba7360f67992a66a097b217a94b5c347eb5bfef5d0f5d1aa474cb61a6da134e7dd4fb5a7d9166361557f9e4b71371edc6d0556c6956709a5095e6259161a5262c168806d77a1e466dd693d77a0ea6ed957a85661e15872ab4dedf41add5e552832567c91276e14479d67addc8d4545a65464d5f57e9571cd86409e75cd23675d474537ccd16c325560d3891208d065840ec730a8788d0790579729340c16946ee644e36b653994649871199ddb97e1d682688331a6995160b9c586e8956a84fed49766b7ff596526198b109d7ac947e39805136622707e69d26c7d85e4db587e62d59897723a893e93727dc735199d8ac9352b6c263aef95a290c107889b5aa1f529298572a81d175791994ddd5f85ba77e0af2eeaae50ab42c8789ea1a29ac99c6481dae299808a8af160999e69d926867e0a2be696b217aaed52fdb46921b262e8c71b9be1790f5f969ed8a22b8f16d72157620e9ae7de81d26bbe12530a0b902f8076489d145966ea78ada8ea295aaaa1b5ba1f10a46a4c956db3c60acb108ce67579a96207d6266fb3ae79fc55b8e94c9f9684b659452e78b2aaf9608576065e21a87a49c41ccb1e1699ebb5d1e426995b7d177fa3a13af8a423a9599c0a254cf5b8147ca5c6a5d624c63adbfd29cac29b5717c39a782f226bf2a6ab5eb27a093e1d80d69a73ecad79b66fa1a55d7a9e54841fef9ae3eb93faeb0ee3ab5b769ce8d32aede172753e8ab9e6c75b17f8efb8a2ddece06373bae1797762ad0f9e6e56f8e6f47bc92de3f4e8529cd27fc1ae1b8edf7c4d7eebd975916c8f2cd66e9ec59eba33cb77e6be6668e9aaea9e3c9a7ebf7777be2cdc037b68bbb7665c99ac5dadbb1a316747def1fc9dbae8dc9b7f5e8cf0bddf455eb524aa9df88d384b437e7d78bd9edc1eebec6eb5c35ca6826f57518bc355f314fbdfba4c3e5124aa62e22f1db816bf933ddf4937199e14f615a931dc6dcb56e919946236f725bdfb03854306d66c250c35196e8851db4159941872c8e4e905519b10658cb565a329c9648fa2a0dcf8352cb6e85c6669dbbb9f0f16f191c1a52f23664ad89cd8f74a27e9b0546b2261a90194a52e31294f44ea080000129f4010a000ff00c2000000000a0005000080ef0059d2318ac80e04385070e1458909022c78c012a3c884172a5c5871b126cd8a1b3a44e8f1d3654e8bc88904263015a2b26509569c3992702bc597216a235933d5a9c2913962dc79c3f6acc6953382e42a0455e1df9b359e056a6379aec8af47aa15298091a6dcac57ba7dea06fba8d0b467ca9d2b86fc61b1a82bd2d469d6f52b48bc3d4ec51ae6fe6c5bb437feb5cb27bf6ddfbe75fe063c9750726abb8103f56c1891b3c094974a8cc85913b5ecc0273b76dc0ab3764a87478a9ef98ad56a628aab53be7d7ad57c68dba76bdead8b567e6adaa38e5d68e055ba40ae3382ae1eb3b8bac3ea039fc43e2cb9fb6b9ccb8a2f381ddaf3f5e9d98f67ce1cb3efead2d7954b9f2f8e937affc7e5dbbfdcdb9a76d2d7457e05bfc438ed5df9f3f7d7b9bf1d7cf1e710a9617df53020803df79023477dc75c586be948fe158ced48ded5851e3790d1880146c754684d3624906a85f402e28a2a55d8df54855572206e81559850622ab86026465958c3668d326804658e3e09bc965bc9148c5373b1180b90880297c463805a2825ad6e46185bd59df15531d230d1143c5786e52734634c16994d968119a62469886af6846d49ede8939f41d9b5fb146e629805d16ad9c825998fd588d45c48727728e886318776a045251a236b929aa9f3e4a59aa9e1a298729585ad7e46d50a629f9ee50ae2893a9a4aa9adf58a5a69a8f1baef702b90367568e9676975162ea665ea3fdeaeb685cba19fbe954bd65b4944672e59ca980628761935d45876d53bac217acd3b68e4bbd16b5d6277da88b0138a11138f50b86d186cdd75612a60eaba4615cb6fab8297065293a1ab0c9ab70175e411513a563858b0f285d554b6d2651e6bb81954f12cbb5129f41741be74576c707e3c072d52fe75513d83697a822a6c518cef5db9063cb365431b84b41f7d764812b47685eba919a462dcf01268133c5bab9c27a9017982ba99cf165f1ddc1f63ab5d3833f0d823aa04396ef51dd192c1660d54acbbf51480dac85a38ba1a69e24a7bee9113a5ea98d3a539037fa7538da1b9bc5e2c6956a7f60dc05fbfd9ef9d3e6f4cea372ed88eca2d30f38233e850b3c183baf26870ea9909bad9075da827c53f9da3a6db824495f64886bd207ab7953c361286d18d6ab28f679867f451f97cefa3dc8225d4ebb71f47b570d2b589b7327cf2cd49bda18b5ce872e4cb1df575d7335b31d4cf170e6153a17ebbcb74f59f98d97f72aa9e4df9ab53967a287913decd6d919f0a99fba157484ed9739748c59449db864d6bc8d67e94f6e4219beeeae2eb8954ab9dcee94ffb8f418af54c9ba4166553232a85c635aa2c88dc446e22e053f654004fc57f8c24b90a1fc847afb0e5fd8f24032cd0d817c1cdf15dc866cad95e9ea7fb9ef0b8ed713b21dbce96572575486742f2e2159827effa2475884172d31b800906f0363d1fce506b3b5a07a32ca3d18e697fb1cf56e2a8abafb8462d6e92ce17f2c4981809770480daf12b5ef789b12efb4e5ce2139d052347311eece98904375e03e76329c9cf218d5b13e90398a2a2dd90b061ebfc57c47316372677ca797c5859b4f5c6c2d9bc63771124d96af4eb30810e429b94ad5f6ea6772722aee5736a5f9201851e94e5c1f87b72d2afcaf8b9225a8ca22cdb090e7069aea0017ea45e6bc6d4e6592830360c6d68bc75a474f508be897ec369d35f1e1947babd212c4227bcab5548465d332ade866003ca573b65454c42eea295c28c51d6939aa4811a0483dc1b5fc0a84f955190596e71e366ead7d0efb7a9705362b337e4fcc5d4470e0ccd9e113cd315f87aa216935287645014c6e7e83b9deba72b6a7d04070908c7711f2e69411e50a237353736747698c215ac0f9971152257c480dc4655faf80abac8ff486493f06c1bd5c4af4a0f25920d48e73ba3eb4e4d9f819782f31af4f8eab3dd4cc28f91926d4aa9d0c4f162fb486c186bfe88b3df9a76688adc0ed25988ff47124aca8c5bfa46445a294ad50c2084521662a8e51894698fc06b63bc5b0564691d81c435547adb2ca868dcb6a2641c2cacaa6643a58890ca9b814204c7d7077648bf0eed288b6d885c3ba897b68ed924a66d5a1cfc99321bfda4ec9ebcc45a33b9fccb9e14bb933542e055e976d2eff1d4709385e4686b38c43789dba8a42acdaafe0841dbc2a45739d49bd4ee48dfaa119d08a1854f0065bafcc6d2ae09740464e4be89e4a6eec48e8ccbf2d5516596afae9d4b48dda124d8798ba0fe34dd79a357656d59bdcd95433b80cce06c136a0e37d625ad6a3d5cd150289bc9c0b01839d982df9a1a37db62f4fe2604f2e72b6780d791a5d89155caaeea7a425a52543195cb66996b3b6fdbb99434611e9718f6e962b73213349e89b897b64971ecfa3b6657b94956092c0e140ee210a1b3f994702c015d0bef47c7c4a6637137b2dee248b2c2c3d4d35da766cc998de5c32c2de605f888b8be6d6b65d36a65273cb4eb924a41a36c266ee2a8c0eabaefa5f77a6c651a4526866eca26f4caea7b527b9cfbb296fb48a32559a9f63abb46dd296373fdb0a33978f51bf95eeda99d80fb489519dff9e79c43663bac2546c4a21b8e274bcd62681d5849c25d6ac3b8a21e571bb8d860e9d81f991e84ec21f5d99599a0ff344553b9f48c3d3537c7bd626c93f34364b369a19696660e8de9936cdc431f9675356472fbb0ebf4e56ad6de655db799432ab1ea822a7c512c1464554cd0963e199d6d05cdc51d76423dba645a9c93a6976345c0bb576210c435713e93d603af516a9639947e219dd6c0cce4cb45887c07ab95569e5aaa35b3a47da86f480b18cf7f0ec7c0db447fc0aa54546fd39a6275cc4f7569e9688f6b5fb49b2c2e91478d96d264163b79adeb1c49468462fabc74d09b4a23e43c46b713db32aab5e6d8a33e0471d5119b584ef0a36d8412c697c888787ba93bbdc2ca42c11bc0a023ea2abb4d0bea7f26199a0fcba0e2ac3b6fbd3545510cc61aade821a3315912bb6e0f0dc5ccfce995949bdd3bcad3313ac36098e27088f6922b80a883c41b07f79db46c693f2c966959e8b3ef922634c129727cbde91ec5bc483b5789aad3ce52febb5d773bca094265de83b5da9294f5115ce9796ff75ce01580bbce6e28618a2af1b6e417924b360240d6cf4dd72d2b9a3395fab1a93da0b287fe1e7f6c9666b3f1179826047cabeeea2e0ed19c310100129f4010a000ff00c200000000fe0005000080ef0059d2318ac80e04385070e1458909022c78c012a3c884172a5c5871b126cd8a1b3a44e8f1d365409325466c0982b46ac3911b890426f27021b18e2599bc560317ac4a950f66ec99ac086d4f913382f4b9f2b8a0de99457a154a8417a2d3a44d9e2d8af37724daa04fa275da34b9675aa261c2359a659c2ad1bb5bc245e8c03e6749b529e664bb07116d5db779f6e5bbe79f6069b38342ed9b18b0fe50c4851ecc7ca316ab47909b2325ac1933b464a5932f563ad9f1f7e0d2572386dc5a933aedc89943be3d69d4bbe4dda53f8e5d4b16b769d8bf5fc61d8195a164c97507363e3c19f1fdbac39f2feb5cf9ff54cdc7a75f68e718a354bf6186777c405bef7ec8af49bb8f3853d929f4fed9d387dacdf669f1f7e9961d5f90bd7ef7f3f90ac71f1e9368ede776d776fd674fd085417780ed71f9f7012f421ec7cf9c76164860aa771e48b1258d41e7c1248b0ae712698e1e3862e5832e08922685f12820e285e118b89942dda46dd1683e07a25d858de8532940d1178d13764a5480967816b5b6165b31b5b4d8595d96f458565e95b9da5f4e695567985d79f5d49152f4e513995d99351b575e76e46999a56606e45c6e58a4a047850777ef897e47246e998509c3a07e723634ed82192663a3712146c4956e4996a5a86449f407e89c8e5a0725afad766bd3aab159d95791a24ab9a6ae955a8aaa6c829a99625da9baef0b685f916637268cf1f978e19a86f8d75ea18eea2825751d57d72292422a08e0a7f55543a4ad8a485fd7513d258225b86a7a5415ad658503a39d5a6bee5791924bc2e496ae794ea99a5a180ee3bd69c99e916c2219b1d876c9778729734a442f5ebf7e356cafa31efa819293cafb3120a311eb982c5c03343966b50d2c0e585c8248cd2ebb496b3b269c319a10eaa96a7af1b7bb1339d1fab3a68c42f9cc17d6fea96ad67a56a968f9dc1d9f774d67585fb919c74ca0c4422b5460d7c2faac6fa68a2b9fee99295b3d2772894b71f5960bb9c6dd655b7b476a6af96bf5baa81b4cb568aaa98bd133a9a1aba5f77a6248ec2b766efbd47b95c22a0c90bb42efd5576071f2fdb79fca7d879fafc41d3c80dfdf091e983db8834cf7a1c387a54a97b54f9b113ac1793a22bb85f69cc378b60d8933eb81027a48728d8faddfe87a8fa9dabda3230ca1e2e3da387d934ca60b0817cfc988dd23c015d7c6706f2e49f79be1121e3530f75d164cbcabc1986971bc65a5c9a74027bc07afdc2b6e3428d9ca9c48e4e823273abc993ac929f472d6ecbc39b29fb5d7d5fa7329bb3386c34b0b6069976e0298897ae17e13371978324ab39def04546a4e54deb58eb5802f8c74bb3d1f64467322b83a0155b16e947a274ca8b92a2a6a63d396d89696b5ad3b6562710a1e58a5bfa602ab2b48c98816a61549329dd52b4c9b8c97a677eff110e83b4d3d81c4160b86f046160ca17c0be0aeb404af11b40aac5b7b6e44b268702bf50c8f303cd2a3f4b2ec100111fe7b1220e0f26449b5d1e8ce5dda22e39aa7232ea4cfe3445cad57b6479e2d1ab05c52645edae06808c61a4c8c670487950f475848cd08068eb39114e46647b771c7cc79d1746346f887c44222932333b803e2641f2532f58b537163267849783341eca123fb9469c47770a2219e895a8ccf0b926452c7f4ed42628b629fc4353a46a482508a112d5cfc382aadc18e8264522bc9b6c628b99df4c399d143e0d699903a6a442f608bb79627e5719dc8ffae7c33146948653296fde7af60bc80e733b7b7252d605e92348951c414d1efab29c5ca53028953e05659bdc9c92586b3086e6c678d2fa1fce095e4126633a821492ee6626303eb542dc20d3e399e2853222a9401c9a3aa5a2e2744c37ad78a79dfbeddf3bc97d926c849d62daff411f639e3b99cd81222396eda057035a1ddee4526c915ba47a47c3bdd0bd842c176909e7a841163922abac6e4623737ec0a5b25b71ecab9a117a48aa527579811da79907c806ce62a395903aca1ea474deae81da493525e1a60579cf322602768b3b7a4f19c66f22566c2f8ed2cedf59045f188a844d99ec90dbdceae4bcb8e43572b3f8e53faa74af4efb467beb4f9f8cd8c1c93ef2dd507475e5e0da0a11bdec897c451ae52746acb0d4ac4fa5238ef424213ab911124a8b672cd0a8fe5371c690ca8b978a55a7575b5854d8f4fe47cb8362921ae5c79e4119880b7ee1ca865ca3e8457f914217201beabecc62cfe370b591516a98cfa85d9e2644e92ee7a247bc33f288c340c499222ffa74c4e241f4b5eba5a82359d6a936a6fbac359edf4f189cbfa6b8e742f51daa42c536c6e52c01b3a503aa8a221e2c02b13456697260350a513b468f8f288bbba2750666bd3e4270bd9c6a9e6bcb22241f533399b4a7562d22cec47d5f6a93f2fe59113aaa5ce164a57a025bc3fe49363e9156b89c7da428e02bfb312ba50ba2eb2ded6bd866bf173cce4504fd2fa0e6afbbf218cc78c5b6294ae4bd30e653b04579ba1ef7f4d902e4751a01a33acaed27e663b4da1b87b1a5e23b33c53c41b9b0bf8234b66fce48ba53429793adbd81b5972abe2c1612778125cf8dd02c066466067c9e0431357f3422b3ae165f73c17f849a1d48a1535ad7bcaa6fdb66d557de2a3d2a84cc30af1f3a3dc55ac7d67afc12739fcb5364d17f42bbc22013ee47e233905312c7fc71f23ad56f3bc2a7b14e6e9e9ce25c47bcb5b5b34ebe441d8dc3a516465198a3ddeed9ccac53b24eba0b5b96303c65da404372c0dd8e14135e66f81a4241a450bab19c93b9522cb02f111f4f8be5f2032d09c15f97f76ff493a2e069a04d5e8095dcfc331e3b8a12575b11767cb4f55ace0d1fadd9d498bcfbbd676ef79cc9eea2e15ea144bbcc6d4774a077b9d1a502a66dde58703e7a6878bcf10b20fcb833693abc509b17a8f27b9948d9e2980a670d67d0071cc0d0bd059a4c754a11bb3c02a17fbb58d8bdf236717bd84c510ad1cf035e5e7f2a6c61922ae2b5c1c467816613e3bb57bf973f8076c7bc5e2ce16815b0acd6fb7fd45c689b17b38a8de074a2e48b5e635c08b732b9f9b937bc4dcebd43d7c664bba9ce9b11ed0b39d47f0626193a25ff0a79d2a57f0fefcfdcfce1b2551996f67bc6ded9f859f969dfe00a792ce79cecc2cfc2fc6521ae19538910597b96997113895d4242906c1b91599ccc8bb71dbcb043731d5bc75ebbd1dcd28e4ddf0150e1653a1d09eefe4c8b22c705fd2ee8d1238d4bd756dbbcd4819dbb93c4bda3465ee6b7fe1f69a9ac20d762a2de39fc72a92b29f17e5deb5fbf37746374864877236781695d712a6677c52c54dd37257c58550d7047c25bc0d45b47721913895eb7f73e05d07de7cc2cc4c02217de7ae2003fe3562243c812671e4821918dd21b37a25053c73d5a644d68e5765366943bb71c4227837a733a71040965574334183b6157624a774168663a3876a344f37271773f69d37634b2eb3775b760b2093172f344246616581866b4e27197e84ce4ce3da22e64843171f7007f84545406a17ed5982db4293db6146848268985911ed6ed7ab6446273d389b39f57571c52c44f3808bb7ef3b78b39b6138c08314f170465b5934d182877d25282425f65a4cc79661b54126045c6ed38d3fe4d08863187d661c6b075837d17c70e78b23553655c4e369940949123b33d7975d97447b166c4bf6306f95f869e77481f2616ec7ca6e12693516265df7723107c88a82ae43b8445058c589a5bb57012485b2ac77b8c560f4f66a67383ff5232b158458d45676e38982346b7f55a960a7376532be8711e37c321171e7ec5e58fb7812cb1d365c33781783977543b8253408237eb2ce40862e4c94dd56c70367a79969172d5ba55c8337c26a273066b2352b03676a74236712e332e81989b4029cf6bb7f25c167d56c74075043b30978f6475cd8cd54d40383ef93a66057a26527dc3fc82a8358f62d35d68da4328498287f96256a432c1d580e80a6783f122b84885f41d7956a94b75083836de4109019386cc13b58f3176b35c98381bc8ea7796e03dc89f8f94b45d49933d596386b38c65c30c89d4316819b39aa29360b8757cd51a8907168449967be4a490545345a57f46641359193683442d81980b80e30934d36f47640762a3a482a5c83d12286489717599b162493257570237888464b7343d576e8e59f64627a583a9cf85479e5cf5123459736418e499c6d847e1883808429c23604822d11fe32373148199f8ab88755148c7a428a4c66ac4a13871d278f79d67b5388077515306ec2557e61b659550e7847bdef44e8d83028829a05fd8b57b84934a898f68523731b99b2478e08511679e67248315b586a4206e039d6cf51a8b866a66945f75798a6ff24a4cf6295b63c29d799493e2238dd16848d8bb7ee36949a6fb8586043f253a9e045b32d86b4b29d780779598b50526e4f89265627887ea80c6127458b488b7a73d658c7779058a47877c69499925b49a94867a464663761691176651b4ba19e8ca8db2c834a3c0a3845659627d50b409890af1acb7859ba91472c5a79f93d73bb4de9975494a555732d3f595a3394b252528079776a80456c59d75b44d9fb6535c63ad87e8276d53984719f79638ea51a9c589f3b375a9f74ad8259253a96e757f3b8612884a574605e5683ed110100129f4010a000ff00c2000000000910f4000080ef0059d2318ac80e04385070e1458909022c78c012a3c884172a5c5871b126cd8a1b3a44e8f1d365409325466c0982b46ac39a2b52bc794216a9c894376adc595317adc564c4021b18f35951b283497af40a3078a05f974595055a54b72f44ab479a1d9ae4392156a85f9e6dba14dba559a165be8d6a263a2a53ba6bb2b5ea56ba6bd8b051e25dab06fee752ba7fcab59b673b20ecb281f2fd2cb77de0e3c96307362cf891fb58c395277468891166edca9b337efce93438e1d2ab439e3d6a353ae5daab53be7dea363ce9d2bb63d60d5c4befcddb478ee63a34d7f4de91c3b2fe2efb98f2d4edbd830f5e3cb93374e1d9af178e7d587677eac5bf37fedd9befb4fae8dfbb87be6e7a79f0fae1cf8fdedefcfaf7f9e9cbb74fcedebcfbf3f1f3dfcf25514a3d08e25e450ed4702182392860e2890e38e0648d0e4880a4851258c0e58a166841975a5d78655885498840d88626988228872aa892298c2eb8e26c8b2ac8d2ec8636d8832c873ae8932d8c3ef8e3609b3a09d3e09646198420933265f7954126057555585d39a0508a4d49322496562414159c5949d5669552a8d497915e5916214a529985aa936a95d62557627970989f52a957ab9772d9f59063769967ef917af9b520aa7a0a96ac958e0ab62c99821ac6e3ad8289976e9805e6e1e6801268b9a6a616680a67a1ae7a2a69a4ae9ac92aae96aa93d8855e14efa9978e5545a51da361655c1ea7beda3b6359bacaabadafbe78fb5371cafa745fa7caea3c5da8ca0b9ca3bbc20bac65b4ce4b2d25b9de6bcb27b3c67b6ca5b0ee7b4e64b1ea7b6e69bea6371ba49aae8acaeaa2f2cb3fa9a1f2db8fadb5febbaf6ebf2d5947679c01f76ed954d1475e126cc5474e5e51e1bb707d5ed9372e9b57dd3750ba511b2cf79b7c0f5cc7d3c5cd8708d4c5ce2c5618c60f2642b0790b7582b3ce7d670132c2135c72f7c849aca179cd09da926087f6fb443fb64f0d74feb84f2da473def23d0fa0c6057935fba8c2ab7deea5e66d0d24bc5f3b75b6d0633b2636be220b7ee9df5b7d56b8bb22adb57bd85bcd96fbdb678de5bbd14fefdd467edcda26b0d23c86784390de920cc9a4d81e8891249baa1ea022ea9a2eb123ed9a3ec024e01a4e4025e30a5e6126ef0a3ef66f4735b5e3359cb57c83f8932fc581f6993bfc2653c29dae96abc685dcb3356f2bbec2bde82ece737dea2b5c485bc98dbee62eea7dce91bd5acdc94cf65ab70c337fe7892f9db3432366c3dde0571d3e72df4b3d4e3af6e7af7e7bfce73ba1d2c5ad6d5cadadc627fa2ad7f3cf0fbdf8f71bdfb6acef0085f310eff89450440e003f795b50a69895f0c306abc08b0c90a2052810cb0eefc2811cd0660b388f3e0230348f1c11660f76b51fc4fe2443b12d5ca643e24cc4c0ba62a991a5de3363410a76278c4ad12c0f78ef534022e0588e3c02a1178874c22221798a4c62e66878619571344c22110cc57ca881943954256f5203d61776d5443d71d83164e2d81177ed3336611c8152f2ea19c8d6413eb11d869a632558e8924b3a060f8e6c680713e8a64f32b1304d74d31f15e8284832121196840b4a11e26c2e35ea2e76b28227680881994221fc66a970606a42a0c0b586c3946bcc0e82c6b9c7b572f68781052923353a465288c49c224561193924c649b0f5841c015c2578f241d1a0917d998b061779234b3295eb44bc679321321a9ba1121a9c118d5519a97810d53312915a66ac09b9d0986240d944dc0a9e0bc9319c6664a22cd43c182bd94ecec8433e9911b6e84e720aef892da13f90b458cdc29980935082241c72ddc311736db5b4e0965471f566681a7d2776a1b488c44696b243ffc491241e7dba57a75af035892c20a00500e3473f1201507dd3d0aa2dec464992254e3084f50d703792be233ea465c2db21a0e3c412b0508504d4f340a00920558a9e43b044c879493a2259d4a72755e72c9d29ffd53d328e95943f036835e8c57489c110e9bcc1465567685138ac80583538ab0850c4d8462ec7be1ca622651cca3f58c78710b538ad70fc5442bae29daaf9a121a871c84f0b508a9605a0bd6d0a2f570b275066548f0e8d504a0e4abb49cd3496702aa767b6b74bc9e5805b93ccda4205e9a33c32768977db27ea0b83871aefaa91d0b35056892af042d924f0ba9b74e8655d16fc4f822fc893092c656d4ab550de25f3bd9d59a0807bd851a2431abe8d1aed4fb886be3447b0082a311b0506dac4d013e4140d62196cbb25ceaaadeea99cdb5c5da6bb24d405a6a6fb2dca7d8bf206ac92e500a87b63015b93ac12f2b49011354979d5ad57c2143db303235a713a1da5d905e020dd196f7b7890e192143e9bc8afab614168d0aeb0cca79241ef531339156c4109bcbc44d2ac1c682a45cf095436d3eee25c25b0ed06c7232ee8813df7ce4dbe2047be090582a8d95715c83457c0430d506492358e34859f078d7a6c9e5c591b417e833601ace165aca72f27b51cc0d2f1b3bad202e500eff7944fdb28226ee982535c2061cbb2a1a440570d4603a879a16da17413425fd217987918b5fb80a19cd4905436b6b35298c96f685c483df9f420bd0982abfb67ac072639a621c37835a817174ada43dc707862838a5ae666e602bd7eb4ea4d179953719d4fa8cd73eab25ade5ef924b22d3b58864b3292ddb903b7d6865608264a7053cd57912e4dade15695ec4cc11bd7db24ba96239a171db299dd47ce3c2f1ead8b631362dd52963b67b9fa97a1a47b74aa853fc640d619992eb9cfb0350075354af4d70f941bd13108503d59a29633f2d1dafc09cba6fb32d48e0ad3bad11960598c0b2ed29bddcffef5694ef8a91c77aabf44dd9337a9fce752766aefcf6ac8a0710e2c801cda28ded317bf25bd08ccc5c6f12419f44ccac49174d4cacb329fc9eb2fa7fc0e1edaeaabb559054f168a3332a300502fd6962b1d8d24e204b75576e548447f50db2f4f5ba6e214e476ac8247661a0a1ac5dddd69c7fa8c5c312c6ae594da48286e1319847c5ac171dea7b10aa491e95c21664fa9374e8ed49e3816bda78d92c181421a078b5879c36209636f5024e82f1e5dbd78c24dc79202d204e773230da9214e4135012f1635095035079733e3d3c24ef1ed7049b762dcc651b3d579cac8aca3bdb9c79bde418da24e71449f3d055c883e54c58f6dbc94330a0c770515e579c03255120a8c244d5dcb2e95e34ede09f6be41a6ef012d19afe9f9af92932673ec01397bb7a9241b4a04a8a1aff2f1529fa879a7144bbf2099af47af358354203fa1d55376124a477451287325697b014564084760b57f77772016a02a7c864c0335b86e310459506f71f7985ec3577197797bc07085009505e5171a87325500cd7b26476cf34c58f4747ec7435747c70405f57501bb7366311cf7028e774a39c13089856a07529c7ed7228081d38aa71258500663017c65d5501585f20b16bc01d7595847ad1527387500850977fc5aa7847b917e62d58030a0358e257643475c5126c08401868145241287454a96f206a7485126b75595907801a87d58cb1978611a65595500b06266f85a488f7201350850ef7d7b65950607538fc7922978243838556f78c86396d06a01f78885556397db15165b5b47bc0e07435984601b48c68c916770288c7b68df7e85b51a964052874e7401c85425cf5991a86226a38283a419b83255983b22888275e78853480a3334676276867394b68ac0975058801026e85b97936428e97924341a87ec6c93868350893ac07588459a8ed7e72b48ad70e8ed80f33f7885108261a872505922020e8587463a988d4682d344535011d55988d8e01ac7df8064837e85017806487f20af7081401f187b80931f7e97991ec7da7e17c25501868f48d72ed76a7fd8416c65b00770277ce8a713e85b6103f277362019d8b989644287a05002781b5eef181d5e372041f7625ba6c01a87b97ee55c05565b55413413770e8a97de7d582016b7ad5e95a268856a0711a398f8eb1e390c7b75e65096131e83ba6341b759504c1705f496d7a51dd8d914d5f291344619371787346d8533a962876d5f24e08aa7c294199053523d72381116273b8c47b756d5f37ce5ee2937b00625e83289f352153223d70c7309ee7824d175374a5c898a61172889977d8965ce27577b84340d7cf89f3f18479dc4f09d34f78e52d53676c016b7de5752850885af75922431181d50295473689f3d91b758570d4f09911f58097093be2f09e83287d72005377b24eb8fc75c2eb8b96ee51167c7035cb9b33ca8a47972ac7245b381e890ef8501e29f87236c38885cd5839456c65da95b6ad44c03984d83728988853116a04254e8fc1b47ec7cd5811a980898255a5301b59ee25a8df9f11484f787a06011e8317cf3b694b21e8099271627b00bb8964341a86556c51305ef5ee4f585985e7e850884552b9c651671852f68934285293017d9f204a5939885950296639234950c2a562ce4556845b851e9d2ad525b35b7556847e42a414590a05c113ac657b7776bf8358e51bd5eb52238a9281885d36fd244ace6363d41b65f396c68850171a6924d172f7ff83e7c914e9d85726e46f78967824d26301a986722668d902236a5259562942b7601e20d85d1a2031f7b88422e831f764a0563394552a7ef028d70235d2878a68a337a9634652236a778a01b95bc01e9c0a5a4678d58920cf8038b9ac9a647459a1ac3a785c27fd41f8de91452501f49e9595d27e82d17f0a72a556b17801e240f9ce8122b69992d17f98ec50ba587c995c6552df75c97a6e88b01249834006571141d88e88a41b65458336341e45d8a1c9d79dc16e8f07f35788125350250cdaf20edabd7cda019767587a61c5aac053ab56924bd58478dab00250ff7adaddacda950e20bdaf202fa8c51415a96815a3096946e195983a6595be96378915baf56cf91d50e7b476b21e89f55512d9a6491a4340033f5398dd48e72d2c3ae85b37be627a781f58439558a5633a9175285ca241250556eef77d22701478d8a59242839762711b721e012f85623e8c7aea6f31678fc9222a980e763b0b2f01e116267491d56172b5a95d1b4dad917d90aa8779014982e7baaf799941f7b00891b682283036e770a0b6c8aa38522647ba739896bcd5792d17397c31f89da66f6504b49d85e371021f7db51f3dba226d34b49e85bfa0bacb7ab6b915417988dad70fb22679ea409702398c26428ab9507283863462398905b38ec26e4b0b226d8429923b51396adf75b5078422553d527d9b6b18ac65c26c83f8a529e23d341a045962a527e20849c26b6ab75ae817a489152a7937a4642078113d7e2b301868c5b367601d88aa8f52b68649b6864ab3671bfd5ec72ba29efa1aa0282b3f6179aa6823a11ae41016eb66f87113d379149339ae85b886a45c07d9de6f760035c065bec70c87b9b113d72f7a01c2b528649f31486368bea5515f9eeb5f96976e404bb11219e1190caa68446b2289e97322ac7cd50a8924689e9452a451428018b95f2b675e187c5347a67aa9054dea14175a0699722160225a94a4b717c799bb75bba5c2a26b597267db2ab95a5950652864282f7bcae19d474c48da96ae1617ae88bcb8cb5211e9347cc994865178b2a5d86382e55deb379c6556a9e41e80aa6885c88788f93f6f2b89b2e7785e6b21155611bf61571678bfa428b001b97823ba7253eb29b2b5f47601aa98350dba34f82a4b9eb48653aef53633cb7bd65e5cb27553f7ce1b57aeb2f8ab965c028931cad3de948715417a896a11e56145706f21ab4c03e7b325dbb40187be4635209ba09debba3c8c385394253f31529d4cef8bb232c607f4b27ac7992b7468f8401e798dbe6cfdb015e246b276cd9b35ad8ad326613985358daf5a0f51f8538f075c2b69d64ec86daa710a32bbea995a339c5604a5282e91225165ca81bee7014d02801ecb6117cb2c6891b7ad913d7649cc94199367984016f9d3116b7a1df9fa5d41df770631a46c7553326f955b556dc527be86cf8a8b5c08da446c938830fca68b757e4df4dea1e47ecfa23015dbbd4ea2da911d1a8f786a0b3aa019c95591e44ca4f5f332885ef29154427e0c04cec2289a93462f7a99b7ac6611e88bb49ba514c9a01f8a72d6d1551a5a7a7d0176a989d791b3a7489760b1e9468b67adb12287c5f59ec1957b90a985a289d188e7a6176c65355cc8321ac2aac13279515889ea91bc96a410a9257e1202b5b61027dcf85d573bc954e0799c4551f75d6683a5c2b51f7d18d6850ba8c99bbc0918abcc1ad7d1a1595e20ca34b2a98019f1a2f9544c83b96b01e195fc70a7e4468edb9765ea57d0a6311e1dd855a880d25532189c389dd4eccfaad72b9da6624d4b8cfcd7c2aadf4e7dee9f75a27a1601117a56c17cae11948f6ce6723b65c966928ad9f57223dabbc619595706817d5655925126848786a29ef614125942670145988be017cb1a0bc4d7ba3de6532392b8fb436672b620037571e63f8f07b374c284a408003f59675fd287b462fca386288faad0532217ad3647bea89c4d527cbb6b352d3dbb242963c2c49a18ad649bc077a1b7483e7a48750030b90113b4ea5418dab39705b412bb649d69c998592ad1e2bfcb75cc796505a2f4a942684eac3121eecd7025aadb12591d6cc902dced6014d586c05286843942631a57d2347ec2930fcaeb0162a7b6681d8dde1c1ad7cb88388cf9cf776dab47e31fa40e4c8da721f7596c9604554ae366fd2933e8ab515cfe95f7653abaef90f550b17b4fcd3a0d4e6a85ab46f31e08bbccf952e9b671507c5babeddddef80136a15a764aa7fa91e40b7479722aab6ad803efdac9661916eb7918f13abc229cb1b68a1e9d69972aaa61a8edbbcb1f0cd06e05f82f0527606d8016785cbf9ea5ccc25ad42dd61298a2d4c2e69d544cca3e6e54ab774cc276a60e1576493a63a8f277cbb882cbe95b375f9307c3deba2b6c5ca6662e3226c5aceeb692702a1a1eaa4ebac7b882d7d49f4493edf58015b8fbdc11125ec88dcd5b595029b1199af7b69d2832212f3e0ab99149a98a3eb07998d7dbc0ac85281095a8dd8f5b9016a01a7cdd6aba98d1aba59cd3b9c27deec91179ad728e601dfe81928c75bbfba7b7c3d1c7fb8cd5966cbf07e2517931e1a50b244a809b3875be0f152141aefcc85a3f5acde4104572d7517083467a0b376b581cf41dfe54ecf8dd18fd819d2fae92784e1e2c86e2415ad3d8b16e0af07706365f3e757cf4db17d9a6692824348e15698a097d3b986da8638b361a8bd5366504a41c8af07716781dce31e78a23545f6eb941e0849d9501cede59b3d4ff859cad488f6da7c1e975a97d49c37462a65a7550894da975a63069cef8740a81d7579fe435df576bed7bde26c158c5ea66a8aeb7b1981fd85aeb6a0f8ced7345258b5f920c0ecc483554160668ad35d354afac07a01386f76476f7f91aafda7a8a68a03f93bd35008138f173017b5250728748ffed952050bf5452cf6c7f845af235545baf57c1188cf6af545e4efca456a0e35cbfdda8798eac3d025a8a30641cc017cf4af6f7337a33b45c70ff7728ff7967a9d5ab501ce72eaf357bf4aa462965e356180776c66cf6c7e837b5ff7afa19a2b6893d356ef001d74911b56ac49513565031624280aaf834e3f0bf444057a49582e3817268a98f0f4114388051224280294e84385055e2c2822712bc18827911389b2916dc79f2d523c6993d02c448b0d5ea42a70d8adc2a44d46a4c9a0362d458bc68efc4a03b4eccc9b2796140982f824d6af317a1d3a039a66ddaa358ad41bb211e050bd35567d0bb0796b53a06f564d8b1656aedaa37baa9d99157c65d0a68b03355a2891f36e973fd236ab27b62147b0499ed519027fe5ef52b857173e89497951d4c96db60d9ad3b85160c097ae168a43f53845d67d5fd48d84d86be09c371fc679725733dfacbb272cecc2783fcac52327f6dc3adaadc6e283a3f59b5bb13e6de97513472f393079de9475af2efd92bfec6fdd9d03b4ab297fa0d2b5a183df9e7990f95ae4e3cf2044feeb8fa04fbe8b4c4da207e3eaa7a0ba8bcf20bade13cac043dafa3e0f340d835f29a8d2abbf6c20e6c3da2db3fc7bf091ccca8affe4c3e04b9caa30f283be0abb1da3ee2934d8cb9beb27c6031d02b9f4041d6dbdc67302b4bccafbee07cafe746d093815e34255a709eaceee24a04bf1d7b60f838052c1d09c6f66c91f8c8caba5e8fb5c6b20d2f33f8742efbca452d5a5ec44fc2543d24b42bca396fc7cc83c07142daec7aebb707943c2f4dfe5c0ecd4947ac3ccd3bc0446fc5c1f62b823ccfc673ce8eb7eefabc63522f4da458cd0745d01c47c223847cb85b9283973f1d6b8c805c474c3072b6d83b10b6c405c3c013511574449ab02985fd4a404d0ca0335c1315fc67a61bad0ec7d26d64629ac907a5cfc05fe69485dc30deaacdc051556c53b5c67b6c5a0d45e2bc54dfaeb43d259adfbc23b6feba11f5957b4b7bcb7acfc12f0508bb538bdb15fe3c35ade2be5c7f16b5d4c8059b033e5dcaf5ae44dab8f5c012594fd488dbd66bb5e3d2e39d36471dba17a453555d43e2e2bd4a7395c511b4471e48dab693befcc59b5f21659571d29773d6b742051b51504a478cb83c4ca4dd8399e053058afa5cf8d4a33bee31dd9ad74503bd6f6940b79cdf24d95dfb4d6cc74d866a82e93314763de06704445c4b0765713dc5a8d580946457f5e57c6cbffbf47ade4fbcb7395b45ceaaf3eb77b3a5515e935d3c1fd16b8efc6ab365a3d67ec0c7fe1c44fa47acf9bd489ff5cb3f4ac3ceddecd32f46dc556a39c4f67579c1540b71fbee7ebe876d29e6f35856c56a7cb6e3f4044b9c682d869df151f047729947475e56396c5184147d3feea79d6f6a5d65f877a93be3bb14cb53cd9616ec7bc267f54ae93ed676fd9f463dfeef2325241e23654e291bd2831521416ea95ebb3f02eefcd7d828d0ed614b0af812e6958f20650dee4fe2c903f0975ca5c1c90e6bba80e2aea4124ee909c386b2b99a5ac4c0c4b0ede25e1ba813c2e6dc3dec374a66320b859a97e8b1b50ac28c821069c253c124a9b78b7234b6dcf8e6504ad9582278cb0254f2c6014d398034513b1a5f8e56fcbff06bc55fc2a71be646d9aef4c03d5cf1a220036859a9719e4c76bbcf520588263b818fc23a2c9590a4d56896e89e6b4cb31c19a0e21a96558ca88ab22c020b37184cc9a52d238ced031765c9281d6c6d5a49e2eefea5bfac953d6766a305d8bce456bcec8d6156c1da938417e33291af072ff214db0bd6e7a44ed09f40ebd3278ef823455642b18544bfd9cefef6fb4635fca179837f960dc221a1a1d2f794c2e89427474b1932bc0b7583cc1101f75a90e92359644ac9df03a8aca076fb4b55db6f87fc498342a12aa442f370a405d8829edd53738e89b2d9d095fa2ee4e0328502afdcc207cead35da2352c2fbd23f972ac4e86fc13d63e21bf656202d3a83755ce4ec14aa58cfc179dbca612b8325b8161b4f2ebda486f105259e19564a4660db50fb0bd52df3e6bee83ba6afd3e3d6e838f1d5654e6b5a3de5ac3f0646b69a9a4d5262a9d1d06953549dc0dd580342592759dd4532bf4d8dfa81a5c07744c4c5fd0565c473e43919c4b64a5c4d2492375b1de79c4fc557ac7773971857a4bb4b317da98714dc8a68666ef9c1aa7d4b877417d70369e4c5e19e29a61520945d845e2bf8d5f677f3be9757744d1d850d8fa5156454f63a60458adea07e51819bb6985f397acfa16fda2a8d1d58a0b3e9537b7295ea20d6c956326abc054da3035a1ba8e03f89cc84b1a5db8239e724d7bee43391657da9d6a876d28d2d4fae2341e045696f99ed2dc4a98cd158ec192b5c3e929448c57a9e6cf950a51995dba58adb9e3f8863405911b5b41d05ae2d5af75c820e4a8d72cad005740e94d11faca42c11117887964b5a121d9bbc67aa2fd97b582238cf7fa5236ac034e94a1e0fa49d7cfe6059ba3daf0a9cc0938d7a59645bf542be339f632bfcac7767e523e17d47894b061d3dbb991e36e917c84c055175ecaa77c729f595c95d403361673e2f0661d152fc08a7876961c726481b554625a09b170c9ac6879eaa36901a5da7e9b8d5fcef4e6908000129f4010a000ff00c2000000000910f4000080ef0059d2318ac80e04385070e1458909022c78c012a3c884172a5c5871b126cd8a1b3a44e8f1d365409325466c0982b46ac39a2b52bc794216a9c894376adc595317adc564c4021b18f35951b283497af40a3078a05f974595055a54b72f44ab479a1d9ae4392156a85f9e6dba14dba559a165be8d6a263a2a53ba6bb2b5ea56ba6bd8b051e25dab06fee752ba7fcab59b673b20ecb281f2fd2cb77de0e3c96307362cf891fb58c395277468891166edca9b337efce93438e1d2ab439e3d6a353ae5daab53be7dea363ce9d2bb63d60d5c4befcddb478ee63a34d7f4de91c3b2fe2efb98f2d4edbd830f5e3cb93374e1d9af178e7d587677eac5bf37fedd9befb4fae8dfbb87be6e7a79f0fae1cf8fdedefcfaf7f9e9cbb74fcedebcfbf3f1f3dfcf25514a3d08e25e450ed4702182392860e2890e38e0648d0e4880a4851258c0e58a166841975a5d78655885498840d88626988228872aa892298c2eb8e26c8b2ac8d2ec8636d8832c873ae8932d8c3ef8e3609b3a09d3e09646198420933265f7954126057555585d39a0508a4d49322496562414159c5949d5669552a8d497915e5916214a529985aa936a95d62557627970989f52a957ab9772d9f59063769967ef917af9b520aa7a0a96ac958e0ab62c99821ac6e3ad8289976e9805e6e1e6801268b9a6a616680a67a1ae7a2a69a4ae9ac92aae96aa93d8855e14efa9978e5545a51da361655c1ea7beda3b6359bacaabadafbe78fb5371cafa745fa7caea3c5da8ca0b9ca3bbc20bac65b4ce4b2d25b9de6bcb27b3c67b6ca5b0ee7b4e64b1ea7b6e69bea6371ba49aae8acaeaa2f2cb3fa9a1f2db8fadb5febbaf6ebf2d5947679c01f76ed954d1475e126cc5474e5e51e1bb707d5ed9372e9b57dd3750ba511b2cf79b7c0f5cc7d3c5cd8708d4c5ce2c5618c60f2642b0790b7582b3ce7d670132c2135c72f7c849aca179cd09da926087f6fb443fb64f0d74feb84f2da473def23d0fa0c6057935fba8c2ab7deea5e66d0d24bc5f3b75b6d0633b2636be220b7ee9df5b7d56b8bb22adb57bd85bcd96fbdb678de5bbd14fefdd467edcda26b0d23c86784390de920cc9a4d81e8891249baa1ea022ea9a2eb123ed9a3ec024e01a4e4025e30a5e6126ef0a3ef66f4735b5e3359cb57c83f8932fc581f6993bfc2653c29dae96abc685dcb3356f2bbec2bde82ece737dea2b5c485bc98dbee62eea7dce91bd5acdc94cf65ab70c337fe7892f9db3432366c3dde0571d3e72df4b3d4e3af6e7af7e7bfce73ba1d2c5ad6d5cadadc627fa2ad7f3cf0fbdf8f71bdfb6acef0085f310eff89450440e003f795b50a69895f0c306abc08b0c90a2052810cb0eefc2811cd0660b388f3e0230348f1c11660f76b51fc4fe2443b12d5ca643e24cc4c0ba62a991a5de3363410a76278c4ad12c0f78ef534022e0588e3c02a1178874c22221798a4c62e66878619571344c22110cc57ca881943954256f5203d61776d5443d71d83164e2d81177ed3336611c8152f2ea19c8d6413eb11d869a632558e8924b3a060f8e6c680713e8a64f32b1304d74d31f15e8284832121196840b4a11e26c2e35ea2e76b28227680881994221fc66a970606a42a0c0b586c3946bcc0e82c6b9c7b572f68781052923353a465288c49c224561193924c649b0f5841c015c2578f241d1a0917d998b061779234b3295eb44bc679321321a9ba1121a9c118d5519a97810d53312915a66ac09b9d0986240d944dc0a9e0bc9319c6664a22cd43c182bd94ecec8433e9911b6e84e720aef892da13f90b458cdc29980935082241c72ddc311736db5b4e0965471f566681a7d2776a1b488c44696b243ffc491241e7dba57a75af035892c20a00500e3473f1201507dd3d0aa2dec464992254e3084f50d703792be233ea465c2db21a0e3c412b0508504d4f340a00920558a9e43b044c879493a2259d4a72755e72c9d29ffd53d328e95943f036835e8c57489c110e9bcc1465567685138ac80583538ab0850c4d8462ec7be1ca622651cca3f58c78710b538ad70fc5442bae29daaf9a121a871c84f0b508a9605a0bd6d0a2f570b275066548f0e8d504a0e4abb49cd3496702aa767b6b74bc9e5805b93ccda4205e9a33c32768977db27ea0b83871aefaa91d0b35056892af042d924f0ba9b74e8655d16fc4f822fc893092c656d4ab550de25f3bd9d59a0807bd851a2431abe8d1aed4fb886be3447b0082a311b0506dac4d013e4140d62196cbb25ceaaadeea99cdb5c5da6bb24d405a6a6fb2dca7d8bf206ac92e500a87b63015b93ac12f2b49011354979d5ad57c2143db303235a713a1da5d905e020dd196f7b7890e192143e9bc8afab614168d0aeb0cca79241ef531339156c4109bcbc44d2ac1c682a45cf095436d3eee25c25b0ed06c7232ee8813df7ce4dbe2047be090582a8d95715c83457c0430d506492358e34859f078d7a6c9e5c591b417e833601ace165aca72f27b51cc0d2f1b3bad202e500eff7944fdb28226ee982535c2061cbb2a1a440570d4603a879a16da17413425fd217987918b5fb80a19cd4905436b6b35298c96f685c483df9f420bd0982abfb67ac072639a621c37835a817174ada43dc707862838a5ae666e602bd7eb4ea4d179953719d4fa8cd73eab25ade5ef924b22d3b58864b3292ddb903b7d6865608264a7053cd57912e4dade15695ec4cc11bd7db24ba96239a171db299dd47ce3c2f1ead8b631362dd52963b67b9fa97a1a47b74aa853fc640d619992eb9cfb0350075354af4d70f941bd13108503d59a29633f2d1dafc09cba6fb32d48e0ad3bad11960598c0b2ed29bddcffef5694ef8a91c77aabf44dd9337a9fce752766aefcf6ac8a0710e2c801cda28ded317bf25bd08ccc5c6f12419f44ccac49174d4cacb329fc9eb2fa7fc0e1edaeaabb559054f168a3332a300502fd6962b1d8d24e204b75576e548447f50db2f4f5ba6e214e476ac8247661a0a1ac5dddd69c7fa8c5c312c6ae594da48286e1319847c5ac171dea7b10aa491e95c21664fa9374e8ed49e3816bda78d92c181421a078b5879c36209636f5024e82f1e5dbd78c24dc79202d204e773230da9214e4135012f1635095035079733e3d3c24ef1ed7049b762dcc651b3d579cac8aca3bdb9c79bde418da24e71449f3d055c883e54c58f6dbc94330a0c770515e579c03255120a8c244d5dcb2e95e34ede09f6be41a6ef012d19afe9f9af92932673ec01397bb7a9241b4a04a8a1aff2f1529fa879a7144bbf2099af47af358354203fa1d55376124a477451287325697b014564084760b57f77772016a02a7c864c0335b86e310459506f71f7985ec3577197797bc07085009505e5171a87325500cd7b26476cf34c58f4747ec7435747c70405f57501bb7366311cf7028e774a39c13089856a07529c7ed7228081d38aa71258500663017c65d5501585f20b16bc01d7595847ad1527387500850977fc5aa7847b917e62d58030a0358e257643475c5126c08401868145241287454a96f206a7485126b75595907801a87d58cb1978611a65595500b06266f85a488f7201350850ef7d7b65950607538fc7922978243838556f78c86396d06a01f78885556397db15165b5b47bc0e07435984601b48c68c916770288c7b68df7e85b51a964052874e7401c85425cf5991a86226a38283a419b83255983b22888275e78853480a3334676276867394b68ac0975058801026e85b97936428e97924341a87ec6c93868350893ac07588459a8ed7e72b48ad70e8ed80f33f7885108261a872505922020e8587463a988d4682d344535011d55988d8e01ac7df8064837e85017806487f20af7081401f187b80931f7e97991ec7da7e17c25501868f48d72ed76a7fd8416c65b00770277ce8a713e85b6103f277362019d8b989644287a05002781b5eef181d5e372041f7625ba6c01a87b97ee55c05565b55413413770e8a97de7d582016b7ad5e95a268856a0711a398f8eb1e390c7b75e65096131e83ba6341b759504c1705f496d7a51dd8d914d5f291344619371787346d8533a962876d5f24e08aa7c294199053523d72381116273b8c47b756d5f37ce5ee2937b00625e83289f352153223d70c7309ee7824d175374a5c898a61172889977d8965ce27577b84340d7cf89f3f18479dc4f09d34f78e52d53676c016b7de5752850885af75922431181d50295473689f3d91b758570d4f09911f58097093be2f09e83287d72005377b24eb8fc75c2eb8b96ee51167c7035cb9b33ca8a47972ac7245b381e890ef8501e29f87236c38885cd5839456c65da95b6ad44c03984d83728988853116a04254e8fc1b47ec7cd5811a980898255a5301b59ee25a8df9f11484f787a06011e8317cf3b694b21e8099271627b00bb8964341a86556c51305ef5ee4f585985e7e850884552b9c651671852f68934285293017d9f204a5939885950296639234950c2a562ce4556845b851e9d2ad525b35b7556847e42a414590a05c113ac657b7776bf8358e51bd5eb52238a9281885d36fd244ace6363d41b65f396c68850171a6924d172f7ff83e7c914e9d85726e46f78967824d26301a986722668d902236a5259562942b7601e20d85d1a2031f7b88422e831f764a0563394552a7ef028d70235d2878a68a337a9634652236a778a01b95bc01e9c0a5a4678d58920cf8038b9ac9a647459a1ac3a785c27fd41f8de91452501f49e9595d27e82d17f0a72a556b17801e240f9ce8122b69992d17f98ec50ba587c995c6552df75c97a6e88b01249834006571141d88e88a41b65458336341e45d8a1c9d79dc16e8f07f35788125350250cdaf20edabd7cda019767587a61c5aac053ab56924bd58478dab00250ff7adaddacda950e20bdaf202fa8c51415a96815a3096946e195983a6595be96378915baf56cf91d50e7b476b21e89f55512d9a6491a4340033f5398dd48e72d2c3ae85b37be627a781f58439558a5633a9175285ca241250556eef77d22701478d8a59242839762711b721e012f85623e8c7aea6f31678fc9222a980e763b0b2f01e116267491d56172b5a95d1b4dad917d90aa8779014982e7baaf799941f7b00891b682283036e770a0b6c8aa38522647ba739896bcd5792d17397c31f89da66f6504b49d85e371021f7db51f3dba226d34b49e85bfa0bacb7ab6b915417988dad70fb22679ea409702398c26428ab9507283863462398905b38ec26e4b0b226d8429923b51396adf75b5078422553d527d9b6b18ac65c26c83f8a529e23d341a045962a527e20849c26b6ab75ae817a489152a7937a4642078113d7e2b301868c5b367601d88aa8f52b68649b6864ab3671bfd5ec72ba29efa1aa0282b3f6179aa6823a11ae41016eb66f87113d379149339ae85b886a45c07d9de6f760035c065bec70c87b9b113d72f7a01c2b528649f31486368bea5515f9eeb5f96976e404bb11219e1190caa68446b2289e97322ac7cd50a8924689e9452a451428018b95f2b675e187c5347a67aa9054dea14175a0699722160225a94a4b717c799bb75bba5c2a26b597267db2ab95a5950652864282f7bcae19d474c48da96ae1617ae88bcb8cb5211e9347cc994865178b2a5d86382e55deb379c6556a9e41e80aa6885c88788f93f6f2b89b2e7785e6b21155611bf61571678bfa428b001b97823ba7253eb29b2b5f47601aa98350dba34f82a4b9eb48653aef53633cb7bd65e5cb27553f7ce1b57aeb2f8ab965c028931cad3de948715417a896a11e56145706f21ab4c03e7b325dbb40187be4635209ba09debba3c8c385394253f31529d4cef8bb232c607f4b27ac7992b7468f8401e798dbe6cfdb015e246b276cd9b35ad8ad326613985358daf5a0f51f8538f075c2b69d64ec86daa710a32bbea995a339c5604a5282e91225165ca81bee7014d02801ecb6117cb2c6891b7ad913d7649cc94199367984016f9d3116b7a1df9fa5d41df770631a46c7553326f955b556dc527be86cf8a8b5c08da446c938830fca68b757e4df4dea1e47ecfa23015dbbd4ea2da911d1a8f786a0b3aa019c95591e44ca4f5f332885ef29154427e0c04cec2289a93462f7a99b7ac6611e88bb49ba514c9a01f8a72d6d1551a5a7a7d0176a989d791b3a7489760b1e9468b67adb12287c5f59ec1957b90a985a289d188e7a6176c65355cc8321ac2aac13279515889ea91bc96a410a9257e1202b5b61027dcf85d573bc954e0799c4551f75d6683a5c2b51f7d18d6850ba8c99bbc0918abcc1ad7d1a1595e20ca34b2a98019f1a2f9544c83b96b01e195fc70a7e4468edb9765ea57d0a6311e1dd855a880d25532189c389dd4eccfaad72b9da6624d4b8cfcd7c2aadf4e7dee9f75a27a1601117a56c17cae11948f6ce6723b65c966928ad9f57223dabbc619595706817d5655925126848786a29ef614125942670145988be017cb1a0bc4d7ba3de6532392b8fb436672b620037571e63f8f07b374c284a408003f59675fd287b462fca386288faad0532217ad3647bea89c4d527cbb6b352d3dbb242963c2c49a18ad649bc077a1b7483e7a48750030b90113b4ea5418dab39705b412bb649d69c998592ad1e2bfcb75cc796505a2f4a942684eac3121eecd7025aadb12591d6cc902dced6014d586c05286843942631a57d2347ec2930fcaeb0162a7b6681d8dde1c1ad7cb88388cf9cf776dab47e31fa40e4c8da721f7596c9604554ae366fd2933e8ab515cfe95f7653abaef90f550b17b4fcd3a0d4e6a85ab46f31e08bbccf952e9b671507c5babeddddef80136a15a764aa7fa91e40b7479722aab6ad803efdac9661916eb7918f13abc229cb1b68a1e9d69972aaa61a8edbbcb1f0cd06e05f82f0527606d8016785cbf9ea5ccc25ad42dd61298a2d4c2e69d544cca3e6e54ab774cc276a60e1576493a63a8f277cbb882cbe95b375f9307c3deba2b6c5ca6662e3226c5aceeb692702a1a1eaa4ebac7b882d7d49f4493edf58015b8fbdc11125ec88dcd5b595029b1199af7b69d2832212f3e0ab99149a98a3eb07998d7dbc0ac85281095a8dd8f5b9016a01a7cdd6aba98d1aba59cd3b9c27deec91179ad728e601dfe81928c75bbfba7b7c3d1c7fb8cd5966cbf07e2517931e1a50b244a809b3875be0f152141aefcc85a3f5acde4104572d7517083467a0b376b581cf41dfe54ecf8dd18fd819d2fae92784e1e2c86e2415ad3d8b16e0af07706365f3e757cf4db17d9a6692824348e15698a097d3b986da8638b361a8bd5366504a41c8af07716781dce31e78a23545f6eb941e0849d9501cede59b3d4ff859cad488f6da7c1e975a97d49c37462a65a7550894da975a63069cef8740a81d7579fe435df576bed7bde26c158c5ea66a8aeb7b1981fd85aeb6a0f8ced7345258b5f920c0ecc483554160668ad35d354afac07a01386f76476f7f91aafda7a8a68a03f93bd35008138f173017b5250728748ffed952050bf5452cf6c7f845af235545baf57c1188cf6af545e4efca456a0e35cbfdda8798eac3d025a8a30641cc017cf4af6f7337a33b45c70ff7728ff7967a9d5ab501ce72eaf357bf4aa462965e356180776c66cf6c7e837b5ff7afa19a2b6893d356ef001d74911b56ac49513565031624280aaf834e3f0bf444057a49582e3817268a98f0f4114388051224280294e84385055e2c2822712bc18827911389b2916dc79f2d523c6993d02c448b0d5ea42a70d8adc2a44d46a4c9a0362d458bc68efc4a03b4eccc9b2796140982f824d6af317a1d3a039a66ddaa358ad41bb211e050bd35567d0bb0796b53a06f564d8b1656aedaa37baa9d99157c65d0a68b03355a2891f36e973fd236ab27b62147b0499ed519027fe5ef52b857173e89497951d4c96db60d9ad3b85160c097ae168a43f53845d67d5fd48d84d86be09c371fc679725733dfacbb272cecc2783fcac52327f6dc3adaadc6e283a3f59b5bb13e6de97513472f393079de9475af2efd92bfec6fdd9d03b4ab297fa0d2b5a183df9e7990f95ae4e3cf2044feeb8fa04fbe8b4c4da207e3eaa7a0ba8bcf20bade13cac043dafa3e0f340d835f29a8d2abbf6c20e6c3da2db3fc7bf091ccca8affe4c3e04b9caa30f283be0abb1da3ee2934d8cb9beb27c6031d02b9f4041d6dbdc67302b4bccafbee07cafe746d093815e34255a709eaceee24a04bf1d7b60f838052c1d09c6f66c91f8c8caba5e8fb5c6b20d2f33f8742efbca452d5a5ec44fc2543d24b42bca396fc7cc83c07142daec7aebb707943c2f4dfe5c0ecd4947ac3ccd3bc0446fc5c1f62b823ccfc673ce8eb7eefabc63522f4da458cd0745d01c47c223847cb85b9283973f1d6b8c805c474c3072b6d83b10b6c405c3c013511574449ab02985fd4a404d0ca0335c1315fc67a61bad0ec7d26d64629ac907a5cfc05fe69485dc30deaacdc051556c53b5c67b6c5a0d45e2bc54dfaeb43d259adfbc23b6feba11f5957b4b7bcb7acfc12f0508bb538bdb15fe3c35ade2be5c7f16b5d4c8059b033e5dcaf5ae44dab8f5c012594fd488dbd66bb5e3d2e39d36471dba17a453555d43e2e2bd4a7395c511b4471e48dab693befcc59b5f21659571d29773d6b742051b51504a478cb83c4ca4dd8399e053058afa5cf8d4a33bee31dd9ad74503bd6f6940b79cdf24d95dfb4d6cc74d866a82e93314763de06704445c4b0765713dc5a8d580946457f5e57c6cbffbf47ade4fbcb7395b45ceaaf3eb77b3a5515e935d3c1fd16b8efc6ab365a3d67ec0c7fe1c44fa47acf9bd489ff5cb3f4ac3ceddecd32f46dc556a39c4f67579c1540b71fbee7ebe876d29e6f35856c56a7cb6e3f4044b9c682d869df151f047729947475e56396c5184147d3feea79d6f6a5d65f877a93be3bb14cb53cd9616ec7bc267f54ae93ed676fd9f463dfeef2325241e23654e291bd2831521416ea95ebb3f02eefcd7d828d0ed614b0af812e6958f20650dee4fe2c903f0975ca5c1c90e6bba80e2aea4124ee909c386b2b99a5ac4c0c4b0ede25e1ba813c2e6dc3dec374a66320b859a97e8b1b50ac28c821069c253c124a9b78b7234b6dcf8e6504ad9582278cb0254f2c6014d398034513b1a5f8e56fcbff06bc55fc2a71be646d9aef4c03d5cf1a220036859a9719e4c76bbcf520588263b818fc23a2c9590a4d56896e89e6b4cb31c19a0e21a96558ca88ab22c020b37184cc9a52d238ced031765c9281d6c6d5a49e2eefea5bfac953d6766a305d8bce456bcec8d6156c1da938417e33291af072ff214db0bd6e7a44ed09f40ebd3278ef823455642b18544bfd9cefef6fb4635fca179837f960dc221a1a1d2f794c2e89427474b1932bc0b7583cc1101f75a90e92359644ac9df03a8aca076fb4b55db6f87fc498342a12aa442f370a405d8829edd53738e89b2d9d095fa2ee4e0328502afdcc207cead35da2352c2fbd23f972ac4e86fc13d63e21bf656202d3a83755ce4ec14aa58cfc179dbca612b8325b8161b4f2ebda486f105259e19564a4660db50fb0bd52df3e6bee83ba6afd3e3d6e838f1d5654e6b5a3de5ac3f0646b69a9a4d5262a9d1d06953549dc0dd580342592759dd4532bf4d8dfa81a5c07744c4c5fd0565c473e43919c4b64a5c4d2492375b1de79c4fc557ac7773971857a4bb4b317da98714dc8a68666ef9c1aa7d4b877417d70369e4c5e19e29a61520945d845e2bf8d5f677f3be9757744d1d850d8fa5156454f63a60458adea07e51819bb6985f397acfa16fda2a8d1d58a0b3e9537b7295ea20d6c956326abc054da3035a1ba8e03f89cc84b1a5db8239e724d7bee43391657da9d6a876d28d2d4fae2341e045696f99ed2dc4a98cd158ec192b5c3e929448c57a9e6cf950a51995dba58adb9e3f8863405911b5b41d05ae2d5af75c820e4a8d72cad005740e94d11faca42c11117887964b5a121d9bbc67aa2fd97b582238cf7fa5236ac034e94a1e0fa49d7cfe6059ba3daf0a9cc0938d7a59645bf542be339f632bfcac7767e523e17d47894b061d3dbb991e36e917c84c055175ecaa77c729f595c95d403361673e2f0661d152fc08a7876961c726481b554625a09b170c9ac6879eaa36901a5da7e9b8d5fcef4e6908000129f4010a000ff00c2000000000910f4000080ef0059d2318ac80e04385070e1458909022c78c012a3c884172a5c5871b126cd8a1b3a44e8f1d365409325466c0982b46ac39a2b52bc794216a9c894376adc595317adc564c4021b18f35951b283497af40a3078a05f974595055a54b72f44ab479a1d9ae4392156a85f9e6dba14dba559a165be8d6a263a2a53ba6bb2b5ea56ba6bd8b051e25dab06fee752ba7fcab59b673b20ecb281f2fd2cb77de0e3c96307362cf891fb58c395277468891166edca9b337efce93438e1d2ab439e3d6a353ae5daab53be7dea363ce9d2bb63d60d5c4befcddb478ee63a34d7f4de91c3b2fe2efb98f2d4edbd830f5e3cb93374e1d9af178e7d587677eac5bf37fedd9befb4fae8dfbb87be6e7a79f0fae1cf8fdedefcfaf7f9e9cbb74fcedebcfbf3f1f3dfcf25514a3d08e25e450ed4702182392860e2890e38e0648d0e4880a4851258c0e58a166841975a5d78655885498840d88626988228872aa892298c2eb8e26c8b2ac8d2ec8636d8832c873ae8932d8c3ef8e3609b3a09d3e09646198420933265f7954126057555585d39a0508a4d49322496562414159c5949d5669552a8d497915e5916214a529985aa936a95d62557627970989f52a957ab9772d9f59063769967ef917af9b520aa7a0a96ac958e0ab62c99821ac6e3ad8289976e9805e6e1e6801268b9a6a616680a67a1ae7a2a69a4ae9ac92aae96aa93d8855e14efa9978e5545a51da361655c1ea7beda3b6359bacaabadafbe78fb5371cafa745fa7caea3c5da8ca0b9ca3bbc20bac65b4ce4b2d25b9de6bcb27b3c67b6ca5b0ee7b4e64b1ea7b6e69bea6371ba49aae8acaeaa2f2cb3fa9a1f2db8fadb5febbaf6ebf2d5947679c01f76ed954d1475e126cc5474e5e51e1bb707d5ed9372e9b57dd3750ba511b2cf79b7c0f5cc7d3c5cd8708d4c5ce2c5618c60f2642b0790b7582b3ce7d670132c2135c72f7c849aca179cd09da926087f6fb443fb64f0d74feb84f2da473def23d0fa0c6057935fba8c2ab7deea5e66d0d24bc5f3b75b6d0633b2636be220b7ee9df5b7d56b8bb22adb57bd85bcd96fbdb678de5bbd14fefdd467edcda26b0d23c86784390de920cc9a4d81e8891249baa1ea022ea9a2eb123ed9a3ec024e01a4e4025e30a5e6126ef0a3ef66f4735b5e3359cb57c83f8932fc581f6993bfc2653c29dae96abc685dcb3356f2bbec2bde82ece737dea2b5c485bc98dbee62eea7dce91bd5acdc94cf65ab70c337fe7892f9db3432366c3dde0571d3e72df4b3d4e3af6e7af7e7bfce73ba1d2c5ad6d5cadadc627fa2ad7f3cf0fbdf8f71bdfb6acef0085f310eff89450440e003f795b50a69895f0c306abc08b0c90a2052810cb0eefc2811cd0660b388f3e0230348f1c11660f76b51fc4fe2443b12d5ca643e24cc4c0ba62a991a5de3363410a76278c4ad12c0f78ef534022e0588e3c02a1178874c22221798a4c62e66878619571344c22110cc57ca881943954256f5203d61776d5443d71d83164e2d81177ed3336611c8152f2ea19c8d6413eb11d869a632558e8924b3a060f8e6c680713e8a64f32b1304d74d31f15e8284832121196840b4a11e26c2e35ea2e76b28227680881994221fc66a970606a42a0c0b586c3946bcc0e82c6b9c7b572f68781052923353a465288c49c224561193924c649b0f5841c015c2578f241d1a0917d998b061779234b3295eb44bc679321321a9ba1121a9c118d5519a97810d53312915a66ac09b9d0986240d944dc0a9e0bc9319c6664a22cd43c182bd94ecec8433e9911b6e84e720aef892da13f90b458cdc29980935082241c72ddc311736db5b4e0965471f566681a7d2776a1b488c44696b243ffc491241e7dba57a75af035892c20a00500e3473f1201507dd3d0aa2dec464992254e3084f50d703792be233ea465c2db21a0e3c412b0508504d4f340a00920558a9e43b044c879493a2259d4a72755e72c9d29ffd53d328e95943f036835e8c57489c110e9bcc1465567685138ac80583538ab0850c4d8462ec7be1ca622651cca3f58c78710b538ad70fc5442bae29daaf9a121a871c84f0b508a9605a0bd6d0a2f570b275066548f0e8d504a0e4abb49cd3496702aa767b6b74bc9e5805b93ccda4205e9a33c32768977db27ea0b83871aefaa91d0b35056892af042d924f0ba9b74e8655d16fc4f822fc893092c656d4ab550de25f3bd9d59a0807bd851a2431abe8d1aed4fb886be3447b0082a311b0506dac4d013e4140d62196cbb25ceaaadeea99cdb5c5da6bb24d405a6a6fb2dca7d8bf206ac92e500a87b63015b93ac12f2b49011354979d5ad57c2143db303235a713a1da5d905e020dd196f7b7890e192143e9bc8afab614168d0aeb0cca79241ef531339156c4109bcbc44d2ac1c682a45cf095436d3eee25c25b0ed06c7232ee8813df7ce4dbe2047be090582a8d95715c83457c0430d506492358e34859f078d7a6c9e5c591b417e833601ace165aca72f27b51cc0d2f1b3bad202e500eff7944fdb28226ee982535c2061cbb2a1a440570d4603a879a16da17413425fd217987918b5fb80a19cd4905436b6b35298c96f685c483df9f420bd0982abfb67ac072639a621c37835a817174ada43dc707862838a5ae666e602bd7eb4ea4d179953719d4fa8cd73eab25ade5ef924b22d3b58864b3292ddb903b7d6865608264a7053cd57912e4dade15695ec4cc11bd7db24ba96239a171db299dd47ce3c2f1ead8b631362dd52963b67b9fa97a1a47b74aa853fc640d619992eb9cfb0350075354af4d70f941bd13108503d59a29633f2d1dafc09cba6fb32d48e0ad3bad11960598c0b2ed29bddcffef5694ef8a91c77aabf44dd9337a9fce752766aefcf6ac8a0710e2c801cda28ded317bf25bd08ccc5c6f12419f44ccac49174d4cacb329fc9eb2fa7fc0e1edaeaabb559054f168a3332a300502fd6962b1d8d24e204b75576e548447f50db2f4f5ba6e214e476ac8247661a0a1ac5dddd69c7fa8c5c312c6ae594da48286e1319847c5ac171dea7b10aa491e95c21664fa9374e8ed49e3816bda78d92c181421a078b5879c36209636f5024e82f1e5dbd78c24dc79202d204e773230da9214e4135012f1635095035079733e3d3c24ef1ed7049b762dcc651b3d579cac8aca3bdb9c79bde418da24e71449f3d055c883e54c58f6dbc94330a0c770515e579c03255120a8c244d5dcb2e95e34ede09f6be41a6ef012d19afe9f9af92932673ec01397bb7a9241b4a04a8a1aff2f1529fa879a7144bbf2099af47af358354203fa1d55376124a477451287325697b014564084760b57f77772016a02a7c864c0335b86e310459506f71f7985ec3577197797bc07085009505e5171a87325500cd7b26476cf34c58f4747ec7435747c70405f57501bb7366311cf7028e774a39c13089856a07529c7ed7228081d38aa71258500663017c65d5501585f20b16bc01d7595847ad1527387500850977fc5aa7847b917e62d58030a0358e257643475c5126c08401868145241287454a96f206a7485126b75595907801a87d58cb1978611a65595500b06266f85a488f7201350850ef7d7b65950607538fc7922978243838556f78c86396d06a01f78885556397db15165b5b47bc0e07435984601b48c68c916770288c7b68df7e85b51a964052874e7401c85425cf5991a86226a38283a419b83255983b22888275e78853480a3334676276867394b68ac0975058801026e85b97936428e97924341a87ec6c93868350893ac07588459a8ed7e72b48ad70e8ed80f33f7885108261a872505922020e8587463a988d4682d344535011d55988d8e01ac7df8064837e85017806487f20af7081401f187b80931f7e97991ec7da7e17c25501868f48d72ed76a7fd8416c65b00770277ce8a713e85b6103f277362019d8b989644287a05002781b5eef181d5e372041f7625ba6c01a87b97ee55c05565b55413413770e8a97de7d582016b7ad5e95a268856a0711a398f8eb1e390c7b75e65096131e83ba6341b759504c1705f496d7a51dd8d914d5f291344619371787346d8533a962876d5f24e08aa7c294199053523d72381116273b8c47b756d5f37ce5ee2937b00625e83289f352153223d70c7309ee7824d175374a5c898a61172889977d8965ce27577b84340d7cf89f3f18479dc4f09d34f78e52d53676c016b7de5752850885af75922431181d50295473689f3d91b758570d4f09911f58097093be2f09e83287d72005377b24eb8fc75c2eb8b96ee51167c7035cb9b33ca8a47972ac7245b381e890ef8501e29f87236c38885cd5839456c65da95b6ad44c03984d83728988853116a04254e8fc1b47ec7cd5811a980898255a5301b59ee25a8df9f11484f787a06011e8317cf3b694b21e8099271627b00bb8964341a86556c51305ef5ee4f585985e7e850884552b9c651671852f68934285293017d9f204a5939885950296639234950c2a562ce4556845b851e9d2ad525b35b7556847e42a414590a05c113ac657b7776bf8358e51bd5eb52238a9281885d36fd244ace6363d41b65f396c68850171a6924d172f7ff83e7c914e9d85726e46f78967824d26301a986722668d902236a5259562942b7601e20d85d1a2031f7b88422e831f764a0563394552a7ef028d70235d2878a68a337a9634652236a778a01b95bc01e9c0a5a4678d58920cf8038b9ac9a647459a1ac3a785c27fd41f8de91452501f49e9595d27e82d17f0a72a556b17801e240f9ce8122b69992d17f98ec50ba587c995c6552df75c97a6e88b01249834006571141d88e88a41b65458336341e45d8a1c9d79dc16e8f07f35788125350250cdaf20edabd7cda019767587a61c5aac053ab56924bd58478dab00250ff7adaddacda950e20bdaf202fa8c51415a96815a3096946e195983a6595be96378915baf56cf91d50e7b476b21e89f55512d9a6491a4340033f5398dd48e72d2c3ae85b37be627a781f58439558a5633a9175285ca241250556eef77d22701478d8a59242839762711b721e012f85623e8c7aea6f31678fc9222a980e763b0b2f01e116267491d56172b5a95d1b4dad917d90aa8779014982e7baaf799941f7b00891b682283036e770a0b6c8aa38522647ba739896bcd5792d17397c31f89da66f6504b49d85e371021f7db51f3dba226d34b49e85bfa0bacb7ab6b915417988dad70fb22679ea409702398c26428ab9507283863462398905b38ec26e4b0b226d8429923b51396adf75b5078422553d527d9b6b18ac65c26c83f8a529e23d341a045962a527e20849c26b6ab75ae817a489152a7937a4642078113d7e2b301868c5b367601d88aa8f52b68649b6864ab3671bfd5ec72ba29efa1aa0282b3f6179aa6823a11ae41016eb66f87113d379149339ae85b886a45c07d9de6f760035c065bec70c87b9b113d72f7a01c2b528649f31486368bea5515f9eeb5f96976e404bb11219e1190caa68446b2289e97322ac7cd50a8924689e9452a451428018b95f2b675e187c5347a67aa9054dea14175a0699722160225a94a4b717c799bb75bba5c2a26b597267db2ab95a5950652864282f7bcae19d474c48da96ae1617ae88bcb8cb5211e9347cc994865178b2a5d86382e55deb379c6556a9e41e80aa6885c88788f93f6f2b89b2e7785e6b21155611bf61571678bfa428b001b97823ba7253eb29b2b5f47601aa98350dba34f82a4b9eb48653aef53633cb7bd65e5cb27553f7ce1b57aeb2f8ab965c028931cad3de948715417a896a11e56145706f21ab4c03e7b325dbb40187be4635209ba09debba3c8c385394253f31529d4cef8bb232c607f4b27ac7992b7468f8401e798dbe6cfdb015e246b276cd9b35ad8ad326613985358daf5a0f51f8538f075c2b69d64ec86daa710a32bbea995a339c5604a5282e91225165ca81bee7014d02801ecb6117cb2c6891b7ad913d7649cc94199367984016f9d3116b7a1df9fa5d41df770631a46c7553326f955b556dc527be86cf8a8b5c08da446c938830fca68b757e4df4dea1e47ecfa23015dbbd4ea2da911d1a8f786a0b3aa019c95591e44ca4f5f332885ef29154427e0c04cec2289a93462f7a99b7ac6611e88bb49ba514c9a01f8a72d6d1551a5a7a7d0176a989d791b3a7489760b1e9468b67adb12287c5f59ec1957b90a985a289d188e7a6176c65355cc8321ac2aac13279515889ea91bc96a410a9257e1202b5b61027dcf85d573bc954e0799c4551f75d6683a5c2b51f7d18d6850ba8c99bbc0918abcc1ad7d1a1595e20ca34b2a98019f1a2f9544c83b96b01e195fc70a7e4468edb9765ea57d0a6311e1dd855a880d25532189c389dd4eccfaad72b9da6624d4b8cfcd7c2aadf4e7dee9f75a27a1601117a56c17cae11948f6ce6723b65c966928ad9f57223dabbc619595706817d5655925126848786a29ef614125942670145988be017cb1a0bc4d7ba3de6532392b8fb436672b620037571e63f8f07b374c284a408003f59675fd287b462fca386288faad0532217ad3647bea89c4d527cbb6b352d3dbb242963c2c49a18ad649bc077a1b7483e7a48750030b90113b4ea5418dab39705b412bb649d69c998592ad1e2bfcb75cc796505a2f4a942684eac3121eecd7025aadb12591d6cc902dced6014d586c05286843942631a57d2347ec2930fcaeb0162a7b6681d8dde1c1ad7cb88388cf9cf776dab47e31fa40e4c8da721f7596c9604554ae366fd2933e8ab515cfe95f7653abaef90f550b17b4fcd3a0d4e6a85ab46f31e08bbccf952e9b671507c5babeddddef80136a15a764aa7fa91e40b7479722aab6ad803efdac9661916eb7918f13abc229cb1b68a1e9d69972aaa61a8edbbcb1f0cd06e05f82f0527606d8016785cbf9ea5ccc25ad42dd61298a2d4c2e69d544cca3e6e54ab774cc276a60e1576493a63a8f277cbb882cbe95b375f9307c3deba2b6c5ca6662e3226c5aceeb692702a1a1eaa4ebac7b882d7d49f4493edf58015b8fbdc11125ec88dcd5b595029b1199af7b69d2832212f3e0ab99149a98a3eb07998d7dbc0ac85281095a8dd8f5b9016a01a7cdd6aba98d1aba59cd3b9c27deec91179ad728e601dfe81928c75bbfba7b7c3d1c7fb8cd5966cbf07e2517931e1a50b244a809b3875be0f152141aefcc85a3f5acde4104572d7517083467a0b376b581cf41dfe54ecf8dd18fd819d2fae92784e1e2c86e2415ad3d8b16e0af07706365f3e757cf4db17d9a6692824348e15698a097d3b986da8638b361a8bd5366504a41c8af07716781dce31e78a23545f6eb941e0849d9501cede59b3d4ff859cad488f6da7c1e975a97d49c37462a65a7550894da975a63069cef8740a81d7579fe435df576bed7bde26c158c5ea66a8aeb7b1981fd85aeb6a0f8ced7345258b5f920c0ecc483554160668ad35d354afac07a01386f76476f7f91aafda7a8a68a03f93bd35008138f173017b5250728748ffed952050bf5452cf6c7f845af235545baf57c1188cf6af545e4efca456a0e35cbfdda8798eac3d025a8a30641cc017cf4af6f7337a33b45c70ff7728ff7967a9d5ab501ce72eaf357bf4aa462965e356180776c66cf6c7e837b5ff7afa19a2b6893d356ef001d74911b56ac49513565031624280aaf834e3f0bf444057a49582e3817268a98f0f4114388051224280294e84385055e2c2822712bc18827911389b2916dc79f2d523c6993d02c448b0d5ea42a70d8adc2a44d46a4c9a0362d458bc68efc4a03b4eccc9b2796140982f824d6af317a1d3a039a66ddaa358ad41bb211e050bd35567d0bb0796b53a06f564d8b1656aedaa37baa9d99157c65d0a68b03355a2891f36e973fd236ab27b62147b0499ed519027fe5ef52b857173e89497951d4c96db60d9ad3b85160c097ae168a43f53845d67d5fd48d84d86be09c371fc679725733dfacbb272cecc2783fcac52327f6dc3adaadc6e283a3f59b5bb13e6de97513472f393079de9475af2efd92bfec6fdd9d03b4ab297fa0d2b5a183df9e7990f95ae4e3cf2044feeb8fa04fbe8b4c4da207e3eaa7a0ba8bcf20bade13cac043dafa3e0f340d835f29a8d2abbf6c20e6c3da2db3fc7bf091ccca8affe4c3e04b9caa30f283be0abb1da3ee2934d8cb9beb27c6031d02b9f4041d6dbdc67302b4bccafbee07cafe746d093815e34255a709eaceee24a04bf1d7b60f838052c1d09c6f66c91f8c8caba5e8fb5c6b20d2f33f8742efbca452d5a5ec44fc2543d24b42bca396fc7cc83c07142daec7aebb707943c2f4dfe5c0ecd4947ac3ccd3bc0446fc5c1f62b823ccfc673ce8eb7eefabc63522f4da458cd0745d01c47c223847cb85b9283973f1d6b8c805c474c3072b6d83b10b6c405c3c013511574449ab02985fd4a404d0ca0335c1315fc67a61bad0ec7d26d64629ac907a5cfc05fe69485dc30deaacdc051556c53b5c67b6c5a0d45e2bc54dfaeb43d259adfbc23b6feba11f5957b4b7bcb7acfc12f0508bb538bdb15fe3c35ade2be5c7f16b5d4c8059b033e5dcaf5ae44dab8f5c012594fd488dbd66bb5e3d2e39d36471dba17a453555d43e2e2bd4a7395c511b4471e48dab693befcc59b5f21659571d29773d6b742051b51504a478cb83c4ca4dd8399e053058afa5cf8d4a33bee31dd9ad74503bd6f6940b79cdf24d95dfb4d6cc74d866a82e93314763de06704445c4b0765713dc5a8d580946457f5e57c6cbffbf47ade4fbcb7395b45ceaaf3eb77b3a5515e935d3c1fd16b8efc6ab365a3d67ec0c7fe1c44fa47acf9bd489ff5cb3f4ac3ceddecd32f46dc556a39c4f67579c1540b71fbee7ebe876d29e6f35856c56a7cb6e3f4044b9c682d869df151f047729947475e56396c5184147d3feea79d6f6a5d65f877a93be3bb14cb53cd9616ec7bc267f54ae93ed676fd9f463dfeef2325241e23654e291bd2831521416ea95ebb3f02eefcd7d828d0ed614b0af812e6958f20650dee4fe2c903f0975ca5c1c90e6bba80e2aea4124ee909c386b2b99a5ac4c0c4b0ede25e1ba813c2e6dc3dec374a66320b859a97e8b1b50ac28c821069c253c124a9b78b7234b6dcf8e6504ad9582278cb0254f2c6014d398034513b1a5f8e56fcbff06bc55fc2a71be646d9aef4c03d5cf1a220036859a9719e4c76bbcf520588263b818fc23a2c9590a4d56896e89e6b4cb31c19a0e21a96558ca88ab22c020b37184cc9a52d238ced031765c9281d6c6d5a49e2eefea5bfac953d6766a305d8bce456bcec8d6156c1da938417e33291af072ff214db0bd6e7a44ed09f40ebd3278ef823455642b18544bfd9cefef6fb4635fca179837f960dc221a1a1d2f794c2e89427474b1932bc0b7583cc1101f75a90e92359644ac9df03a8aca076fb4b55db6f87fc498342a12aa442f370a405d8829edd53738e89b2d9d095fa2ee4e0328502afdcc207cead35da2352c2fbd23f972ac4e86fc13d63e21bf656202d3a83755ce4ec14aa58cfc179dbca612b8325b8161b4f2ebda486f105259e19564a4660db50fb0bd52df3e6bee83ba6afd3e3d6e838f1d5654e6b5a3de5ac3f0646b69a9a4d5262a9d1d06953549dc0dd580342592759dd4532bf4d8dfa81a5c07744c4c5fd0565c473e43919c4b64a5c4d2492375b1de79c4fc557ac7773971857a4bb4b317da98714dc8a68666ef9c1aa7d4b877417d70369e4c5e19e29a61520945d845e2bf8d5f677f3be9757744d1d850d8fa5156454f63a60458adea07e51819bb6985f397acfa16fda2a8d1d58a0b3e9537b7295ea20d6c956326abc054da3035a1ba8e03f89cc84b1a5db8239e724d7bee43391657da9d6a876d28d2d4fae2341e045696f99ed2dc4a98cd158ec192b5c3e929448c57a9e6cf950a51995dba58adb9e3f8863405911b5b41d05ae2d5af75c820e4a8d72cad005740e94d11faca42c11117887964b5a121d9bbc67aa2fd97b582238cf7fa5236ac034e94a1e0fa49d7cfe6059ba3daf0a9cc0938d7a59645bf542be339f632bfcac7767e523e17d47894b061d3dbb991e36e917c84c055175ecaa77c729f595c95d403361673e2f0661d152fc08a7876961c726481b554625a09b170c9ac6879eaa36901a5da7e9b8d5fcef4e6908000129f4010a000ff00c2000000000910f4000080ef0059d2318ac80e04385070e1458909022c78c012a3c884172a5c5871b126cd8a1b3a44e8f1d365409325466c0982b46ac39a2b52bc794216a9c894376adc595317adc564c4021b18f35951b283497af40a3078a05f974595055a54b72f44ab479a1d9ae4392156a85f9e6dba14dba559a165be8d6a263a2a53ba6bb2b5ea56ba6bd8b051e25dab06fee752ba7fcab59b673b20ecb281f2fd2cb77de0e3c96307362cf891fb58c395277468891166edca9b337efce93438e1d2ab439e3d6a353ae5daab53be7dea363ce9d2bb63d60d5c4befcddb478ee63a34d7f4de91c3b2fe2efb98f2d4edbd830f5e3cb93374e1d9af178e7d587677eac5bf37fedd9befb4fae8dfbb87be6e7a79f0fae1cf8fdedefcfaf7f9e9cbb74fcedebcfbf3f1f3dfcf25514a3d08e25e450ed4702182392860e2890e38e0648d0e4880a4851258c0e58a166841975a5d78655885498840d88626988228872aa892298c2eb8e26c8b2ac8d2ec8636d8832c873ae8932d8c3ef8e3609b3a09d3e09646198420933265f7954126057555585d39a0508a4d49322496562414159c5949d5669552a8d497915e5916214a529985aa936a95d62557627970989f52a957ab9772d9f59063769967ef917af9b520aa7a0a96ac958e0ab62c99821ac6e3ad8289976e9805e6e1e6801268b9a6a616680a67a1ae7a2a69a4ae9ac92aae96aa93d8855e14efa9978e5545a51da361655c1ea7beda3b6359bacaabadafbe78fb5371cafa745fa7caea3c5da8ca0b9ca3bbc20bac65b4ce4b2d25b9de6bcb27b3c67b6ca5b0ee7b4e64b1ea7b6e69bea6371ba49aae8acaeaa2f2cb3fa9a1f2db8fadb5febbaf6ebf2d5947679c01f76ed954d1475e126cc5474e5e51e1bb707d5ed9372e9b57dd3750ba511b2cf79b7c0f5cc7d3c5cd8708d4c5ce2c5618c60f2642b0790b7582b3ce7d670132c2135c72f7c849aca179cd09da926087f6fb443fb64f0d74feb84f2da473def23d0fa0c6057935fba8c2ab7deea5e66d0d24bc5f3b75b6d0633b2636be220b7ee9df5b7d56b8bb22adb57bd85bcd96fbdb678de5bbd14fefdd467edcda26b0d23c86784390de920cc9a4d81e8891249baa1ea022ea9a2eb123ed9a3ec024e01a4e4025e30a5e6126ef0a3ef66f4735b5e3359cb57c83f8932fc581f6993bfc2653c29dae96abc685dcb3356f2bbec2bde82ece737dea2b5c485bc98dbee62eea7dce91bd5acdc94cf65ab70c337fe7892f9db3432366c3dde0571d3e72df4b3d4e3af6e7af7e7bfce73ba1d2c5ad6d5cadadc627fa2ad7f3cf0fbdf8f71bdfb6acef0085f310eff89450440e003f795b50a69895f0c306abc08b0c90a2052810cb0eefc2811cd0660b388f3e0230348f1c11660f76b51fc4fe2443b12d5ca643e24cc4c0ba62a991a5de3363410a76278c4ad12c0f78ef534022e0588e3c02a1178874c22221798a4c62e66878619571344c22110cc57ca881943954256f5203d61776d5443d71d83164e2d81177ed3336611c8152f2ea19c8d6413eb11d869a632558e8924b3a060f8e6c680713e8a64f32b1304d74d31f15e8284832121196840b4a11e26c2e35ea2e76b28227680881994221fc66a970606a42a0c0b586c3946bcc0e82c6b9c7b572f68781052923353a465288c49c224561193924c649b0f5841c015c2578f241d1a0917d998b061779234b3295eb44bc679321321a9ba1121a9c118d5519a97810d53312915a66ac09b9d0986240d944dc0a9e0bc9319c6664a22cd43c182bd94ecec8433e9911b6e84e720aef892da13f90b458cdc29980935082241c72ddc311736db5b4e0965471f566681a7d2776a1b488c44696b243ffc491241e7dba57a75af035892c20a00500e3473f1201507dd3d0aa2dec464992254e3084f50d703792be233ea465c2db21a0e3c412b0508504d4f340a00920558a9e43b044c879493a2259d4a72755e72c9d29ffd53d328e95943f036835e8c57489c110e9bcc1465567685138ac80583538ab0850c4d8462ec7be1ca622651cca3f58c78710b538ad70fc5442bae29daaf9a121a871c84f0b508a9605a0bd6d0a2f570b275066548f0e8d504a0e4abb49cd3496702aa767b6b74bc9e5805b93ccda4205e9a33c32768977db27ea0b83871aefaa91d0b35056892af042d924f0ba9b74e8655d16fc4f822fc893092c656d4ab550de25f3bd9d59a0807bd851a2431abe8d1aed4fb886be3447b0082a311b0506dac4d013e4140d62196cbb25ceaaadeea99cdb5c5da6bb24d405a6a6fb2dca7d8bf206ac92e500a87b63015b93ac12f2b49011354979d5ad57c2143db303235a713a1da5d905e020dd196f7b7890e192143e9bc8afab614168d0aeb0cca79241ef531339156c4109bcbc44d2ac1c682a45cf095436d3eee25c25b0ed06c7232ee8813df7ce4dbe2047be090582a8d95715c83457c0430d506492358e34859f078d7a6c9e5c591b417e833601ace165aca72f27b51cc0d2f1b3bad202e500eff7944fdb28226ee982535c2061cbb2a1a440570d4603a879a16da17413425fd217987918b5fb80a19cd4905436b6b35298c96f685c483df9f420bd0982abfb67ac072639a621c37835a817174ada43dc707862838a5ae666e602bd7eb4ea4d179953719d4fa8cd73eab25ade5ef924b22d3b58864b3292ddb903b7d6865608264a7053cd57912e4dade15695ec4cc11bd7db24ba96239a171db299dd47ce3c2f1ead8b631362dd52963b67b9fa97a1a47b74aa853fc640d619992eb9cfb0350075354af4d70f941bd13108503d59a29633f2d1dafc09cba6fb32d48e0ad3bad11960598c0b2ed29bddcffef5694ef8a91c77aabf44dd9337a9fce752766aefcf6ac8a0710e2c801cda28ded317bf25bd08ccc5c6f12419f44ccac49174d4cacb329fc9eb2fa7fc0e1edaeaabb559054f168a3332a300502fd6962b1d8d24e204b75576e548447f50db2f4f5ba6e214e476ac8247661a0a1ac5dddd69c7fa8c5c312c6ae594da48286e1319847c5ac171dea7b10aa491e95c21664fa9374e8ed49e3816bda78d92c181421a078b5879c36209636f5024e82f1e5dbd78c24dc79202d204e773230da9214e4135012f1635095035079733e3d3c24ef1ed7049b762dcc651b3d579cac8aca3bdb9c79bde418da24e71449f3d055c883e54c58f6dbc94330a0c770515e579c03255120a8c244d5dcb2e95e34ede09f6be41a6ef012d19afe9f9af92932673ec01397bb7a9241b4a04a8a1aff2f1529fa879a7144bbf2099af47af358354203fa1d55376124a477451287325697b014564084760b57f77772016a02a7c864c0335b86e310459506f71f7985ec3577197797bc07085009505e5171a87325500cd7b26476cf34c58f4747ec7435747c70405f57501bb7366311cf7028e774a39c13089856a07529c7ed7228081d38aa71258500663017c65d5501585f20b16bc01d7595847ad1527387500850977fc5aa7847b917e62d58030a0358e257643475c5126c08401868145241287454a96f206a7485126b75595907801a87d58cb1978611a65595500b06266f85a488f7201350850ef7d7b65950607538fc7922978243838556f78c86396d06a01f78885556397db15165b5b47bc0e07435984601b48c68c916770288c7b68df7e85b51a964052874e7401c85425cf5991a86226a38283a419b83255983b22888275e78853480a3334676276867394b68ac0975058801026e85b97936428e97924341a87ec6c93868350893ac07588459a8ed7e72b48ad70e8ed80f33f7885108261a872505922020e8587463a988d4682d344535011d55988d8e01ac7df8064837e85017806487f20af7081401f187b80931f7e97991ec7da7e17c25501868f48d72ed76a7fd8416c65b00770277ce8a713e85b6103f277362019d8b989644287a05002781b5eef181d5e372041f7625ba6c01a87b97ee55c05565b55413413770e8a97de7d582016b7ad5e95a268856a0711a398f8eb1e390c7b75e65096131e83ba6341b759504c1705f496d7a51dd8d914d5f291344619371787346d8533a962876d5f24e08aa7c294199053523d72381116273b8c47b756d5f37ce5ee2937b00625e83289f352153223d70c7309ee7824d175374a5c898a61172889977d8965ce27577b84340d7cf89f3f18479dc4f09d34f78e52d53676c016b7de5752850885af75922431181d50295473689f3d91b758570d4f09911f58097093be2f09e83287d72005377b24eb8fc75c2eb8b96ee51167c7035cb9b33ca8a47972ac7245b381e890ef8501e29f87236c38885cd5839456c65da95b6ad44c03984d83728988853116a04254e8fc1b47ec7cd5811a980898255a5301b59ee25a8df9f11484f787a06011e8317cf3b694b21e8099271627b00bb8964341a86556c51305ef5ee4f585985e7e850884552b9c651671852f68934285293017d9f204a5939885950296639234950c2a562ce4556845b851e9d2ad525b35b7556847e42a414590a05c113ac657b7776bf8358e51bd5eb52238a9281885d36fd244ace6363d41b65f396c68850171a6924d172f7ff83e7c914e9d85726e46f78967824d26301a986722668d902236a5259562942b7601e20d85d1a2031f7b88422e831f764a0563394552a7ef028d70235d2878a68a337a9634652236a778a01b95bc01e9c0a5a4678d58920cf8038b9ac9a647459a1ac3a785c27fd41f8de91452501f49e9595d27e82d17f0a72a556b17801e240f9ce8122b69992d17f98ec50ba587c995c6552df75c97a6e88b01249834006571141d88e88a41b65458336341e45d8a1c9d79dc16e8f07f35788125350250cdaf20edabd7cda019767587a61c5aac053ab56924bd58478dab00250ff7adaddacda950e20bdaf202fa8c51415a96815a3096946e195983a6595be96378915baf56cf91d50e7b476b21e89f55512d9a6491a4340033f5398dd48e72d2c3ae85b37be627a781f58439558a5633a9175285ca241250556eef77d22701478d8a59242839762711b721e012f85623e8c7aea6f31678fc9222a980e763b0b2f01e116267491d56172b5a95d1b4dad917d90aa8779014982e7baaf799941f7b00891b682283036e770a0b6c8aa38522647ba739896bcd5792d17397c31f89da66f6504b49d85e371021f7db51f3dba226d34b49e85bfa0bacb7ab6b915417988dad70fb22679ea409702398c26428ab9507283863462398905b38ec26e4b0b226d8429923b51396adf75b5078422553d527d9b6b18ac65c26c83f8a529e23d341a045962a527e20849c26b6ab75ae817a489152a7937a4642078113d7e2b301868c5b367601d88aa8f52b68649b6864ab3671bfd5ec72ba29efa1aa0282b3f6179aa6823a11ae41016eb66f87113d379149339ae85b886a45c07d9de6f760035c065bec70c87b9b113d72f7a01c2b528649f31486368bea5515f9eeb5f96976e404bb11219e1190caa68446b2289e97322ac7cd50a8924689e9452a451428018b95f2b675e187c5347a67aa9054dea14175a0699722160225a94a4b717c799bb75bba5c2a26b597267db2ab95a5950652864282f7bcae19d474c48da96ae1617ae88bcb8cb5211e9347cc994865178b2a5d86382e55deb379c6556a9e41e80aa6885c88788f93f6f2b89b2e7785e6b21155611bf61571678bfa428b001b97823ba7253eb29b2b5f47601aa98350dba34f82a4b9eb48653aef53633cb7bd65e5cb27553f7ce1b57aeb2f8ab965c028931cad3de948715417a896a11e56145706f21ab4c03e7b325dbb40187be4635209ba09debba3c8c385394253f31529d4cef8bb232c607f4b27ac7992b7468f8401e798dbe6cfdb015e246b276cd9b35ad8ad326613985358daf5a0f51f8538f075c2b69d64ec86daa710a32bbea995a339c5604a5282e91225165ca81bee7014d02801ecb6117cb2c6891b7ad913d7649cc94199367984016f9d3116b7a1df9fa5d41df770631a46c7553326f955b556dc527be86cf8a8b5c08da446c938830fca68b757e4df4dea1e47ecfa23015dbbd4ea2da911d1a8f786a0b3aa019c95591e44ca4f5f332885ef29154427e0c04cec2289a93462f7a99b7ac6611e88bb49ba514c9a01f8a72d6d1551a5a7a7d0176a989d791b3a7489760b1e9468b67adb12287c5f59ec1957b90a985a289d188e7a6176c65355cc8321ac2aac13279515889ea91bc96a410a9257e1202b5b61027dcf85d573bc954e0799c4551f75d6683a5c2b51f7d18d6850ba8c99bbc0918abcc1ad7d1a1595e20ca34b2a98019f1a2f9544c83b96b01e195fc70a7e4468edb9765ea57d0a6311e1dd855a880d25532189c389dd4eccfaad72b9da6624d4b8cfcd7c2aadf4e7dee9f75a27a1601117a56c17cae11948f6ce6723b65c966928ad9f57223dabbc619595706817d5655925126848786a29ef614125942670145988be017cb1a0bc4d7ba3de6532392b8fb436672b620037571e63f8f07b374c284a408003f59675fd287b462fca386288faad0532217ad3647bea89c4d527cbb6b352d3dbb242963c2c49a18ad649bc077a1b7483e7a48750030b90113b4ea5418dab39705b412bb649d69c998592ad1e2bfcb75cc796505a2f4a942684eac3121eecd7025aadb12591d6cc902dced6014d586c05286843942631a57d2347ec2930fcaeb0162a7b6681d8dde1c1ad7cb88388cf9cf776dab47e31fa40e4c8da721f7596c9604554ae366fd2933e8ab515cfe95f7653abaef90f550b17b4fcd3a0d4e6a85ab46f31e08bbccf952e9b671507c5babeddddef80136a15a764aa7fa91e40b7479722aab6ad803efdac9661916eb7918f13abc229cb1b68a1e9d69972aaa61a8edbbcb1f0cd06e05f82f0527606d8016785cbf9ea5ccc25ad42dd61298a2d4c2e69d544cca3e6e54ab774cc276a60e1576493a63a8f277cbb882cbe95b375f9307c3deba2b6c5ca6662e3226c5aceeb692702a1a1eaa4ebac7b882d7d49f4493edf58015b8fbdc11125ec88dcd5b595029b1199af7b69d2832212f3e0ab99149a98a3eb07998d7dbc0ac85281095a8dd8f5b9016a01a7cdd6aba98d1aba59cd3b9c27deec91179ad728e601dfe81928c75bbfba7b7c3d1c7fb8cd5966cbf07e2517931e1a50b244a809b3875be0f152141aefcc85a3f5acde4104572d7517083467a0b376b581cf41dfe54ecf8dd18fd819d2fae92784e1e2c86e2415ad3d8b16e0af07706365f3e757cf4db17d9a6692824348e15698a097d3b986da8638b361a8bd5366504a41c8af07716781dce31e78a23545f6eb941e0849d9501cede59b3d4ff859cad488f6da7c1e975a97d49c37462a65a7550894da975a63069cef8740a81d7579fe435df576bed7bde26c158c5ea66a8aeb7b1981fd85aeb6a0f8ced7345258b5f920c0ecc483554160668ad35d354afac07a01386f76476f7f91aafda7a8a68a03f93bd35008138f173017b5250728748ffed952050bf5452cf6c7f845af235545baf57c1188cf6af545e4efca456a0e35cbfdda8798eac3d025a8a30641cc017cf4af6f7337a33b45c70ff7728ff7967a9d5ab501ce72eaf357bf4aa462965e356180776c66cf6c7e837b5ff7afa19a2b6893d356ef001d74911b56ac49513565031624280aaf834e3f0bf444057a49582e3817268a98f0f4114388051224280294e84385055e2c2822712bc18827911389b2916dc79f2d523c6993d02c448b0d5ea42a70d8adc2a44d46a4c9a0362d458bc68efc4a03b4eccc9b2796140982f824d6af317a1d3a039a66ddaa358ad41bb211e050bd35567d0bb0796b53a06f564d8b1656aedaa37baa9d99157c65d0a68b03355a2891f36e973fd236ab27b62147b0499ed519027fe5ef52b857173e89497951d4c96db60d9ad3b85160c097ae168a43f53845d67d5fd48d84d86be09c371fc679725733dfacbb272cecc2783fcac52327f6dc3adaadc6e283a3f59b5bb13e6de97513472f393079de9475af2efd92bfec6fdd9d03b4ab297fa0d2b5a183df9e7990f95ae4e3cf2044feeb8fa04fbe8b4c4da207e3eaa7a0ba8bcf20bade13cac043dafa3e0f340d835f29a8d2abbf6c20e6c3da2db3fc7bf091ccca8affe4c3e04b9caa30f283be0abb1da3ee2934d8cb9beb27c6031d02b9f4041d6dbdc67302b4bccafbee07cafe746d093815e34255a709eaceee24a04bf1d7b60f838052c1d09c6f66c91f8c8caba5e8fb5c6b20d2f33f8742efbca452d5a5ec44fc2543d24b42bca396fc7cc83c07142daec7aebb707943c2f4dfe5c0ecd4947ac3ccd3bc0446fc5c1f62b823ccfc673ce8eb7eefabc63522f4da458cd0745d01c47c223847cb85b9283973f1d6b8c805c474c3072b6d83b10b6c405c3c013511574449ab02985fd4a404d0ca0335c1315fc67a61bad0ec7d26d64629ac907a5cfc05fe69485dc30deaacdc051556c53b5c67b6c5a0d45e2bc54dfaeb43d259adfbc23b6feba11f5957b4b7bcb7acfc12f0508bb538bdb15fe3c35ade2be5c7f16b5d4c8059b033e5dcaf5ae44dab8f5c012594fd488dbd66bb5e3d2e39d36471dba17a453555d43e2e2bd4a7395c511b4471e48dab693befcc59b5f21659571d29773d6b742051b51504a478cb83c4ca4dd8399e053058afa5cf8d4a33bee31dd9ad74503bd6f6940b79cdf24d95dfb4d6cc74d866a82e93314763de06704445c4b0765713dc5a8d580946457f5e57c6cbffbf47ade4fbcb7395b45ceaaf3eb77b3a5515e935d3c1fd16b8efc6ab365a3d67ec0c7fe1c44fa47acf9bd489ff5cb3f4ac3ceddecd32f46dc556a39c4f67579c1540b71fbee7ebe876d29e6f35856c56a7cb6e3f4044b9c682d869df151f047729947475e56396c5184147d3feea79d6f6a5d65f877a93be3bb14cb53cd9616ec7bc267f54ae93ed676fd9f463dfeef2325241e23654e291bd2831521416ea95ebb3f02eefcd7d828d0ed614b0af812e6958f20650dee4fe2c903f0975ca5c1c90e6bba80e2aea4124ee909c386b2b99a5ac4c0c4b0ede25e1ba813c2e6dc3dec374a66320b859a97e8b1b50ac28c821069c253c124a9b78b7234b6dcf8e6504ad9582278cb0254f2c6014d398034513b1a5f8e56fcbff06bc55fc2a71be646d9aef4c03d5cf1a220036859a9719e4c76bbcf520588263b818fc23a2c9590a4d56896e89e6b4cb31c19a0e21a96558ca88ab22c020b37184cc9a52d238ced031765c9281d6c6d5a49e2eefea5bfac953d6766a305d8bce456bcec8d6156c1da938417e33291af072ff214db0bd6e7a44ed09f40ebd3278ef823455642b18544bfd9cefef6fb4635fca179837f960dc221a1a1d2f794c2e89427474b1932bc0b7583cc1101f75a90e92359644ac9df03a8aca076fb4b55db6f87fc498342a12aa442f370a405d8829edd53738e89b2d9d095fa2ee4e0328502afdcc207cead35da2352c2fbd23f972ac4e86fc13d63e21bf656202d3a83755ce4ec14aa58cfc179dbca612b8325b8161b4f2ebda486f105259e19564a4660db50fb0bd52df3e6bee83ba6afd3e3d6e838f1d5654e6b5a3de5ac3f0646b69a9a4d5262a9d1d06953549dc0dd580342592759dd4532bf4d8dfa81a5c07744c4c5fd0565c473e43919c4b64a5c4d2492375b1de79c4fc557ac7773971857a4bb4b317da98714dc8a68666ef9c1aa7d4b877417d70369e4c5e19e29a61520945d845e2bf8d5f677f3be9757744d1d850d8fa5156454f63a60458adea07e51819bb6985f397acfa16fda2a8d1d58a0b3e9537b7295ea20d6c956326abc054da3035a1ba8e03f89cc84b1a5db8239e724d7bee43391657da9d6a876d28d2d4fae2341e045696f99ed2dc4a98cd158ec192b5c3e929448c57a9e6cf950a51995dba58adb9e3f8863405911b5b41d05ae2d5af75c820e4a8d72cad005740e94d11faca42c11117887964b5a121d9bbc67aa2fd97b582238cf7fa5236ac034e94a1e0fa49d7cfe6059ba3daf0a9cc0938d7a59645bf542be339f632bfcac7767e523e17d47894b061d3dbb991e36e917c84c055175ecaa77c729f595c95d403361673e2f0661d152fc08a7876961c726481b554625a09b170c9ac6879eaa36901a5da7e9b8d5fcef4e6908000129f4010a000ff00c2000000000910f4000080ef0059d2318ac80e04385070e1458909022c78c012a3c884172a5c5871b126cd8a1b3a44e8f1d365409325466c0982b46ac39a2b52bc794216a9c894376adc595317adc564c4021b18f35951b283497af40a3078a05f974595055a54b72f44ab479a1d9ae4392156a85f9e6dba14dba559a165be8d6a263a2a53ba6bb2b5ea56ba6bd8b051e25dab06fee752ba7fcab59b673b20ecb281f2fd2cb77de0e3c96307362cf891fb58c395277468891166edca9b337efce93438e1d2ab439e3d6a353ae5daab53be7dea363ce9d2bb63d60d5c4befcddb478ee63a34d7f4de91c3b2fe2efb98f2d4edbd830f5e3cb93374e1d9af178e7d587677eac5bf37fedd9befb4fae8dfbb87be6e7a79f0fae1cf8fdedefcfaf7f9e9cbb74fcedebcfbf3f1f3dfcf25514a3d08e25e450ed4702182392860e2890e38e0648d0e4880a4851258c0e58a166841975a5d78655885498840d88626988228872aa892298c2eb8e26c8b2ac8d2ec8636d8832c873ae8932d8c3ef8e3609b3a09d3e09646198420933265f7954126057555585d39a0508a4d49322496562414159c5949d5669552a8d497915e5916214a529985aa936a95d62557627970989f52a957ab9772d9f59063769967ef917af9b520aa7a0a96ac958e0ab62c99821ac6e3ad8289976e9805e6e1e6801268b9a6a616680a67a1ae7a2a69a4ae9ac92aae96aa93d8855e14efa9978e5545a51da361655c1ea7beda3b6359bacaabadafbe78fb5371cafa745fa7caea3c5da8ca0b9ca3bbc20bac65b4ce4b2d25b9de6bcb27b3c67b6ca5b0ee7b4e64b1ea7b6e69bea6371ba49aae8acaeaa2f2cb3fa9a1f2db8fadb5febbaf6ebf2d5947679c01f76ed954d1475e126cc5474e5e51e1bb707d5ed9372e9b57dd3750ba511b2cf79b7c0f5cc7d3c5cd8708d4c5ce2c5618c60f2642b0790b7582b3ce7d670132c2135c72f7c849aca179cd09da926087f6fb443fb64f0d74feb84f2da473def23d0fa0c6057935fba8c2ab7deea5e66d0d24bc5f3b75b6d0633b2636be220b7ee9df5b7d56b8bb22adb57bd85bcd96fbdb678de5bbd14fefdd467edcda26b0d23c86784390de920cc9a4d81e8891249baa1ea022ea9a2eb123ed9a3ec024e01a4e4025e30a5e6126ef0a3ef66f4735b5e3359cb57c83f8932fc581f6993bfc2653c29dae96abc685dcb3356f2bbec2bde82ece737dea2b5c485bc98dbee62eea7dce91bd5acdc94cf65ab70c337fe7892f9db3432366c3dde0571d3e72df4b3d4e3af6e7af7e7bfce73ba1d2c5ad6d5cadadc627fa2ad7f3cf0fbdf8f71bdfb6acef0085f310eff89450440e003f795b50a69895f0c306abc08b0c90a2052810cb0eefc2811cd0660b388f3e0230348f1c11660f76b51fc4fe2443b12d5ca643e24cc4c0ba62a991a5de3363410a76278c4ad12c0f78ef534022e0588e3c02a1178874c22221798a4c62e66878619571344c22110cc57ca881943954256f5203d61776d5443d71d83164e2d81177ed3336611c8152f2ea19c8d6413eb11d869a632558e8924b3a060f8e6c680713e8a64f32b1304d74d31f15e8284832121196840b4a11e26c2e35ea2e76b28227680881994221fc66a970606a42a0c0b586c3946bcc0e82c6b9c7b572f68781052923353a465288c49c224561193924c649b0f5841c015c2578f241d1a0917d998b061779234b3295eb44bc679321321a9ba1121a9c118d5519a97810d53312915a66ac09b9d0986240d944dc0a9e0bc9319c6664a22cd43c182bd94ecec8433e9911b6e84e720aef892da13f90b458cdc29980935082241c72ddc311736db5b4e0965471f566681a7d2776a1b488c44696b243ffc491241e7dba57a75af035892c20a00500e3473f1201507dd3d0aa2dec464992254e3084f50d703792be233ea465c2db21a0e3c412b0508504d4f340a00920558a9e43b044c879493a2259d4a72755e72c9d29ffd53d328e95943f036835e8c57489c110e9bcc1465567685138ac80583538ab0850c4d8462ec7be1ca622651cca3f58c78710b538ad70fc5442bae29daaf9a121a871c84f0b508a9605a0bd6d0a2f570b275066548f0e8d504a0e4abb49cd3496702aa767b6b74bc9e5805b93ccda4205e9a33c32768977db27ea0b83871aefaa91d0b35056892af042d924f0ba9b74e8655d16fc4f822fc893092c656d4ab550de25f3bd9d59a0807bd851a2431abe8d1aed4fb886be3447b0082a311b0506dac4d013e4140d62196cbb25ceaaadeea99cdb5c5da6bb24d405a6a6fb2dca7d8bf206ac92e500a87b63015b93ac12f2b49011354979d5ad57c2143db303235a713a1da5d905e020dd196f7b7890e192143e9bc8afab614168d0aeb0cca79241ef531339156c4109bcbc44d2ac1c682a45cf095436d3eee25c25b0ed06c7232ee8813df7ce4dbe2047be090582a8d95715c83457c0430d506492358e34859f078d7a6c9e5c591b417e833601ace165aca72f27b51cc0d2f1b3bad202e500eff7944fdb28226ee982535c2061cbb2a1a440570d4603a879a16da17413425fd217987918b5fb80a19cd4905436b6b35298c96f685c483df9f420bd0982abfb67ac072639a621c37835a817174ada43dc707862838a5ae666e602bd7eb4ea4d179953719d4fa8cd73eab25ade5ef924b22d3b58864b3292ddb903b7d6865608264a7053cd57912e4dade15695ec4cc11bd7db24ba96239a171db299dd47ce3c2f1ead8b631362dd52963b67b9fa97a1a47b74aa853fc640d619992eb9cfb0350075354af4d70f941bd13108503d59a29633f2d1dafc09cba6fb32d48e0ad3bad11960598c0b2ed29bddcffef5694ef8a91c77aabf44dd9337a9fce752766aefcf6ac8a0710e2c801cda28ded317bf25bd08ccc5c6f12419f44ccac49174d4cacb329fc9eb2fa7fc0e1edaeaabb559054f168a3332a300502fd6962b1d8d24e204b75576e548447f50db2f4f5ba6e214e476ac8247661a0a1ac5dddd69c7fa8c5c312c6ae594da48286e1319847c5ac171dea7b10aa491e95c21664fa9374e8ed49e3816bda78d92c181421a078b5879c36209636f5024e82f1e5dbd78c24dc79202d204e773230da9214e4135012f1635095035079733e3d3c24ef1ed7049b762dcc651b3d579cac8aca3bdb9c79bde418da24e71449f3d055c883e54c58f6dbc94330a0c770515e579c03255120a8c244d5dcb2e95e34ede09f6be41a6ef012d19afe9f9af92932673ec01397bb7a9241b4a04a8a1aff2f1529fa879a7144bbf2099af47af358354203fa1d55376124a477451287325697b014564084760b57f77772016a02a7c864c0335b86e310459506f71f7985ec3577197797bc07085009505e5171a87325500cd7b26476cf34c58f4747ec7435747c70405f57501bb7366311cf7028e774a39c13089856a07529c7ed7228081d38aa71258500663017c65d5501585f20b16bc01d7595847ad1527387500850977fc5aa7847b917e62d58030a0358e257643475c5126c08401868145241287454a96f206a7485126b75595907801a87d58cb1978611a65595500b06266f85a488f7201350850ef7d7b65950607538fc7922978243838556f78c86396d06a01f78885556397db15165b5b47bc0e07435984601b48c68c916770288c7b68df7e85b51a964052874e7401c85425cf5991a86226a38283a419b83255983b22888275e78853480a3334676276867394b68ac0975058801026e85b97936428e97924341a87ec6c93868350893ac07588459a8ed7e72b48ad70e8ed80f33f7885108261a872505922020e8587463a988d4682d344535011d55988d8e01ac7df8064837e85017806487f20af7081401f187b80931f7e97991ec7da7e17c25501868f48d72ed76a7fd8416c65b00770277ce8a713e85b6103f277362019d8b989644287a05002781b5eef181d5e372041f7625ba6c01a87b97ee55c05565b55413413770e8a97de7d582016b7ad5e95a268856a0711a398f8eb1e390c7b75e65096131e83ba6341b759504c1705f496d7a51dd8d914d5f291344619371787346d8533a962876d5f24e08aa7c294199053523d72381116273b8c47b756d5f37ce5ee2937b00625e83289f352153223d70c7309ee7824d175374a5c898a61172889977d8965ce27577b84340d7cf89f3f18479dc4f09d34f78e52d53676c016b7de5752850885af75922431181d50295473689f3d91b758570d4f09911f58097093be2f09e83287d72005377b24eb8fc75c2eb8b96ee51167c7035cb9b33ca8a47972ac7245b381e890ef8501e29f87236c38885cd5839456c65da95b6ad44c03984d83728988853116a04254e8fc1b47ec7cd5811a980898255a5301b59ee25a8df9f11484f787a06011e8317cf3b694b21e8099271627b00bb8964341a86556c51305ef5ee4f585985e7e850884552b9c651671852f68934285293017d9f204a5939885950296639234950c2a562ce4556845b851e9d2ad525b35b7556847e42a414590a05c113ac657b7776bf8358e51bd5eb52238a9281885d36fd244ace6363d41b65f396c68850171a6924d172f7ff83e7c914e9d85726e46f78967824d26301a986722668d902236a5259562942b7601e20d85d1a2031f7b88422e831f764a0563394552a7ef028d70235d2878a68a337a9634652236a778a01b95bc01e9c0a5a4678d58920cf8038b9ac9a647459a1ac3a785c27fd41f8de91452501f49e9595d27e82d17f0a72a556b17801e240f9ce8122b69992d17f98ec50ba587c995c6552df75c97a6e88b01249834006571141d88e88a41b65458336341e45d8a1c9d79dc16e8f07f35788125350250cdaf20edabd7cda019767587a61c5aac053ab56924bd58478dab00250ff7adaddacda950e20bdaf202fa8c51415a96815a3096946e195983a6595be96378915baf56cf91d50e7b476b21e89f55512d9a6491a4340033f5398dd48e72d2c3ae85b37be627a781f58439558a5633a9175285ca241250556eef77d22701478d8a59242839762711b721e012f85623e8c7aea6f31678fc9222a980e763b0b2f01e116267491d56172b5a95d1b4dad917d90aa8779014982e7baaf799941f7b00891b682283036e770a0b6c8aa38522647ba739896bcd5792d17397c31f89da66f6504b49d85e371021f7db51f3dba226d34b49e85bfa0bacb7ab6b915417988dad70fb22679ea409702398c26428ab9507283863462398905b38ec26e4b0b226d8429923b51396adf75b5078422553d527d9b6b18ac65c26c83f8a529e23d341a045962a527e20849c26b6ab75ae817a489152a7937a4642078113d7e2b301868c5b367601d88aa8f52b68649b6864ab3671bfd5ec72ba29efa1aa0282b3f6179aa6823a11ae41016eb66f87113d379149339ae85b886a45c07d9de6f760035c065bec70c87b9b113d72f7a01c2b528649f31486368bea5515f9eeb5f96976e404bb11219e1190caa68446b2289e97322ac7cd50a8924689e9452a451428018b95f2b675e187c5347a67aa9054dea14175a0699722160225a94a4b717c799bb75bba5c2a26b597267db2ab95a5950652864282f7bcae19d474c48da96ae1617ae88bcb8cb5211e9347cc994865178b2a5d86382e55deb379c6556a9e41e80aa6885c88788f93f6f2b89b2e7785e6b21155611bf61571678bfa428b001b97823ba7253eb29b2b5f47601aa98350dba34f82a4b9eb48653aef53633cb7bd65e5cb27553f7ce1b57aeb2f8ab965c028931cad3de948715417a896a11e56145706f21ab4c03e7b325dbb40187be4635209ba09debba3c8c385394253f31529d4cef8bb232c607f4b27ac7992b7468f8401e798dbe6cfdb015e246b276cd9b35ad8ad326613985358daf5a0f51f8538f075c2b69d64ec86daa710a32bbea995a339c5604a5282e91225165ca81bee7014d02801ecb6117cb2c6891b7ad913d7649cc94199367984016f9d3116b7a1df9fa5d41df770631a46c7553326f955b556dc527be86cf8a8b5c08da446c938830fca68b757e4df4dea1e47ecfa23015dbbd4ea2da911d1a8f786a0b3aa019c95591e44ca4f5f332885ef29154427e0c04cec2289a93462f7a99b7ac6611e88bb49ba514c9a01f8a72d6d1551a5a7a7d0176a989d791b3a7489760b1e9468b67adb12287c5f59ec1957b90a985a289d188e7a6176c65355cc8321ac2aac13279515889ea91bc96a410a9257e1202b5b61027dcf85d573bc954e0799c4551f75d6683a5c2b51f7d18d6850ba8c99bbc0918abcc1ad7d1a1595e20ca34b2a98019f1a2f9544c83b96b01e195fc70a7e4468edb9765ea57d0a6311e1dd855a880d25532189c389dd4eccfaad72b9da6624d4b8cfcd7c2aadf4e7dee9f75a27a1601117a56c17cae11948f6ce6723b65c966928ad9f57223dabbc619595706817d5655925126848786a29ef614125942670145988be017cb1a0bc4d7ba3de6532392b8fb436672b620037571e63f8f07b374c284a408003f59675fd287b462fca386288faad0532217ad3647bea89c4d527cbb6b352d3dbb242963c2c49a18ad649bc077a1b7483e7a48750030b90113b4ea5418dab39705b412bb649d69c998592ad1e2bfcb75cc796505a2f4a942684eac3121eecd7025aadb12591d6cc902dced6014d586c05286843942631a57d2347ec2930fcaeb0162a7b6681d8dde1c1ad7cb88388cf9cf776dab47e31fa40e4c8da721f7596c9604554ae366fd2933e8ab515cfe95f7653abaef90f550b17b4fcd3a0d4e6a85ab46f31e08bbccf952e9b671507c5babeddddef80136a15a764aa7fa91e40b7479722aab6ad803efdac9661916eb7918f13abc229cb1b68a1e9d69972aaa61a8edbbcb1f0cd06e05f82f0527606d8016785cbf9ea5ccc25ad42dd61298a2d4c2e69d544cca3e6e54ab774cc276a60e1576493a63a8f277cbb882cbe95b375f9307c3deba2b6c5ca6662e3226c5aceeb692702a1a1eaa4ebac7b882d7d49f4493edf58015b8fbdc11125ec88dcd5b595029b1199af7b69d2832212f3e0ab99149a98a3eb07998d7dbc0ac85281095a8dd8f5b9016a01a7cdd6aba98d1aba59cd3b9c27deec91179ad728e601dfe81928c75bbfba7b7c3d1c7fb8cd5966cbf07e2517931e1a50b244a809b3875be0f152141aefcc85a3f5acde4104572d7517083467a0b376b581cf41dfe54ecf8dd18fd819d2fae92784e1e2c86e2415ad3d8b16e0af07706365f3e757cf4db17d9a6692824348e15698a097d3b986da8638b361a8bd5366504a41c8af07716781dce31e78a23545f6eb941e0849d9501cede59b3d4ff859cad488f6da7c1e975a97d49c37462a65a7550894da975a63069cef8740a81d7579fe435df576bed7bde26c158c5ea66a8aeb7b1981fd85aeb6a0f8ced7345258b5f920c0ecc483554160668ad35d354afac07a01386f76476f7f91aafda7a8a68a03f93bd35008138f173017b5250728748ffed952050bf5452cf6c7f845af235545baf57c1188cf6af545e4efca456a0e35cbfdda8798eac3d025a8a30641cc017cf4af6f7337a33b45c70ff7728ff7967a9d5ab501ce72eaf357bf4aa462965e356180776c66cf6c7e837b5ff7afa19a2b6893d356ef001d74911b56ac49513565031624280aaf834e3f0bf444057a49582e3817268a98f0f4114388051224280294e84385055e2c2822712bc18827911389b2916dc79f2d523c6993d02c448b0d5ea42a70d8adc2a44d46a4c9a0362d458bc68efc4a03b4eccc9b2796140982f824d6af317a1d3a039a66ddaa358ad41bb211e050bd35567d0bb0796b53a06f564d8b1656aedaa37baa9d99157c65d0a68b03355a2891f36e973fd236ab27b62147b0499ed519027fe5ef52b857173e89497951d4c96db60d9ad3b85160c097ae168a43f53845d67d5fd48d84d86be09c371fc679725733dfacbb272cecc2783fcac52327f6dc3adaadc6e283a3f59b5bb13e6de97513472f393079de9475af2efd92bfec6fdd9d03b4ab297fa0d2b5a183df9e7990f95ae4e3cf2044feeb8fa04fbe8b4c4da207e3eaa7a0ba8bcf20bade13cac043dafa3e0f340d835f29a8d2abbf6c20e6c3da2db3fc7bf091ccca8affe4c3e04b9caa30f283be0abb1da3ee2934d8cb9beb27c6031d02b9f4041d6dbdc67302b4bccafbee07cafe746d093815e34255a709eaceee24a04bf1d7b60f838052c1d09c6f66c91f8c8caba5e8fb5c6b20d2f33f8742efbca452d5a5ec44fc2543d24b42bca396fc7cc83c07142daec7aebb707943c2f4dfe5c0ecd4947ac3ccd3bc0446fc5c1f62b823ccfc673ce8eb7eefabc63522f4da458cd0745d01c47c223847cb85b9283973f1d6b8c805c474c3072b6d83b10b6c405c3c013511574449ab02985fd4a404d0ca0335c1315fc67a61bad0ec7d26d64629ac907a5cfc05fe69485dc30deaacdc051556c53b5c67b6c5a0d45e2bc54dfaeb43d259adfbc23b6feba11f5957b4b7bcb7acfc12f0508bb538bdb15fe3c35ade2be5c7f16b5d4c8059b033e5dcaf5ae44dab8f5c012594fd488dbd66bb5e3d2e39d36471dba17a453555d43e2e2bd4a7395c511b4471e48dab693befcc59b5f21659571d29773d6b742051b51504a478cb83c4ca4dd8399e053058afa5cf8d4a33bee31dd9ad74503bd6f6940b79cdf24d95dfb4d6cc74d866a82e93314763de06704445c4b0765713dc5a8d580946457f5e57c6cbffbf47ade4fbcb7395b45ceaaf3eb77b3a5515e935d3c1fd16b8efc6ab365a3d67ec0c7fe1c44fa47acf9bd489ff5cb3f4ac3ceddecd32f46dc556a39c4f67579c1540b71fbee7ebe876d29e6f35856c56a7cb6e3f4044b9c682d869df151f047729947475e56396c5184147d3feea79d6f6a5d65f877a93be3bb14cb53cd9616ec7bc267f54ae93ed676fd9f463dfeef2325241e23654e291bd2831521416ea95ebb3f02eefcd7d828d0ed614b0af812e6958f20650dee4fe2c903f0975ca5c1c90e6bba80e2aea4124ee909c386b2b99a5ac4c0c4b0ede25e1ba813c2e6dc3dec374a66320b859a97e8b1b50ac28c821069c253c124a9b78b7234b6dcf8e6504ad9582278cb0254f2c6014d398034513b1a5f8e56fcbff06bc55fc2a71be646d9aef4c03d5cf1a220036859a9719e4c76bbcf520588263b818fc23a2c9590a4d56896e89e6b4cb31c19a0e21a96558ca88ab22c020b37184cc9a52d238ced031765c9281d6c6d5a49e2eefea5bfac953d6766a305d8bce456bcec8d6156c1da938417e33291af072ff214db0bd6e7a44ed09f40ebd3278ef823455642b18544bfd9cefef6fb4635fca179837f960dc221a1a1d2f794c2e89427474b1932bc0b7583cc1101f75a90e92359644ac9df03a8aca076fb4b55db6f87fc498342a12aa442f370a405d8829edd53738e89b2d9d095fa2ee4e0328502afdcc207cead35da2352c2fbd23f972ac4e86fc13d63e21bf656202d3a83755ce4ec14aa58cfc179dbca612b8325b8161b4f2ebda486f105259e19564a4660db50fb0bd52df3e6bee83ba6afd3e3d6e838f1d5654e6b5a3de5ac3f0646b69a9a4d5262a9d1d06953549dc0dd580342592759dd4532bf4d8dfa81a5c07744c4c5fd0565c473e43919c4b64a5c4d2492375b1de79c4fc557ac7773971857a4bb4b317da98714dc8a68666ef9c1aa7d4b877417d70369e4c5e19e29a61520945d845e2bf8d5f677f3be9757744d1d850d8fa5156454f63a60458adea07e51819bb6985f397acfa16fda2a8d1d58a0b3e9537b7295ea20d6c956326abc054da3035a1ba8e03f89cc84b1a5db8239e724d7bee43391657da9d6a876d28d2d4fae2341e045696f99ed2dc4a98cd158ec192b5c3e929448c57a9e6cf950a51995dba58adb9e3f8863405911b5b41d05ae2d5af75c820e4a8d72cad005740e94d11faca42c11117887964b5a121d9bbc67aa2fd97b582238cf7fa5236ac034e94a1e0fa49d7cfe6059ba3daf0a9cc0938d7a59645bf542be339f632bfcac7767e523e17d47894b061d3dbb991e36e917c84c055175ecaa77c729f595c95d403361673e2f0661d152fc08a7876961c726481b554625a09b170c9ac6879eaa36901a5da7e9b8d5fcef4e6908000129f4010a000ff00c2000000000910f4000080ef0059d2318ac80e04385070e1458909022c78c012a3c884172a5c5871b126cd8a1b3a44e8f1d365409325466c0982b46ac39a2b52bc794216a9c894376adc595317adc564c4021b18f35951b283497af40a3078a05f974595055a54b72f44ab479a1d9ae4392156a85f9e6dba14dba559a165be8d6a263a2a53ba6bb2b5ea56ba6bd8b051e25dab06fee752ba7fcab59b673b20ecb281f2fd2cb77de0e3c96307362cf891fb58c395277468891166edca9b337efce93438e1d2ab439e3d6a353ae5daab53be7dea363ce9d2bb63d60d5c4befcddb478ee63a34d7f4de91c3b2fe2efb98f2d4edbd830f5e3cb93374e1d9af178e7d587677eac5bf37fedd9befb4fae8dfbb87be6e7a79f0fae1cf8fdedefcfaf7f9e9cbb74fcedebcfbf3f1f3dfcf25514a3d08e25e450ed4702182392860e2890e38e0648d0e4880a4851258c0e58a166841975a5d78655885498840d88626988228872aa892298c2eb8e26c8b2ac8d2ec8636d8832c873ae8932d8c3ef8e3609b3a09d3e09646198420933265f7954126057555585d39a0508a4d49322496562414159c5949d5669552a8d497915e5916214a529985aa936a95d62557627970989f52a957ab9772d9f59063769967ef917af9b520aa7a0a96ac958e0ab62c99821ac6e3ad8289976e9805e6e1e6801268b9a6a616680a67a1ae7a2a69a4ae9ac92aae96aa93d8855e14efa9978e5545a51da361655c1ea7beda3b6359bacaabadafbe78fb5371cafa745fa7caea3c5da8ca0b9ca3bbc20bac65b4ce4b2d25b9de6bcb27b3c67b6ca5b0ee7b4e64b1ea7b6e69bea6371ba49aae8acaeaa2f2cb3fa9a1f2db8fadb5febbaf6ebf2d5947679c01f76ed954d1475e126cc5474e5e51e1bb707d5ed9372e9b57dd3750ba511b2cf79b7c0f5cc7d3c5cd8708d4c5ce2c5618c60f2642b0790b7582b3ce7d670132c2135c72f7c849aca179cd09da926087f6fb443fb64f0d74feb84f2da473def23d0fa0c6057935fba8c2ab7deea5e66d0d24bc5f3b75b6d0633b2636be220b7ee9df5b7d56b8bb22adb57bd85bcd96fbdb678de5bbd14fefdd467edcda26b0d23c86784390de920cc9a4d81e8891249baa1ea022ea9a2eb123ed9a3ec024e01a4e4025e30a5e6126ef0a3ef66f4735b5e3359cb57c83f8932fc581f6993bfc2653c29dae96abc685dcb3356f2bbec2bde82ece737dea2b5c485bc98dbee62eea7dce91bd5acdc94cf65ab70c337fe7892f9db3432366c3dde0571d3e72df4b3d4e3af6e7af7e7bfce73ba1d2c5ad6d5cadadc627fa2ad7f3cf0fbdf8f71bdfb6acef0085f310eff89450440e003f795b50a69895f0c306abc08b0c90a2052810cb0eefc2811cd0660b388f3e0230348f1c11660f76b51fc4fe2443b12d5ca643e24cc4c0ba62a991a5de3363410a76278c4ad12c0f78ef534022e0588e3c02a1178874c22221798a4c62e66878619571344c22110cc57ca881943954256f5203d61776d5443d71d83164e2d81177ed3336611c8152f2ea19c8d6413eb11d869a632558e8924b3a060f8e6c680713e8a64f32b1304d74d31f15e8284832121196840b4a11e26c2e35ea2e76b28227680881994221fc66a970606a42a0c0b586c3946bcc0e82c6b9c7b572f68781052923353a465288c49c224561193924c649b0f5841c015c2578f241d1a0917d998b061779234b3295eb44bc679321321a9ba1121a9c118d5519a97810d53312915a66ac09b9d0986240d944dc0a9e0bc9319c6664a22cd43c182bd94ecec8433e9911b6e84e720aef892da13f90b458cdc29980935082241c72ddc311736db5b4e0965471f566681a7d2776a1b488c44696b243ffc491241e7dba57a75af035892c20a00500e3473f1201507dd3d0aa2dec464992254e3084f50d703792be233ea465c2db21a0e3c412b0508504d4f340a00920558a9e43b044c879493a2259d4a72755e72c9d29ffd53d328e95943f036835e8c57489c110e9bcc1465567685138ac80583538ab0850c4d8462ec7be1ca622651cca3f58c78710b538ad70fc5442bae29daaf9a121a871c84f0b508a9605a0bd6d0a2f570b275066548f0e8d504a0e4abb49cd3496702aa767b6b74bc9e5805b93ccda4205e9a33c32768977db27ea0b83871aefaa91d0b35056892af042d924f0ba9b74e8655d16fc4f822fc893092c656d4ab550de25f3bd9d59a0807bd851a2431abe8d1aed4fb886be3447b0082a311b0506dac4d013e4140d62196cbb25ceaaadeea99cdb5c5da6bb24d405a6a6fb2dca7d8bf206ac92e500a87b63015b93ac12f2b49011354979d5ad57c2143db303235a713a1da5d905e020dd196f7b7890e192143e9bc8afab614168d0aeb0cca79241ef531339156c4109bcbc44d2ac1c682a45cf095436d3eee25c25b0ed06c7232ee8813df7ce4dbe2047be090582a8d95715c83457c0430d506492358e34859f078d7a6c9e5c591b417e833601ace165aca72f27b51cc0d2f1b3bad202e500eff7944fdb28226ee982535c2061cbb2a1a440570d4603a879a16da17413425fd217987918b5fb80a19cd4905436b6b35298c96f685c483df9f420bd0982abfb67ac072639a621c37835a817174ada43dc707862838a5ae666e602bd7eb4ea4d179953719d4fa8cd73eab25ade5ef924b22d3b58864b3292ddb903b7d6865608264a7053cd57912e4dade15695ec4cc11bd7db24ba96239a171db299dd47ce3c2f1ead8b631362dd52963b67b9fa97a1a47b74aa853fc640d619992eb9cfb0350075354af4d70f941bd13108503d59a29633f2d1dafc09cba6fb32d48e0ad3bad11960598c0b2ed29bddcffef5694ef8a91c77aabf44dd9337a9fce752766aefcf6ac8a0710e2c801cda28ded317bf25bd08ccc5c6f12419f44ccac49174d4cacb329fc9eb2fa7fc0e1edaeaabb559054f168a3332a300502fd6962b1d8d24e204b75576e548447f50db2f4f5ba6e214e476ac8247661a0a1ac5dddd69c7fa8c5c312c6ae594da48286e1319847c5ac171dea7b10aa491e95c21664fa9374e8ed49e3816bda78d92c181421a078b5879c36209636f5024e82f1e5dbd78c24dc79202d204e773230da9214e4135012f1635095035079733e3d3c24ef1ed7049b762dcc651b3d579cac8aca3bdb9c79bde418da24e71449f3d055c883e54c58f6dbc94330a0c770515e579c03255120a8c244d5dcb2e95e34ede09f6be41a6ef012d19afe9f9af92932673ec01397bb7a9241b4a04a8a1aff2f1529fa879a7144bbf2099af47af358354203fa1d55376124a477451287325697b014564084760b57f77772016a02a7c864c0335b86e310459506f71f7985ec3577197797bc07085009505e5171a87325500cd7b26476cf34c58f4747ec7435747c70405f57501bb7366311cf7028e774a39c13089856a07529c7ed7228081d38aa71258500663017c65d5501585f20b16bc01d7595847ad1527387500850977fc5aa7847b917e62d58030a0358e257643475c5126c08401868145241287454a96f206a7485126b75595907801a87d58cb1978611a65595500b06266f85a488f7201350850ef7d7b65950607538fc7922978243838556f78c86396d06a01f78885556397db15165b5b47bc0e07435984601b48c68c916770288c7b68df7e85b51a964052874e7401c85425cf5991a86226a38283a419b83255983b22888275e78853480a3334676276867394b68ac0975058801026e85b97936428e97924341a87ec6c93868350893ac07588459a8ed7e72b48ad70e8ed80f33f7885108261a872505922020e8587463a988d4682d344535011d55988d8e01ac7df8064837e85017806487f20af7081401f187b80931f7e97991ec7da7e17c25501868f48d72ed76a7fd8416c65b00770277ce8a713e85b6103f277362019d8b989644287a05002781b5eef181d5e372041f7625ba6c01a87b97ee55c05565b55413413770e8a97de7d582016b7ad5e95a268856a0711a398f8eb1e390c7b75e65096131e83ba6341b759504c1705f496d7a51dd8d914d5f291344619371787346d8533a962876d5f24e08aa7c294199053523d72381116273b8c47b756d5f37ce5ee2937b00625e83289f352153223d70c7309ee7824d175374a5c898a61172889977d8965ce27577b84340d7cf89f3f18479dc4f09d34f78e52d53676c016b7de5752850885af75922431181d50295473689f3d91b758570d4f09911f58097093be2f09e83287d72005377b24eb8fc75c2eb8b96ee51167c7035cb9b33ca8a47972ac7245b381e890ef8501e29f87236c38885cd5839456c65da95b6ad44c03984d83728988853116a04254e8fc1b47ec7cd5811a980898255a5301b59ee25a8df9f11484f787a06011e8317cf3b694b21e8099271627b00bb8964341a86556c51305ef5ee4f585985e7e850884552b9c651671852f68934285293017d9f204a5939885950296639234950c2a562ce4556845b851e9d2ad525b35b7556847e42a414590a05c113ac657b7776bf8358e51bd5eb52238a9281885d36fd244ace6363d41b65f396c68850171a6924d172f7ff83e7c914e9d85726e46f78967824d26301a986722668d902236a5259562942b7601e20d85d1a2031f7b88422e831f764a0563394552a7ef028d70235d2878a68a337a9634652236a778a01b95bc01e9c0a5a4678d58920cf8038b9ac9a647459a1ac3a785c27fd41f8de91452501f49e9595d27e82d17f0a72a556b17801e240f9ce8122b69992d17f98ec50ba587c995c6552df75c97a6e88b01249834006571141d88e88a41b65458336341e45d8a1c9d79dc16e8f07f35788125350250cdaf20edabd7cda019767587a61c5aac053ab56924bd58478dab00250ff7adaddacda950e20bdaf202fa8c51415a96815a3096946e195983a6595be96378915baf56cf91d50e7b476b21e89f55512d9a6491a4340033f5398dd48e72d2c3ae85b37be627a781f58439558a5633a9175285ca241250556eef77d22701478d8a59242839762711b721e012f85623e8c7aea6f31678fc9222a980e763b0b2f01e116267491d56172b5a95d1b4dad917d90aa8779014982e7baaf799941f7b00891b682283036e770a0b6c8aa38522647ba739896bcd5792d17397c31f89da66f6504b49d85e371021f7db51f3dba226d34b49e85bfa0bacb7ab6b915417988dad70fb22679ea409702398c26428ab9507283863462398905b38ec26e4b0b226d8429923b51396adf75b5078422553d527d9b6b18ac65c26c83f8a529e23d341a045962a527e20849c26b6ab75ae817a489152a7937a4642078113d7e2b301868c5b367601d88aa8f52b68649b6864ab3671bfd5ec72ba29efa1aa0282b3f6179aa6823a11ae41016eb66f87113d379149339ae85b886a45c07d9de6f760035c065bec70c87b9b113d72f7a01c2b528649f31486368bea5515f9eeb5f96976e404bb11219e1190caa68446b2289e97322ac7cd50a8924689e9452a451428018b95f2b675e187c5347a67aa9054dea14175a0699722160225a94a4b717c799bb75bba5c2a26b597267db2ab95a5950652864282f7bcae19d474c48da96ae1617ae88bcb8cb5211e9347cc994865178b2a5d86382e55deb379c6556a9e41e80aa6885c88788f93f6f2b89b2e7785e6b21155611bf61571678bfa428b001b97823ba7253eb29b2b5f47601aa98350dba34f82a4b9eb48653aef53633cb7bd65e5cb27553f7ce1b57aeb2f8ab965c028931cad3de948715417a896a11e56145706f21ab4c03e7b325dbb40187be4635209ba09debba3c8c385394253f31529d4cef8bb232c607f4b27ac7992b7468f8401e798dbe6cfdb015e246b276cd9b35ad8ad326613985358daf5a0f51f8538f075c2b69d64ec86daa710a32bbea995a339c5604a5282e91225165ca81bee7014d02801ecb6117cb2c6891b7ad913d7649cc94199367984016f9d3116b7a1df9fa5d41df770631a46c7553326f955b556dc527be86cf8a8b5c08da446c938830fca68b757e4df4dea1e47ecfa23015dbbd4ea2da911d1a8f786a0b3aa019c95591e44ca4f5f332885ef29154427e0c04cec2289a93462f7a99b7ac6611e88bb49ba514c9a01f8a72d6d1551a5a7a7d0176a989d791b3a7489760b1e9468b67adb12287c5f59ec1957b90a985a289d188e7a6176c65355cc8321ac2aac13279515889ea91bc96a410a9257e1202b5b61027dcf85d573bc954e0799c4551f75d6683a5c2b51f7d18d6850ba8c99bbc0918abcc1ad7d1a1595e20ca34b2a98019f1a2f9544c83b96b01e195fc70a7e4468edb9765ea57d0a6311e1dd855a880d25532189c389dd4eccfaad72b9da6624d4b8cfcd7c2aadf4e7dee9f75a27a1601117a56c17cae11948f6ce6723b65c966928ad9f57223dabbc619595706817d5655925126848786a29ef614125942670145988be017cb1a0bc4d7ba3de6532392b8fb436672b620037571e63f8f07b374c284a408003f59675fd287b462fca386288faad0532217ad3647bea89c4d527cbb6b352d3dbb242963c2c49a18ad649bc077a1b7483e7a48750030b90113b4ea5418dab39705b412bb649d69c998592ad1e2bfcb75cc796505a2f4a942684eac3121eecd7025aadb12591d6cc902dced6014d586c05286843942631a57d2347ec2930fcaeb0162a7b6681d8dde1c1ad7cb88388cf9cf776dab47e31fa40e4c8da721f7596c9604554ae366fd2933e8ab515cfe95f7653abaef90f550b17b4fcd3a0d4e6a85ab46f31e08bbccf952e9b671507c5babeddddef80136a15a764aa7fa91e40b7479722aab6ad803efdac9661916eb7918f13abc229cb1b68a1e9d69972aaa61a8edbbcb1f0cd06e05f82f0527606d8016785cbf9ea5ccc25ad42dd61298a2d4c2e69d544cca3e6e54ab774cc276a60e1576493a63a8f277cbb882cbe95b375f9307c3deba2b6c5ca6662e3226c5aceeb692702a1a1eaa4ebac7b882d7d49f4493edf58015b8fbdc11125ec88dcd5b595029b1199af7b69d2832212f3e0ab99149a98a3eb07998d7dbc0ac85281095a8dd8f5b9016a01a7cdd6aba98d1aba59cd3b9c27deec91179ad728e601dfe81928c75bbfba7b7c3d1c7fb8cd5966cbf07e2517931e1a50b244a809b3875be0f152141aefcc85a3f5acde4104572d7517083467a0b376b581cf41dfe54ecf8dd18fd819d2fae92784e1e2c86e2415ad3d8b16e0af07706365f3e757cf4db17d9a6692824348e15698a097d3b986da8638b361a8bd5366504a41c8af07716781dce31e78a23545f6eb941e0849d9501cede59b3d4ff859cad488f6da7c1e975a97d49c37462a65a7550894da975a63069cef8740a81d7579fe435df576bed7bde26c158c5ea66a8aeb7b1981fd85aeb6a0f8ced7345258b5f920c0ecc483554160668ad35d354afac07a01386f76476f7f91aafda7a8a68a03f93bd35008138f173017b5250728748ffed952050bf5452cf6c7f845af235545baf57c1188cf6af545e4efca456a0e35cbfdda8798eac3d025a8a30641cc017cf4af6f7337a33b45c70ff7728ff7967a9d5ab501ce72eaf357bf4aa462965e356180776c66cf6c7e837b5ff7afa19a2b6893d356ef001d74911b56ac49513565031624280aaf834e3f0bf444057a49582e3817268a98f0f4114388051224280294e84385055e2c2822712bc18827911389b2916dc79f2d523c6993d02c448b0d5ea42a70d8adc2a44d46a4c9a0362d458bc68efc4a03b4eccc9b2796140982f824d6af317a1d3a039a66ddaa358ad41bb211e050bd35567d0bb0796b53a06f564d8b1656aedaa37baa9d99157c65d0a68b03355a2891f36e973fd236ab27b62147b0499ed519027fe5ef52b857173e89497951d4c96db60d9ad3b85160c097ae168a43f53845d67d5fd48d84d86be09c371fc679725733dfacbb272cecc2783fcac52327f6dc3adaadc6e283a3f59b5bb13e6de97513472f393079de9475af2efd92bfec6fdd9d03b4ab297fa0d2b5a183df9e7990f95ae4e3cf2044feeb8fa04fbe8b4c4da207e3eaa7a0ba8bcf20bade13cac043dafa3e0f340d835f29a8d2abbf6c20e6c3da2db3fc7bf091ccca8affe4c3e04b9caa30f283be0abb1da3ee2934d8cb9beb27c6031d02b9f4041d6dbdc67302b4bccafbee07cafe746d093815e34255a709eaceee24a04bf1d7b60f838052c1d09c6f66c91f8c8caba5e8fb5c6b20d2f33f8742efbca452d5a5ec44fc2543d24b42bca396fc7cc83c07142daec7aebb707943c2f4dfe5c0ecd4947ac3ccd3bc0446fc5c1f62b823ccfc673ce8eb7eefabc63522f4da458cd0745d01c47c223847cb85b9283973f1d6b8c805c474c3072b6d83b10b6c405c3c013511574449ab02985fd4a404d0ca0335c1315fc67a61bad0ec7d26d64629ac907a5cfc05fe69485dc30deaacdc051556c53b5c67b6c5a0d45e2bc54dfaeb43d259adfbc23b6feba11f5957b4b7bcb7acfc12f0508bb538bdb15fe3c35ade2be5c7f16b5d4c8059b033e5dcaf5ae44dab8f5c012594fd488dbd66bb5e3d2e39d36471dba17a453555d43e2e2bd4a7395c511b4471e48dab693befcc59b5f21659571d29773d6b742051b51504a478cb83c4ca4dd8399e053058afa5cf8d4a33bee31dd9ad74503bd6f6940b79cdf24d95dfb4d6cc74d866a82e93314763de06704445c4b0765713dc5a8d580946457f5e57c6cbffbf47ade4fbcb7395b45ceaaf3eb77b3a5515e935d3c1fd16b8efc6ab365a3d67ec0c7fe1c44fa47acf9bd489ff5cb3f4ac3ceddecd32f46dc556a39c4f67579c1540b71fbee7ebe876d29e6f35856c56a7cb6e3f4044b9c682d869df151f047729947475e56396c5184147d3feea79d6f6a5d65f877a93be3bb14cb53cd9616ec7bc267f54ae93ed676fd9f463dfeef2325241e23654e291bd2831521416ea95ebb3f02eefcd7d828d0ed614b0af812e6958f20650dee4fe2c903f0975ca5c1c90e6bba80e2aea4124ee909c386b2b99a5ac4c0c4b0ede25e1ba813c2e6dc3dec374a66320b859a97e8b1b50ac28c821069c253c124a9b78b7234b6dcf8e6504ad9582278cb0254f2c6014d398034513b1a5f8e56fcbff06bc55fc2a71be646d9aef4c03d5cf1a220036859a9719e4c76bbcf520588263b818fc23a2c9590a4d56896e89e6b4cb31c19a0e21a96558ca88ab22c020b37184cc9a52d238ced031765c9281d6c6d5a49e2eefea5bfac953d6766a305d8bce456bcec8d6156c1da938417e33291af072ff214db0bd6e7a44ed09f40ebd3278ef823455642b18544bfd9cefef6fb4635fca179837f960dc221a1a1d2f794c2e89427474b1932bc0b7583cc1101f75a90e92359644ac9df03a8aca076fb4b55db6f87fc498342a12aa442f370a405d8829edd53738e89b2d9d095fa2ee4e0328502afdcc207cead35da2352c2fbd23f972ac4e86fc13d63e21bf656202d3a83755ce4ec14aa58cfc179dbca612b8325b8161b4f2ebda486f105259e19564a4660db50fb0bd52df3e6bee83ba6afd3e3d6e838f1d5654e6b5a3de5ac3f0646b69a9a4d5262a9d1d06953549dc0dd580342592759dd4532bf4d8dfa81a5c07744c4c5fd0565c473e43919c4b64a5c4d2492375b1de79c4fc557ac7773971857a4bb4b317da98714dc8a68666ef9c1aa7d4b877417d70369e4c5e19e29a61520945d845e2bf8d5f677f3be9757744d1d850d8fa5156454f63a60458adea07e51819bb6985f397acfa16fda2a8d1d58a0b3e9537b7295ea20d6c956326abc054da3035a1ba8e03f89cc84b1a5db8239e724d7bee43391657da9d6a876d28d2d4fae2341e045696f99ed2dc4a98cd158ec192b5c3e929448c57a9e6cf950a51995dba58adb9e3f8863405911b5b41d05ae2d5af75c820e4a8d72cad005740e94d11faca42c11117887964b5a121d9bbc67aa2fd97b582238cf7fa5236ac034e94a1e0fa49d7cfe6059ba3daf0a9cc0938d7a59645bf542be339f632bfcac7767e523e17d47894b061d3dbb991e36e917c84c055175ecaa77c729f595c95d403361673e2f0661d152fc08a7876961c726481b554625a09b170c9ac6879eaa36901a5da7e9b8d5fcef4e6908000b3
197EOL
198
199
200
201use DBI;
202
203
204
205
206
207
208
209
210
211
212$way="";
213#######
214## se houver cookie login então verifica se o cookie lid( login id) consta na base de dados e se o tempo de login
215## é inferior ao tempo-300s (caso tenham passado 5 minutos o login deixa de ser valido
216## se tudo estiver correcto então actualiza a data do ultimo acesso na table de utilizadores e activa a variavel $way
217## para logged
218if($COOKIE{login}) {
219 $db=DBI->connect("dbi:$dbdriver:dbname=$dbname","$dbuser","$dbpass");
220 $sth=$db->prepare("select * from userinfo where userid='\Q$COOKIE{login}\E' and lid='$COOKIE{lid}'");
221 $sth->execute;
222 if($sth->rows>0) {
223 $db->do("update userinfo set lldate='".time."' where userid='\Q$COOKIE{login}\E'");
224 if($QUERY_STRING{sair} eq $COOKIE{lid}) {
225 $db->do("update userinfo set lid='0' where userid='\Q$COOKIE{login}\E'");
226 cookie("login",$POST{username},"now");
227 cookie("lid","$lid","now");
228 } else {
229 $way="logged";
230 cookie("login",$COOKIE{username},"+5m");
231 cookie("lid","$COOKIE{lid}","+5m");
232 };
233
234 };
235 $sth->finish;
236 $db->disconnect;
237};
238if($QUERY_STRING{adduser}) {
239 $way="adduser";
240};
241
242
243
244########
245## metodo login se for enviado o pedido de login então vai verificar se a entrada username & password consta na
246## base de dados se constar então actualiza a base de dados com o novo login id (lid) e activa o cookie login e loginid
247## Se o login tiver activo manda uma resposta ao utilizador indicando que não pode refazer o login até estar
248## desactivo, excepto se o login id for diferente (problema do refresh)
249##
250if($POST{login} and $way ne "logged") {
251 $lid=int(rand()*100)+1;
252 $db=DBI->connect("dbi:$dbdriver:dbname=$dbname","$dbuser","$dbpass");
253 $sth=$db->prepare("select * from userinfo where userid='\Q$POST{username}\E' and password='\Q$POST{passwd}\E'");
254 $sth->execute;
255 if($sth->rows>0) {
256 $res=$sth->fetchrow_hashref;
257 if(time>($res->{lldate}+300) or $res->{lid} eq "0") {
258 cookie("login",$POST{username},"+5m");
259 cookie("lid","$lid","+5m");
260 $db->do("update userinfo set lid='$lid', lldate='".time."' where userid='\Q$POST{username}\E'");
261 $COOKIE{login}=$POST{username};
262 $COOKIE{lid}=$lid;
263 $way="logged";
264 } else {
265 $errorway="norelogin";
266 };
267
268 }else {
269 $errorway="invalidlog";
270 };
271 $sth->finish;
272 $db->disconnect;
273
274};
275cookie("teste1",$POST{username},"+5m");
276cookie("teste4","conas","+10m");
277if($POST{adduser}) {
278 $way="adduser";
279 if($POST{passwd} ne $POST{repasswd}) {
280 $errorway="nomatch";
281 } else {
282 if($POST{username} eq "") {
283 $errorway="emptylogin";
284 } else {
285 $db=DBI->connect("dbi:$dbdriver:dbname=$dbname","$dbuser","$dbpass");
286 $sth=$db->prepare("select * from userinfo where userid='\Q$POST{username}\E'");
287 $sth->execute;
288 if($sth->rows>0) {
289 $errorway="exists";
290 } else {
291 $db->do("insert into userinfo (userid,password,nome,email,phone) values('\Q$POST{username}\E','\Q$POST{passwd}\E','\Q$POST{name}\E','\Q$POST{email}\E','\Q$POST{phone}\E')");
292 enviarnoticia("Bem vindo ao $softversion, Está a iniciar como novo utilizador e provavelmente precisa de ajuda, o sistema irá mandar dicas através das noticias, por agora tente criar a sua equipe pelo menu equipe e depois escolha os jogadores..., foram debitados 2000cts na sua conta principal(nota: AS NOTICIAS SERAO AUTO-REMOVIDAS DEPOIS DE 10Minutos DA SUA DATA DE LEITURA)",$POST{username});
293 do {
294 $id=int(rand()*200000);
295 $sth=$db->prepare("select * from conta where id='$id'");
296 $sth->execute;
297 }while($sth->rows);
298 $db->do("insert into conta (id,userid,value) values('\Q$id\E','\Q$POST{username}\E','2000')");
299 $way="";
300 };
301 };
302 };
303};
304
305
306
307
308#COOKIES
309#print "Date: ".mydate("%a, %d %b %Y %H:%M:%S %Z",0)."\n";
310#print "Cona: ".mydate("%a, %d %b %Y %H:%M:%S %Z",0)."\n";
311
312## este metedo apenas indica para o carregamento de imagens se o parametro img tiver ligado então uploada
313## a imagem escolhida
314##
315if($QUERY_STRING{img}) {
316 #print "Accept-ranges: bytes\n";
317 #print "Content-length: ".length($img{$QUERY_STRING{img}})."\n";
318 print "Content-type: image/gif\r\n\r\n";
319 print pack("h*",$img{$QUERY_STRING{img}});
320 exit;
321};
322
323
324
325## ---------------------------------------------- FUNCOES ----------------------------------------##
326## funcoes especificas
327## imprime a página do login
328##
329sub printlogin {
330 print "<HTML>\n<HEAD>\n<TITLE> footaid login</title>\n</HEAD>\n";
331 print "<BODY background='$ENV{SCRIPT_NAME}?img=bg'>\n";
332 print "<FORM METHOD='POST' ACTION='$ENV{SCRIPT_NAME}'>\n";
333 print "<TABLE width=100% cellspacing=0 height='100%' border=0>\n";
334 print "<TR><TD bgcolor='bb8800' height=90 align=center valign='center'>\n";
335 print "<table width=400 height=80 border=0 bgcolor='efefef'><TR><TD><img src='$ENV{SCRIPT_NAME}?img=logo'></TD></TR></TABLE>\n";
336 print "</TD></TR>\n";
337 print "<TR><TD valign='center' align='center' height=100% bgcolor='008800'>\n";
338 print "<font color='FF0000'>Terá de terminar a outra sessão ou esperar 5 minutos</font><BR><BR>" if ($errorway eq "norelogin");
339 print "<font color='FF0000'>Login inválido</font><BR><BR>" if ($errorway eq "invalidlog");
340 print "<TABLE bgcolor='000000' cellspacing=2 cellpadding=0><TR><TD>\n";
341 print "<TABLE border=0 cellspacing=0 cellpadding=3 bgcolor='EFEFEF'>\n";
342 print "<TR><TD> Login:</TD><TD><input type=text name='username' size=14 maxlength=14 value='$COOKIE{username}'></TD></TR>\n";
343 print "<TR><TD> Password:</TD><TD><input type=password name='passwd' size=14 maxlength=14></TD></TR>\n";
344 print "<TR><TD colspan=2 align=left><table border=0 cellpadding=0 cellspacing=0><TR><TD><input type=submit name='login' value='Entrar'></TD><TD><input type=button onclick='parent.location=\"$ENV{SCRIPT_NAME}?adduser=1\"' value='Adicionar utilizador'></TD></TR></TABLE></TD></TR>\n";
345 print "</TABLE>\n";
346 print "</TD></TR></TABLE>\n";
347 print "</TD></TR>\n";
348 print "</TABLE>\n";
349 print "</FORM>\n";
350 print "</BODY>\n</HTML>";
351};
352## pagina adicionar utilizador
353##
354##
355sub printadduser {
356 print "<HTML>\n<HEAD>\n<TITLE> footaid login</title>\n</HEAD>\n";
357 print "<BODY background='$ENV{SCRIPT_NAME}?img=bg'>\n";
358 print "<TABLE width=100% cellspacing=0 height='100%' border=0>\n";
359 print "<TR><TD bgcolor='bb8800' height=90 align=center valign='center'>\n";
360 print "<table width=400 height=80 border=0 bgcolor='efefef'><TR><TD><img src='$ENV{SCRIPT_NAME}?img=logo'></TD></TR></TABLE>\n";
361 print "</TD></TR>\n";
362 print "<TR><TD valign='center' align='center' height=100% bgcolor='008800'>\n";
363 print "<FORM METHOD='POST' ACTION='$ENV{SCRIPT_NAME}'>\n";
364 print "<font color='ff0000'>Login já existente por favor escolha outro</font>" if ($errorway eq "exists");
365 print "<font color='ff0000'>Password não é igual</font>" if ($errorway eq "nomatch");
366 print "<font color='ff0000'>O campo login não pode estar vazio</font>" if ($errorway eq "emptylogin");
367 print "<TABLE bgcolor='000000' cellspacing=2 cellpadding=0><TR><TD>\n";
368 print "<TABLE border=0 cellspacing=0 cellpadding=3 bgcolor='EFEFEF'>\n";
369 print "<TR><TD> ";
370 print ."<font color='FF0000'>*</font>" if ($errorway eq "exists");
371 print "Login: </TD><TD><input type=text name='username' size=14 maxlength=13 value='$POST{username}'></TD></TR>\n";
372 print "<TR><TD> Nome de utilizador:</TD><TD><input type=text name='name' value='$POST{name}'></TD></TR>\n";
373 print "<TR><TD> E-mail:</TD><TD><input type=text name='email' maxlength=160 value='$POST{email}'></TD></TR>\n";
374 print "<TR><TD> Telefone:</TD><TD><input type=text name='phone' maxlenght=13 value='$POST{phone}'></TD></TR>\n";
375 print "<TR><TD> Password:</TD><TD><input type=password name='passwd' size=14 maxlength=14></TD></TR>\n";
376 print "<TR><TD> Re-Password:</TD><TD><input type=password name='repasswd' size=14 maxlength=14></TD></TR>\n";
377 print "<TR><TD colspan=2 align=left><table border=0 cellspacing=0 cellpadding=0><TR><TD><input type=button onclick='parent.location=\"$ENV{SCRIPT_NAME}?\&rid=".int(rand()*100)."\"' value='<- Voltar'></TD><TD><input type=submit name='adduser' value='adicionar'></TD></TR></TABLE></TD></TR>\n";
378 print "</TABLE>\n";
379 print "</TD></TR></TABLE>\n";
380 print "</FORM>\n";
381 print "</TD></TR>\n";
382 print "</TABLE>\n";
383
384};
385
386
387## enviar noticia
388## funcção enviar noticia;
389sub enviarnoticia {
390 $noticia=shift;
391 $useridto=shift;
392 if(!$useridto) {
393 $sth=$db->prepare("select * from userinfo");
394 $sth->execute;
395 while($res=$sth->fetchrow_hashref) {
396 $useridto=$res->{userid};
397 do {
398 $id=int(rand()*200000);
399 $sth1=$db->prepare("select * from noticia where id='$id'");
400 $sth1->execute;
401 }while($sth1->rows);
402 $db->do("insert into noticia (id,useridto,noticia,date) values('\Q$id\E','\Q$useridto\E','\Q$noticia\E','".time()."')");
403 };
404 }else {
405 do {
406 $id=int(rand()*200000);
407 $sth1=$db->prepare("select * from noticia where id='$id'");
408 $sth1->execute;
409 }while($sth1->rows);
410 $db->do("insert into noticia (id,useridto,noticia,date) values('\Q$id\E','\Q$useridto\E','\Q$noticia\E','".time()."')");
411 };
412
413};
414
415## subfuncção game (pagina inicial)
416## é aqui que decorre a 'acção' do jogo
417##
418sub game {
419## Menu de cima com os icons
420##
421 $db=DBI->connect("dbi:$dbdriver:dbname=$dbname","$dbuser","$dbpass");
422 $sth=$db->prepare("select * from userinfo where userid='\Q$COOKIE{login}\E'");
423 $sth->execute;
424 $res=$sth->fetchrow_hashref;
425 print "<HTML><HEAD><TITLE>$softversion\n</TITLE></HEAD>\n";
426 print "<BODY background='$ENV{SCRIPT_NAME}?img=bg' bgcolor=111111>\n";
427 print "<font face='Verdana' color='FFFF00'>\n";
428 print "<TABLE width=100% border=0 bgcolor='008800'>\n";
429 print "<TR><TD bgcolor='bb8800' height=90 align=center valign='center'>\n";
430 print "<table width=400 height=80 border=0 bgcolor='efefef'><TR><TD><img src='$ENV{SCRIPT_NAME}?img=logo'></TD></TR></TABLE>\n";
431 print "</TD></TR>\n";
432 print "<TR><TD height='20px' bgcolor='EFEFEF' valign='center'>\n";
433 print "<TABLE border=0 height='20px' cellspacing=1 cellpadding=0><TR>";
434 print "<TD>Football menu:\&nbsp;\&nbsp;</TD>\n";
435 print "<TD>[</TD>\n";
436 print "<TD bgcolor='CFCFDF'><a href='$ENV{SCRIPT_NAME}?rid=".int(rand()*100)."'><img width=20 height=20 border=0 alt='Inicio' src='$ENV{SCRIPT_NAME}?img=home'></a></TD>\n";
437 print "<TD bgcolor='CFCFDF'><a href='$ENV{SCRIPT_NAME}?subway=msg'><img width=20 height=20 border=0 alt='mensagens' src='$ENV{SCRIPT_NAME}?img=msg'></a></TD>\n";
438 print "<TD bgcolor='CFCFDF'><a href='$ENV{SCRIPT_NAME}?subway=forum'><img width=20 height=20 border=0 alt='forum' src='$ENV{SCRIPT_NAME}?img=forum'></a></TD>\n";
439 print "<TD bgcolor='CFCFDF'><a href='$ENV{SCRIPT_NAME}?sair=$COOKIE{lid}'><img width=20 height=20 border=0 alt='sair' src='$ENV{SCRIPT_NAME}?img=sair'></a></TD>\n";
440 print "<TD>][</TD>\n";
441 print "<TD bgcolor='CFCFDF'><a href='$ENV{SCRIPT_NAME}?subway=conta'><img width=20 height=20 border=0 alt='conta' src='$ENV{SCRIPT_NAME}?img=conta'></a></TD>\n";
442 print "<TD bgcolor='CFCFDF'><a href='$ENV{SCRIPT_NAME}?subway=team'><img width=20 height=20 border=0 alt='equipa' src='$ENV{SCRIPT_NAME}?img=equipa'></a></TD>\n";
443 print "<TD bgcolor='CFCFDF'><a href='$ENV{SCRIPT_NAME}?subway=jogador'><img width=20 height=20 border=0 alt='jogadores' src='$ENV{SCRIPT_NAME}?img=jog'></a></TD>\n";
444 print "<TD>]</TD>\n";
445 print "<TD>\&nbsp;\&nbsp;".mydate("%a, %d %b %Y %H:%M").", <font color='444444'>$COOKIE{login}</font>";
446 print "</TR></table>\n";
447 print "</TD></TR><TR><TD valign='top'><font face='Verdana' color='FFFF00'>\n";
448 $sth->finish;
449## conforme a escolha
450##
451
452### ecran conta
453##
454#
455 if($QUERY_STRING{subway} eq "conta") {
456 print "<CENTER><font size=6 face='Verdana'><B>Conta</B></font><hr></CENTER><BR><BR>\n";
457 $sth=$db->prepare("select * from conta where userid='$COOKIE{login}'");
458 $sth->execute;
459 if($sth->rows) {
460 $res=$sth->fetchrow_hashref;
461 print "Conta id: <B>$res->{id}</B> Contem um saldo de <B>$res->{value}cts</B><BR><BR>\n";
462 };
463 };
464 if($QUERY_STRING{subway} eq "jogador") {
465 if($POST{treino}) {
466 print "Treino<BR>\n";
467 $sth=$db->prepare("select * from treino where jogid='\Q$POST{nome}\E'");
468 $sth->execute;
469 if($sth->rows) {
470 print "Jogador já se encontra em treino\n";
471 } else {
472 $db->do("insert into treino (jogid,treino,fdate,date) values('\Q$POST{nome}\E','\Q$POST{what}\E','".mydate("%g","+$POST{days}d")."','".time()."')");
473 $db->do("update jogador set doing='1' where nome='\Q$POST{nome}\E'");
474 };
475
476 };
477 print "<CENTER><font size=6 face='Verdana'><B>Jogadores</B></font><hr></CENTER><BR><BR>\n";
478 if($QUERY_STRING{mostrar}) {
479 $sth=$db->prepare("select * from jogador where nome='$QUERY_STRING{mostrar}'");
480 $sth->execute;
481 if($sth->rows) {
482 $res1=$sth->fetchrow_hashref;
483 print "<FORM method='POST'>\n";
484 print "Equipa: <B>$res1->{equipaid}</B>\n";
485 print "<TABLE border=0 bgcolor='000000' cellspacing=0 cellpadding=1><TR><TD>\n";
486 print "<TABLE border=0 bgcolor='FFFFEE' cellspacing=0 cellpadding=0>\n";
487 print "<TR bgcolor='EEEEFF'><TD>Nome:</TD><TD><B>$res1->{nome}</B></TD></TR>\n";
488 print "<TR><TD>Velocidade:</TD><TD>\n";
489 for $i (0 .. 10) {
490 if($i<($res1->{vel}/100)) {
491 print "<img width=15 height=15 src='$ENV{SCRIPT_NAME}?img=redball'>\n";
492 } else {
493 print "<img width=15 height=15 src='$ENV{SCRIPT_NAME}?img=blackball'>\n";
494 };
495 };
496 print "</TD></TR>\n";
497 print "<TR><TD>Força:</TD><TD>\n";
498 for $i (0 .. 10) {
499 if($i<($res1->{forc}/100)) {
500 print "<img width=15 height=15 src='$ENV{SCRIPT_NAME}?img=redball'>\n";
501 } else {
502 print "<img width=15 height=15 src='$ENV{SCRIPT_NAME}?img=blackball'>\n";
503 };
504 };
505 print "</TD></TR>\n";
506 print "<TR><TD>Agilidade:</TD><TD>\n";
507 for $i (0 .. 10) {
508 if($i<($res1->{agi}/100)) {
509 print "<img width=15 height=15 src='$ENV{SCRIPT_NAME}?img=redball'>\n";
510 } else {
511 print "<img width=15 height=15 src='$ENV{SCRIPT_NAME}?img=blackball'>\n";
512 };
513 };
514 print "</TD></TR>\n";
515 print "<TR><TD>Eficacia:</TD><TD>\n";
516 for $i (0 .. 10) {
517 if($i<($res1->{efi}/100)) {
518 print "<img width=15 height=15 src='$ENV{SCRIPT_NAME}?img=redball'>\n";
519 } else {
520 print "<img width=15 height=15 src='$ENV{SCRIPT_NAME}?img=blackball'>\n";
521 };
522 };
523 print "</TD></TR>\n";
524 print "<TR><TD>Expriencia:</TD><TD>\n";
525 for $i (0 .. 10) {
526 if($i<($res1->{exp}/100)) {
527 print "<img width=15 height=15 src='$ENV{SCRIPT_NAME}?img=redball'>\n";
528 } else {
529 print "<img width=15 height=15 src='$ENV{SCRIPT_NAME}?img=blackball'>\n";
530 };
531 };
532 print "</TD></TR>\n";
533 print "<TR><TD>Adaptação:</TD><TD>\n";
534 for $i (0 .. 10) {
535 if($i<($res1->{fel}/100)) {
536 print "<img width=15 height=15 src='$ENV{SCRIPT_NAME}?img=redball'>\n";
537 } else {
538 print "<img width=15 height=15 src='$ENV{SCRIPT_NAME}?img=blackball'>\n";
539 };
540 };
541 print "</TD></TR>\n";
542 print "<TR><TD>Posição</TD><TD>\n";
543 $sth1=$db->prepare("select * from pos where id='$res1->{tipo}'");
544 $sth1->execute;
545 $res2=$sth1->fetchrow_hashref;
546 print "<B>$res2->{namepos}</B>\n";
547 print "</TD></TR>\n";
548 print "<TR><TD>Fazer:</TD><TD>\n";
549 $sth1->finish;
550 $sth1=$db->prepare("select * from doing where id='$res1->{doing}'");
551 $sth1->execute;
552 $res2=$sth1->fetchrow_hashref;
553 print "<B>$res2->{dowhat}</B>\n";
554 print "</TD></TR>\n";
555 $sth1->finish;
556 $sth1=$db->prepare("select * from equipa where userid='$COOKIE{login}'");
557 $sth1->execute;
558 $res=$sth1->fetchrow_hashref;
559 $sth1->finish;
560 print "<TR><TD>Ordenado:</TD><TD><B>$res1->{ordenado}cts/mês</B></TD></TR>\n";
561 print "<input type=hidden name='nome' value='$res1->{nome}'>\n";
562 if(($res1->{equipaid} eq $res->{equipaid}) and ($res1->{doing} ne "1")) {
563 print "<TR><TD colspan=2>\n";
564 print "<select name=what>\n";
565 print "<option value='vel'>Velocidade\n";
566 print "<option value='forc'>Força\n";
567 print "<option value='agi'>Agilidade\n";
568 print "<option value='efi'>Eficacia\n";
569 print "</select>\n";
570 print "Dias: <input type=text size=2 maxlength=2 name='days' value='01'>\n";
571 print "<input type=submit name='treino' value='Treinar'></TD></TR>\n";
572 }
573 if($res1->{equipaid} ne $res->{equipaid}){
574 print "<TR><TD colspan=2>Valor: <input type=text size=4 maxlength=4 name=valor value='0000'>cts <input type=submit name='comprar' value='comprar'>\n";
575 };
576 print "</TABLE>\n";
577 print "</TD></TR></TABLE><BR>\n";
578 };
579 }else {
580 print "<BR>\n";
581 $sth=$db->prepare("select * from jogador");
582 $sth->execute;
583 while($res=$sth->fetchrow_hashref) {
584 $urlname=$res->{nome};
585 $urlname =~ s/ /%20/g;
586 print "Nome: <a href='$ENV{SCRIPT_NAME}?subway=jogador\&mostrar=$urlname'><B>$res->{nome}</B></a> equipa: <B>$res->{equipaid}</B><BR>\n";
587 };
588 print "<BR>\n";
589 };
590 };
591
592### ecran equipa
593##
594#
595 if($QUERY_STRING{subway} eq "team") {
596 print "<CENTER><font size=6 face='Verdana'><B>Equipa</B></font><hr></CENTER><BR><BR>\n";
597 if($POST{criar}) {
598 $sth=$db->prepare("select * from equipa where lower(equipaid)=lower('\Q$POST{equipa}\E')");
599 $sth->execute;
600 if($sth->rows) {
601 print "<font color='FF0000'>Nome de equipa existente</font><BR>\n";
602 } else {
603 $db->do("insert into equipa (equipaid,userid) values('\Q$POST{equipa}\E','\Q$COOKIE{login}\E')");
604 };
605 };
606 if($POST{simcria}) {
607 $sth=$db->prepare("select * from jogador where lower(nome)=lower('$POST{nome}')");
608 $sth->execute;
609 if($sth->rows) {
610 print "<font color='FF0000'>Nome de jogador existente</font><BR>";
611 }else {
612 $sth=$db->prepare("select * from conta where userid='$COOKIE{login}'");
613 $sth->execute;
614 if($sth->rows) {
615 $res=$sth->fetchrow_hashref;
616 $contaval=$res->{value};
617 };
618 $val=100;
619 $val+=($POST{vel}*150);
620 $val+=($POST{for}*150);
621 $val+=($POST{agi}*150);
622 $val+=($POST{efi}*150);
623 $contaval-=$val;
624 if($contaval>0) {
625 $sth=$db->prepare("select * from equipa where userid='$COOKIE{login}'");
626 $sth->execute;
627 $res=$sth->fetchrow_hashref;
628 $db->do("insert into jogador (nome,equipaid,vel,forc,agi,efi,tipo) values('\Q$POST{nome}\E','\Q$res->{equipaid}\E','".($POST{vel}*100)."','".($POST{for}*100)."','".($POST{agi}*100)."','".($POST{efi}*100)."','$POST{pos}')");
629 $db->do("update conta set value='$contaval' where userid='$COOKIE{login}'");
630 $db->do("update equipa set jogdisp='".($res->{jogdisp}-1)."' where userid='$COOKIE{login}'");
631 enviarnoticia("$COOKIE{login} Criou o jogador $POST{nome}");
632 } else {
633 print "<font color='FF0000'>Não contem fundos suficientes para criar este jogador</font><BR>\n";
634 };
635 };
636
637 };
638 if($POST{criarjog}) {
639 if($POST{nome} ne "") {
640 $sth=$db->prepare("select * from jogador where lower(nome)=lower('$POST{nome}')");
641 $sth->execute;
642 if($sth->rows) {
643 print "<font color='FF0000'>Nome de jogador existente</font><BR>";
644 print "<form><input type=button onclick='parent.location=\"javascript:history.go(-1)\"' value='<- Voltar'><HR>\n";
645 }else {
646 $val=100;
647 $val+=($POST{vel}*150);
648 $val+=($POST{for}*150);
649 $val+=($POST{agi}*150);
650 $val+=($POST{efi}*150);
651 print "Vai gastar $val cts ao criar o jogador <B>$POST{nome}</B> deseja continuar?<BR>";
652 print "Velocidade:<B>$POST{vel}</B> Força: <B>$POST{for}</B> Agilidade: <B>$POST{agi}</B> Eficacia: <B>$POST{efi}</B><BR>\n";
653 print "<form method='POST'>\n";
654 print "<input type=hidden name=nome value='$POST{nome}'>\n";
655 print "<input type=hidden name=vel value='$POST{vel}'>\n";
656 print "<input type=hidden name=for value='$POST{for}'>\n";
657 print "<input type=hidden name=agi value='$POST{agi}'>\n";
658 print "<input type=hidden name=efi value='$POST{efi}'>\n";
659 print "<input type=hidden name=pos value='$POST{pos}'>\n";
660 print "<input type=submit name='simcria' value='sim'>";
661 print "<input type=button onclick='parent.location=\"$ENV{SCRIPT_NAME}?subway=team\&rid=".int(rand()*100)."\"' value='nao'>";
662 print "</form><HR>\n";
663 };
664 $sth->finish;
665 } else {
666 print "<font color='FF0000'>Tem que dar nome ao jogador</font><BR>";
667 print "<form><input type=button onclick='parent.location=\"javascript:history.go(-1)\"' value='<- Voltar'><HR>\n";
668 };
669 };
670 $sth=$db->prepare("select * from equipa where userid='$COOKIE{login}'");
671 $sth->execute;
672 if($sth->rows) {
673 $res=$sth->fetchrow_hashref;
674 $sth->finish;
675 print "<B>Equipa $res->{equipaid}</B><BR>\n";
676 $sth=$db->prepare("select * from jogador where equipaid='$res->{equipaid}' order by tipo ASC");
677 $sth->execute;
678 ## Mostrar jogador
679 if($sth->rows) {
680 while($res1=$sth->fetchrow_hashref) {
681 $sth1=$db->prepare("select * from pos where id='$res1->{tipo}'");
682 $sth1->execute;
683 $res2=$sth1->fetchrow_hashref;
684 $urlname=$res1->{nome};
685 $urlname=~s/ /%20/g;
686 print "\&nbsp;\&nbsp;Nome: <a href='$ENV{SCRIPT_NAME}?subway=jogador\&mostrar=$urlname'><B>$res1->{nome}</B></a> ($res2->{namepos})<BR>\n";
687 $sth1->finish;
688 };
689 $sth->finish;
690 print "<HR>\n";
691 } else {
692 print "Não se encontram jogadores na sua equipa<BR><BR>\n";
693 };
694 if($res->{jogdisp}>0) {
695 if($QUERY_STRING{criarjog}) {
696 print "<HR><B>Criar jogador</B><BR>\n";
697 print "<FORM method=post action='$ENV{SCRIPT_NAME}?subway=team'>\n";
698 print "<table bgcolor=000000 cellspacing=0 cellpadding=1><TR><TD>\n";
699 print "<TABLE bgcolor='EFEFEF' cellspacing=0 cellpadding=0>\n";
700 print "<TR><TD>Nome:</TD><TD><input type=text name='nome'></TD></TR>\n";
701 print "<TR><TD>Velocidade</TD><TD>\n";
702 for $i (0 .. 10) {
703 print "<input type=radio name='vel' value='$i'>\n";
704 };
705 print "</TD></TR>\n";
706 print "<TR><TD>Força</TD><TD>\n";
707 for $i (0 .. 10) {
708 print "<input type=radio name='for' value='$i'>\n";
709 };
710 print "</TD></TR>\n";
711 print "<TR><TD>Agilidade</TD><TD>\n";
712 for $i (0 .. 10) {
713 print "<input type=radio name='agi' value='$i'>\n";
714 };
715 print "</TD></TR>\n";
716 print "<TR><TD>Eficacia</TD><TD>\n";
717 for $i (0 .. 10) {
718 print "<input type=radio name='efi' value='$i'>\n";
719 };
720 print "</TD></TR>\n";
721 print "<TR><TD>Posição</TD><TD>\n";
722 $sth=$db->prepare("select * from pos");
723 $sth->execute;
724 print "<select name=pos>\n";
725 while($res=$sth->fetchrow_hashref) {
726 print "<option value='$res->{id}'>$res->{namepos}</option>\n";
727 };
728 print "</select>\n";
729 print "</TD></TR>\n";
730 print "<TR><TD colspan=2 align='left'><input type=button onclick='parent.location=\"$ENV{SCRIPT_NAME}?subway=team\&rid=".int(rand()*100)."\"' value='<- Voltar'><input type=submit name=criarjog value='Criar'></TD></TR>\n";
731 print "</TABLE>\n";
732 print "</TD></TR></TABLE>\n";
733 print "</form>\n";
734 print "<HR>";
735 } else {
736 print "<form><input type=button onclick='parent.location=\"$ENV{SCRIPT_NAME}?subway=team\&criarjog=1\&rid=".int(rand()*100)."\"' value='Criar jogador'></form>\n";
737 };
738 };
739 } else {
740 print "Ainda não tem ainda uma equipa, escreva os dados para cria-la<BR>\n";
741 print "<FORM method='POST' action='$ENV{SCRIPT_NAME}?subway=team'>\n";
742 print "<table border=0 cellspacing=0 cellpading=1 bgcolor='000000'><TR><TD>";
743 print "<table bgcolor='EFEFEF' cellspacing=0 cellpadding=0 border=0>\n";
744 print "<TR><TD> Nome de equipa: </TD><TD><input type=text name=equipa></TD></TR>\n";
745 print "<TR><TD colspan=2><input type=submit value='Criar' name='criar'></TD></TR>\n";
746 print "</TABLE>\n";
747 print "</TD></TR></TABLE>\n";
748 print "</FORM>\n";
749
750 };
751 };
752
753
754### ecran que especifica os utilizadores online
755##
756#
757 if($QUERY_STRING{subway} eq "who") {
758 print "<CENTER><font size=6 face='Verdana'><B>Quem está online</B></font><hr></CENTER>\n";
759 print "Encontram-se os seguintes utilizadores online:<BR>\n";
760 $sth=$db->prepare("select * from userinfo where lldate>'".(time-300)."' and lid!='0'");
761 $sth->execute;
762 while($res=$sth->fetchrow_hashref) {
763 print "<font color='FFEE00'><B>$res->{userid}($res->{nome})</B></font><BR>\n";
764 };
765 print "<HR>\n";
766 $sth->finish;
767 };
768### submenu das mensagens
769##
770#
771 if($QUERY_STRING{subway} eq "msg") {
772 print "<CENTER><font size=6 face='Verdana'><B>Caixa de correio</B></font><hr></CENTER>\n";
773 if($POST{apagar}) {
774 $sth=$db->prepare("select * from msg where useridto='\Q$COOKIE{login}\E'");
775 $sth->execute;
776 while($res=$sth->fetchrow_hashref) {
777 if($POST{'del'.$res->{id}}) {
778 $db->do("delete from msg where id='$res->{id}'");
779 print "Mensagem Apagada<BR>\n";
780 };
781 };
782 };
783 if($POST{msg}) {
784 do {
785 $id=int(rand()*200000);
786 $sth=$db->prepare("select * from msg where id='$id'");
787 $sth->execute;
788 } while($sth->rows);
789 if($POST{to} eq "") {
790 print "<font color='ff0000'>Terá de especificar um utilizador a quem enviar</font><BR>\n";
791 } else {
792 $db->do("insert into msg (id,useridfrom,useridto,data,subject,mensagem) values('$id','\Q$COOKIE{login}\E','\Q$POST{to}\E','".time()."','\Q$POST{Assunto}\E','\Q$POST{message}\E')");
793 print "Mensagem Enviada<BR>\n";
794 };
795 }
796 if($QUERY_STRING{ler}) {
797 $sth=$db->prepare("select * from msg where useridto='\Q$COOKIE{login}\E' and id='\Q$QUERY_STRING{ler}\E'");
798 $sth->execute;
799 $res=$sth->fetchrow_hashref;
800 $sth->finish;
801 $sth=$db->prepare("select * from userinfo where userid='\Q$res->{useridfrom}\E'");
802 $sth->execute;
803 $res1=$sth->fetchrow_hashref;
804 $sth->finish;
805 print "<CENTER><TABLE bgcolor='FFFFCC' border=0 cellspacing=0 cellpadding=0>\n";
806 print "<TR><TD>De: <B>$res->{useridfrom}($res1->{nome})</B> Assunto: <B>$res->{subject}</B> em: <B>".mydate("%a %d %b %Y %H:%M",$res->{data})."</B><BR><BR>\n";
807 $text= $res->{mensagem};
808 $text=~ s/\n/<BR>/sg;
809 print "$text<BR><BR></TD></TR>\n";
810 $db->do("update msg set lida='1' where id='\Q$QUERY_STRING{ler}\E'");
811 print "<TR><TD>\n";
812 print "<TABLE cellspacing=0 cellpadding=0><TR><TD><form><input type=button onclick='parent.location=\"$ENV{SCRIPT_NAME}?subway=msg&rid=".int(rand()*100)."\"' value='<- Voltar'></form></TD>\n";
813 print "<TD><form action='$ENV{SCRIPT_NAME}?subway=msg' method=POST><input type=hidden name='del$res->{id}' value='1'><input type=submit name='apagar' value='Apagar'></form></TD>\n";
814 print "</TR></TABLE></TD></TR></TABLE></CENTER>\n";
815 print "<HR>\n";
816 print "<CENTER>Responder<BR>\n";
817 print "<FORM action='$ENV{SCRIPT_NAME}?subway=msg' method='post'>\n";
818 print "<TABLE bgcolor='000000' cellspacing=1 border=0><TR><TD>\n";
819 print "<TABLE cellspacing=0 bgcolor='EFEFEF' border=0>\n";
820 print "<input type=hidden name=to value='$res1->{userid}'>\n";
821 print "<TR><TD>Assunto:</TD><TD><input type=text name='Assunto' value='RE: $res->{subject}' size=40></TD></TR>\n";
822 print "<TR><TD colspan=2>Mensagem:</TD></TR>\n";
823 print "<TR><TD colspan=2><textarea name='message' cols=50 rows=7>";
824 $text="\nDe: $res->{useridfrom} Em: ".mydate("%a %d %b %Y %H:%M",$res->{data})."\n\n$res->{mensagem}";
825 $text=~ s/\n/\n>/sg;
826 print $text;
827 print "</textarea></TD></TR>\n";
828 print "<TR><TD colspan=2 align='right'><input type=submit name='msg' value=' Enviar '></TD></TR>\n";
829 print "</TABLE>\n";
830 print "</TD></TR></TABLE></CENTER>\n";
831 print "</FORM>\n";
832 }else {
833 print "Consulta de mensagens: <BR>\n";
834 $sth=$db->prepare("select * from msg where useridto='\Q$COOKIE{login}\E' order by data DESC");
835 $sth->execute;
836 if($sth->rows) {
837 print "<table border=0 width=100% cellspacing=0 cellpadding=0 bgcolor='EFEFEF'>";
838 print "<FORM action='$ENV{SCRIPT_NAME}?subway=msg&rid=".int(rand()*100)."' METHOD='POST'>\n";
839 while($res=$sth->fetchrow_hashref) {
840 $sth1=$db->prepare("select * from userinfo where userid='\Q$res->{useridfrom}\E'");
841 $sth1->execute;
842 $res1=$sth1->fetchrow_hashref;
843 print "<TR><TD><input type=checkbox name='del$res->{id}' value='1'>De: <a href='mailto:$res1->{email}'>$res->{useridfrom}</a> Assunto: <a href='$ENV{SCRIPT_NAME}?subway=msg\&ler=$res->{id}'><B>$res->{subject}</B></a> Data: ".mydate("%a, %d %b %Y %H:%M",$res->{date});
844 if($res->{lida}) {
845 print " <font color='FF0000'>lida</font>\n";
846 } else {
847 print " <font color='00AA00'>Nova</font>\n";
848 };
849 print "</TD></TR>\n";
850 $sth1->finish;
851 };
852 print "<TR><TD colspan=2 align='left'><input type=submit name='apagar' value='Apagar'></TD></TR>\n";
853 print "</FORM>\n";
854 print "</TABLE>\n";
855
856 };
857 print "<HR>\n";
858 print "<CENTER>\n";
859 print "Enviar mensagem<BR>\n";
860 print "<FORM action='$ENV{SCRIPT_NAME}?subway=msg&rid=".int(rand()*100)."' method='post'>\n";
861 print "<TABLE bgcolor='000000' cellspacing=1 border=0><TR><TD>\n";
862 print "<TABLE cellspacing=0 bgcolor='EFEFEF' border=0>\n";
863 $sth=$db->prepare("select * from userinfo where userid<>'\Q$COOKIE{login}\E'");
864 $sth->execute;
865 print "<TR><TD>Para:</TD><TD>\n";
866 print "<select name='to'>\n";
867 while($res=$sth->fetchrow_hashref) {
868 print "<option value='$res->{userid}'>$res->{userid}($res->{nome})</option>\n";
869 };
870 print "</select>\n";
871 print "</TD></TR>\n";
872 print "<TR><TD>Assunto:</TD><TD><input type=text name='Assunto' size=40></TD></TR>\n";
873 print "<TR><TD colspan=2>Mensagem:</TD></TR>\n";
874 print "<TR><TD colspan=2><textarea name='message' cols=50 rows=7></textarea></TD></TR>\n";
875 print "<TR><TD colspan=2 align='right'><input type=submit name='msg' value=' Enviar '></TD></TR>\n";
876 print "</TABLE>\n";
877 print "</TD></TR></TABLE>\n";
878 print "</FORM>\n";
879 print "</CENTER>\n";
880 };
881
882 }; ## END CORREIO
883## START FORUM
884 if($QUERY_STRING{subway} eq "forum") {
885 print "<CENTER><font size=6 face='Verdana'><B>Forum</B></font><hr></CENTER>\n";
886 if($POST{enviar}) {
887 $done=0;
888 if($POST{replyto} ne "-1") {
889 $sth=$db->prepare("select * from forum where id='\Q$POST{replyto}\E'");
890 $sth->execute;
891 if(!$sth->rows){
892 print "<FONT color='FF000000'>Não poderá responder a uma mensagem não existente</font><BR>\n";
893 $done=1;
894 };
895 $sth->finish;
896 };
897 if(!$done) {
898 ## force to give new id without doubling
899 do {
900 $id=int(rand()*200000);
901 $sth=$db->prepare("select * from forum where id='$id'");
902 } while($sth->rows);
903 $sth->finish;
904 $db->do("insert into forum (id,useridfrom,subject,message,date,replyto) values('$id','\Q$COOKIE{login}\E','\Q$POST{subject}\E','\Q$POST{message}\E','".time."','$POST{replyto}')");
905 };
906 };
907 if($QUERY_STRING{ler}) {
908 $sth=$db->prepare("select * from forum where id='\Q$QUERY_STRING{ler}\E'");
909 $sth->execute;
910 $res=$sth->fetchrow_hashref;
911 $sth->finish;
912 $sth=$db->prepare("select * from userinfo where userid='\Q$res->{useridfrom}\E'");
913 $sth->execute;
914 $res1=$sth->fetchrow_hashref;
915 $sth->finish;
916 print "<center><table bgcolor='FFFFCC' cellspacing=0 cellpadding=0>\n";
917 print "<TR><TD>De: <B>$res->{useridfrom}($res1->{nome})</B> Assunto: <B>$res->{subject}</B> em: <B>".mydate("%a %d %b %Y %H:%M",$res->{data})."</B><BR><BR>\n";
918 $text= $res->{message};
919 $text=~ s/\n/<BR>/sg;
920 print "$text<BR><BR></TD></TR>\n";
921 $db->do("update msg set lida='1' where id='\Q$QUERY_STRING{ler}\E'");
922 print "<TR><TD>\n";
923 print "<TABLE border=0 cellspacing=0 cellpadding=0><TR>\n";
924 print "<TD><form><input type=button onclick='parent.location=\"$ENV{SCRIPT_NAME}?subway=forum\&rid=".int(rand()*100)."\"' value='<- Voltar'></form></TD>\n";
925 print "<TD><form><input type=button onclick='parent.location=\"$ENV{SCRIPT_NAME}?subway=forum\&adicionar=$res->{id}\&ler=$res->{id}\&rid=".int(rand()*100)."\"' value='Responder'></form></TD>\n" if(!$QUERY_STRING{adicionar});
926 print "</TR></TABLE>\n";
927 print "</TD></TR></TABLE></CENTER>\n";
928 print "<HR>\n";
929 };
930 if($QUERY_STRING{adicionar}) {
931 print "<CENTER>\n";
932 print "<FORM action='$ENV{SCRIPT_NAME}?subway=forum' METHOD='POST'>\n";
933 print "<TABLE bgcolor='000000' cellspacing=1 cellpadding=0><TR><TD>\n";
934 print "<TABLE border=0 bgcolor='EFEFEF' cellpadding=0 cellspacing=0>\n";
935 print "<TR><TD>Assunto:</TD><TD>";
936 if($QUERY_STRING{adicionar} > '-1') {
937 $sth=$db->prepare("select * from forum where id='\Q$QUERY_STRING{adicionar}\E'");
938 $sth->execute;
939 $res=$sth->fetchrow_hashref;
940 print "<input size=40 type='text' value='RE:$res->{subject}' name='subject'></TD>\n";
941 $sth->finish;
942 } else {
943 print "<input size=40 type='text' name='subject'></TD>\n";
944
945 };
946 print "<TR><TD colspan=2>Mensagem</TD></TR>\n";
947 print "<TR><TD colspan=2 align=center><textarea name='message' cols=40 rows=5></textarea></TD></TR>\n";
948 print "<TR><TD colspan=2 align=right><input type=submit name='enviar' value='Enviar'></TD></TR>\n";
949 print "<input type=hidden name='replyto' value='$QUERY_STRING{adicionar}'>\n";
950 print "</TABLE>\n";
951 print "</TD></TR></TABLE>\n";
952 print "</FORM>\n";
953 print "<form><input type=button onclick='parent.location=\"$ENV{SCRIPT_NAME}?subway=forum\&rid=".int(rand()*100)."\"' value='<- Voltar'></form>\n" if ($QUERY_STRING{adicionar} eq "-1");
954 print "</CENTER>\n";
955 print "<HR>\n";
956 };
957 print "Mensagens<BR>\n";
958 $in=1;
959 $sth[$in]=$db->prepare("select * from forum where replyto='-1' order by date DESC");
960 $sth[$in]->execute;
961 print "<TABLE width=100% cellspacing=1 cellpadding=0 border=0>\n";
962 $done=0;
963 while($in>0) {
964 while(!$done && !($res=$sth[$in]->fetchrow_hashref)) {
965 $sth[$in]->finish;
966 $in--;
967 if($in==0) {
968 $done=1;
969 };
970 };
971 if(!$done) {
972 if($in==1) {
973 print "<TR><TD bgcolor='FFFFFF'>#<a href='$ENV{SCRIPT_NAME}?subway=forum\&ler=$res->{id}\&rid=".int(rand()*100)."'><B>$res->{subject}</B></A> Por: <B>$res->{useridfrom}</B> em: ".mydate("%a %d %b %Y %H:%M",$res->{date})."</TD></TR>\n";
974 } else {
975 print "<TR><TD bgcolor='EFEFEF'>"."\&nbsp" x ($in*2)."\$<a href='$ENV{SCRIPT_NAME}?subway=forum\&ler=$res->{id}\&rid=".int(rand()*100)."'><B>$res->{subject}</B></A> Por: <B>$res->{useridfrom}</B> em: ".mydate("%a %d %b %Y %H:%M",$res->{date})."</TD></TR>\n";
976 };
977 $sth[$in+1]=$db->prepare("select * from forum where replyto='$res->{id}' order by date DESC");
978 $sth[$in+1]->execute;
979 if($sth[$in+1]->rows>0) {
980 $in++;
981 }else {
982 $sth[$in+1]->finish;
983 };
984 };
985 };
986 print "</TABLE>\n";
987 print "<form><input type=button onclick='parent.location=\"$ENV{SCRIPT_NAME}?subway=forum\&adicionar=-1\&rid=".int(rand()*100)."\"' value='Adicionar'></form>\n" if(!$QUERY_STRING{adicionar});
988 print "<HR>\n";
989 }; ## END FORUM
990
991##
992#########
993### ecran inicial
994###
995###
996## START HOME
997 if(!$QUERY_STRING{subway}) {
998 print "Boas, <B>" . (split(/ /,$res->{nome}))[0] . "</B><BR>\n";
999 $sth=$db->prepare("select * from conta where userid='\Q$COOKIE{login}\E'");
1000 $sth->execute;
1001 $res=$sth->fetchrow_hashref;
1002 print "Tens currentemente ";
1003 if($res->{value}>0) {
1004 print "<font color='00FF00'>$res->{value}</font>";
1005 } else {
1006 print "<font color='FF0000'>$res->{value}</font>";
1007 };
1008 print " cts na Conta principal, tem ";
1009 $sth=$db->prepare("select count(id) from msg where useridto='\Q$COOKIE{login}\E' and lida='0'");
1010 $sth->execute;
1011 $res=$sth->fetchrow_arrayref;
1012 print "<B>$res->[0]</B> mensagen(s) nova(s)<BR>\n";
1013 $sth=$db->prepare("select count(userid) from userinfo where lldate>'".(time-300)."' and lid!='0'");
1014 $sth->execute;
1015 $res=$sth->fetchrow_arrayref;
1016 print "->$res->[0] Utilizadores online<BR><BR>\n";
1017 $sth->finish;
1018 print "<B>Estatísticas: (demo)</B><BR>\n";
1019 print "<table cellspacing=0 cellpading=0 border=0>\n";
1020 @rtempname=("Desempenho","Dinheiro","Força","ex1","ex2");
1021 $r=0;
1022 while($r<5) {
1023 print "<TR><TD align=right >$rtempname[$r]:</TD><TD>";
1024 $c=int(rand()*10);
1025 for $i (0 .. 10) {
1026 if($i<$c) {
1027 print "<img width=15 height=15 src='$ENV{SCRIPT_NAME}?img=greenball'>";
1028 } else {
1029 print "<img wdith=15 height=15 src='$ENV{SCRIPT_NAME}?img=blackball'>";
1030
1031 };
1032 };
1033 print "</TD></TR>";
1034 $r++;
1035 };
1036 print "</TABLE>\n";
1037 print "<CENTER><font size=6 face='Verdana'><B>Noticias</B></font><hr></CENTER><BR><BR>\n";
1038 $sth=$db->prepare("select * from noticia where useridto='$COOKIE{login}' order by date DESC");
1039 $sth->execute;
1040 while($res=$sth->fetchrow_hashref) {
1041 print "<center><TABLE border=0 cellspacing=0 cellpading=1>\n";
1042 print "<TR><TD bgcolor='EEEEFF'>Data: <B>".mydate("%a, %d %b %Y %H:%M",$res->{date})."</B><BR></TD></TR>\n";
1043 print "<TR><TD bgcolor='FFFFEE'>$res->{noticia}<BR></TD></TR>\n";
1044 print "</TABLE></center><BR>\n";
1045 $db->do("update noticia set lida='1',rdate='".time()."' where id='$res->{id}' and lida='0'");
1046 };
1047 print "<HR>\n";
1048
1049 }; ## END HOME
1050 print "</font>\n";
1051 print "</TD></TR>\n";
1052 print "<TR><TD height='20px' bgcolor='EFEFEF' align='bottom'>\n";
1053 $sth=$db->prepare("select count(userid) from userinfo where lldate>'".(time-300)."' and lid!='0'");
1054 $sth->execute;
1055 $res=$sth->fetchrow_arrayref;
1056 $sth->finish;
1057 print "<a href='$ENV{SCRIPT_NAME}?subway=who&rid=".int(rand()*100)."'> <B>$res->[0]</B></a> Utilizador(es) online,";
1058 $sth=$db->prepare("select count(id) from msg where useridto='\Q$COOKIE{login}\E' and lida='0'");
1059 $sth->execute;
1060 $res=$sth->fetchrow_arrayref;
1061 $sth->finish;
1062 print " <a href='$ENV{SCRIPT_NAME}?subway=msg&rid=".int(rand()*100)."'><B>$res->[0]</B></a> Mensagens novas, ";
1063 $sth=$db->prepare("select * from conta where userid='\Q$COOKIE{login}\E'");
1064 $sth->execute;
1065 $res=$sth->fetchrow_hashref;
1066 $sth->finish;
1067 print "Tem <B>$res->{value}cts</B> na sua conta</TD></TR>\n";
1068
1069 print "</TD></TR></table>\n";
1070 print "</BODY>\n";
1071 $db->disconnect;
1072};
1073
1074
1075## isto é para quando iniciar o login o nome de utilizador já estar na caixa de texto durante 1 mês :)
1076##
1077cookie("username",$POST{username},"+1M") if( $POST{username} );
1078print "Content-type: text/html\n\n";
1079
1080
1081## tratamento de treinos
1082$db=DBI->connect("dbi:$dbdriver:dbname=$dbname","$dbuser","$dbpass");
1083$sth=$db->prepare("select * from treino where fdate<'".time()."'");
1084$sth->execute;
1085if($sth->rows>0) {
1086 while($res=$sth->fetchrow_hashref) {
1087 $sth1=$db->prepare("select * from jogador where nome='$res->{jogid}'");
1088 $sth1->execute;
1089 $res1=$sth1->fetchrow_hashref;
1090 $curval=$res1->{$res->{treino}};
1091 $newval=($curval+int((($res->{fdate}-$res->{date})/8460)));
1092 $db->do("update jogador set $res->{treino}='$newval', doing='0' where nome='$res->{jogid}'");
1093 $db->do("delete from treino where jogid='$res->{jogid}'");
1094 $sth2=$db->prepare("select * from equipa where equipaid='$res1->{equipaid}'");
1095 $sth2->execute;
1096 $res2=$sth2->fetchrow_hashref;
1097 enviarnoticia("Jogador $res->{nome} Acabou o seu treino ganhando assim $newval nas suas caracteristicas","$res2->{userid}");
1098 $sth2->finish;
1099 };
1100 $sth1->finish;
1101};
1102$sth->finish;
1103$db->disconnect;
1104####
1105## se a variavel posteriormente activa way for igual a logged (significa que o utilizador está identificado)
1106## então corre a funcção game onde está o jogo em si
1107
1108if($way eq "logged") {
1109 ### Tratamento de noticias obsoletas
1110 ##
1111 $db=DBI->connect("dbi:$dbdriver:dbname=$dbname","$dbuser","$dbpass");
1112 $sth=$db->prepare("select * from noticia where lida='1' and rdate<'".(time-600)."' and useridto='$COOKIE{login}'");
1113 $sth->execute;
1114 while($res=$sth->fetchrow_hashref) {
1115 $db->do("delete from noticia where id='$res->{id}'");
1116 };
1117 $db->disconnect;
1118 ################### noticias
1119 game;
1120};
1121
1122if($way eq "adduser") {
1123 printadduser;
1124};
1125## se a variavel $way não estiver activa (significa que nada anteriormente se passou) então imprime o menu de login
1126##
1127if($way eq "") {
1128 printlogin;
1129};
1130#
1131
1132
1133
1134
1135
1136
1137
diff --git a/doc/examples/cgi-bin/simple.cgi b/doc/examples/cgi-bin/simple.cgi
deleted file mode 100644
index 421924c3..00000000
--- a/doc/examples/cgi-bin/simple.cgi
+++ /dev/null
@@ -1,14 +0,0 @@
1#!/bin/sh
2
3
4
5echo -ne "Content-type: text/html\r\n\r\n"
6
7echo -e "<HTML>\n"
8echo -e "<BODY>\n"
9
10echo -e "THis is a simple cgi file\n"
11echo -e "$QUERY_STRING"
12echo -e "</body>"
13echo -e "</html>"
14
diff --git a/doc/examples/cgi-bin/simple1.cgi b/doc/examples/cgi-bin/simple1.cgi
deleted file mode 100644
index 15a20458..00000000
--- a/doc/examples/cgi-bin/simple1.cgi
+++ /dev/null
@@ -1,125 +0,0 @@
1#!/usr/bin/perl
2# Perl CGI document template... by Luis Figueiredo (stdio@netc.pt)
3#
4#
5#
6
7
8#use strict;
9my %POST;
10my %QUERY_STRING;
11my %COOKIE;
12my $stdindata;
13
14while(<STDIN>) {
15 $stdindata.=$_;
16};
17if($ENV{QUERY_STRING}) {
18 my (@varsdata)=split(/&/,$ENV{QUERY_STRING});
19 foreach (@varsdata) {
20 my ($name,$value)=split(/=/,$_);
21 $value =~ s/\+/ /g;
22 $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
23 $QUERY_STRING{$name}=$value;
24 };
25
26};
27if($ENV{REQUEST_METHOD} =~ m/POST/ && $ENV{CONTENT_TYPE} =~ m/application\/x-www-form-urlencoded/i) {
28 my (@varsdata)=split(/&/,$stdindata);
29 foreach (@varsdata) {
30 my ($name,$value)=split(/=/,$_);
31 $value =~ s/\+/ /g;
32 $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
33 $POST{$name}=$value;
34 };
35
36};
37if($ENV{HTTP_COOKIE} || $ENV{COOKIE}) {
38 my $cookie=$ENV{HTTP_COOKIE} || $ENV{COOKIE};
39 my(@cookiedata)=split(/; /,$cookie);
40 foreach(@cookiedata) {
41 $_ =~ /(.*?)=(.*)/;
42 $COOKIE{$1}=$2;
43 };
44};
45
46sub mydate {
47 my $format=shift;
48 my($time) = @_;
49 my(%mult) = ('s'=>1,
50 'm'=>60,
51 'h'=>60*60,
52 'd'=>60*60*24,
53 'M'=>60*60*24*30,
54 'y'=>60*60*24*365);
55 my($offset);
56 if (!$time || (lc($time) eq 'now')) {
57 $offset = 0;
58 } elsif ($time=~/^\d+/) {
59 $offset=($time-time);
60 } elsif ($time=~/^([+-]?(?:\d+|\d*\.\d*))([mhdMy]?)/) {
61 $offset = ($mult{$2} || 1)*$1;
62 } else {
63 $offset=($time-time);
64 }
65 my(@MON)=qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/;
66 my(@LMON)=qw/January February March April May June July August September October November December/;
67 my(@WDAY) = qw/Sun Mon Tue Wed Thu Fri Sat/;
68 my(@LWDAY) = qw/Sunday Monday Tuesday Wednesday Thursday Friday Saturdat/;
69 my($sec,$min,$hour,$mday,$mon,$year,$wday) = gmtime(time+$offset);
70 $year+=1900;
71 $format =~ s/\%Y/$year/eg;
72 $format =~ s/\%a/$WDAY[$wday]/eg;
73 $format =~ s/\%A/$LWDAY[$wday]/eg;
74 $format =~ s/\%m/sprintf("%02d",$mon+1)/eg;
75 $format =~ s/\%d/sprintf("%02d",$mday)/eg;
76 $format =~ s/\%H/sprintf("%02d",$hour)/eg;
77 $format =~ s/\%M/sprintf("%02d",$min)/eg;
78 $format =~ s/\%S/sprintf("%02d",$sec)/eg;
79 $format =~ s/\%b/$MON[$mon]/eg;
80 $format =~ s/\%B/$LMON[$mon]/eg;
81 $format =~ s/\%Z/GMT/g;
82 return $format;
83}
84
85sub cookie {
86 my $name=shift;
87 my $value=shift;
88 my $expire=shift;
89 if($value eq "") {
90 print "Set-Cookie: $name; path=$ENV{SCRIPT_NAME}; ";
91 } else {
92 print "Set-Cookie: $name=$value; path=$ENV{SCRIPT_NAME}; ";
93 };
94 if($expire) {
95 print "expires=".mydate("%a, %d-%b-%Y %H:%M:%S %Z",$expire);
96 };
97 #print " secure";
98 print "\r\n"; # end cookie
99};
100
101
102#COOKIES
103
104
105#print "Date: ".mydate("%a, %d %b %Y %H:%M:%S %Z","+5m")."\n";
106cookie("teste1","maria","+5m");
107cookie("login","manel","+5m");
108print "Content-type: text/html\r\n\r\n";
109
110
111
112print "<HTML>\n";
113print "<BODY bgcolor='EFEFEF'>\n";
114print "Simple cgi demo<BR>\n";
115print "<form action='$ENV{SCRIPT_NAME}?teste=new' method='POST'>\n";
116print "post value: <input type='text' name='login'>\n";
117print "<input type=submit name='go' value='send'>\n";
118print "</form><BR>\n";
119
120print "results:<table border=1><TR><TD>cookie 'maria'</TD><TD> $COOKIE{teste1}</TD></TR>\n";
121print "<TR><TD>post 'login':</TD><TD> $POST{login}</TD></TR>\n";
122print "<TR><TD>querystring 'teste':</TD><TD> $QUERY_STRING{teste}</TD></TR>\n";
123print "</TABLE>\n";
124
125print "</BODY></HTML>\n";
diff --git a/doc/examples/cgi.c b/doc/examples/cgi.c
deleted file mode 100644
index 5e1b76b9..00000000
--- a/doc/examples/cgi.c
+++ /dev/null
@@ -1,100 +0,0 @@
1/* by Luis Figueiredo (stdio@netc.pt)
2 *
3 * This is only a example if you intend to use this, please
4 * make this secure (checking file exec permissions etc.etc.)
5 */
6#include <stdio.h>
7#include <fcntl.h>
8#include <stdlib.h>
9#include <string.h>
10#include <dirent.h>
11#include "web_server.h"
12#include "debug.h"
13
14
15
16extern struct web_client *current_web_client;
17int PORT=80;
18
19extern char **environ;
20void cgi() {
21 char *reqfile=ClientInfo->request+1; // Skip '/'
22 char *tmp;
23 FILE *instream;
24 int stdo;
25 int ret;
26 int pid;
27 int outp;
28 if(!(pid=fork())) {
29 instream=tmpfile();
30 // Setup envvars
31 setenv("SCRIPT_NAME",ClientInfo->request,1);
32 setenv("REQUEST_METHOD",ClientInfo->method,1);
33 if(strlen(tmp=ClientInfo->Query(NULL))) {
34 setenv("QUERY_STRING",tmp,1);
35 };
36 if(strlen(tmp=ClientInfo->Post(NULL))) {
37 fwrite(tmp,strlen(tmp),1,instream);
38 }
39 setenv("CONTENT_TYPE",ClientInfo->Header("Content-type"),1);
40 if(strlen(tmp=ClientInfo->Header("Cookie"))) {
41 setenv("HTTP_COOKIE",tmp,1);
42 };
43 dup2(ClientInfo->outfd,1);
44 dup2(fileno(instream),0);
45 fseek(instream,0,SEEK_SET);
46 execve(reqfile,NULL,environ);
47 };
48 while(!(ret=waitpid(pid,&ret,0)))fprintf(stderr,"ret-%d\n",ret);;
49
50};
51void index_() {
52 DIR *dir;
53 struct dirent *dire;
54 dir=opendir("cgi-bin");
55 printf("Content-type: text/html\r\n\r\n");
56 printf("<HTML>\n");
57 printf("<BODY bgcolor='EFEFEF'>\n");
58 printf("Browse /cgi-bin/*<BR>\n");
59 while(dire=readdir(dir)) {
60 if(dire->d_name[0]!='.') {
61 if((int)(strstr(dire->d_name,".cgi")+4)==(int)(dire->d_name+strlen(dire->d_name))) {
62 printf("<a href='/cgi-bin/%s'>%s</a> -- ",dire->d_name,dire->d_name);
63 printf("<a href='/source?src=/cgi-bin/%s'>(see source)</a><BR>",dire->d_name,dire->d_name);
64 };
65 };
66 };
67 closedir(dir);
68};
69void source() {
70 char *tmp=ClientInfo->Query("src");
71 char *tmp1;
72 /* security */
73 while((tmp1=strstr(tmp,"../"))) {
74 tmp=tmp1+3;
75 };
76 while((tmp1=strstr(tmp,"//"))) {
77 tmp=tmp1+2;
78 };
79 tmp1=strstr(tmp,"/");
80 if(tmp1==tmp) {
81 tmp=tmp1+1;
82 };
83 /* security */
84 printf("Content-type: text/plain\r\n\r\n");
85 web_client_addfile(tmp);
86};
87main() {
88 struct web_server server;
89
90 while(!web_server_init(&server,PORT,"cgi.log",0)) {
91 PORT++;
92 };
93 printf("http://localhost:%d\n",PORT);
94 web_server_addhandler(&server,"* /source",source,0);
95 web_server_addhandler(&server,"* /*.cgi",cgi,0);
96 web_server_addhandler(&server,"* /",index_,0);
97 while(1) {
98 web_server_run(&server);
99 };
100};
diff --git a/doc/examples/demo.c b/doc/examples/demo.c
deleted file mode 100644
index 5fb43a19..00000000
--- a/doc/examples/demo.c
+++ /dev/null
@@ -1,66 +0,0 @@
1
2
3#include <stdio.h>
4#include <stdlib.h>
5
6
7#include "web_server.h"
8
9int PORT=80;
10
11void index_html() {
12 printf("Content-type: text/html\r\n\r\n");
13 printf("<HTML>\n");
14 printf("<BODY bgcolor='EFEFEF'>\n");
15 printf("libwebserver Example<BR><BR>\n");
16 printf("Client info structure:<BR><code>\n");
17 printf("struct ClientInfo {<BR>\n &nbsp;&nbsp;&nbsp;int outfd<BR>\n &nbsp;&nbsp;&nbsp;char *inetname<BR>\n &nbsp;&nbsp;&nbsp;char *request<BR>\n &nbsp;&nbsp;&nbsp;char *method<BR>\n &nbsp;&nbsp;&nbsp;char *user<BR>\n &nbsp;&nbsp;&nbsp;char *pass<BR>\n &nbsp;&nbsp;&nbsp;char *QueryData;<BR>\n &nbsp;&nbsp;&nbsp;struct memrequest *mem;<BR>\n &nbsp;&nbsp;&nbsp;char *(*Header)(char*);<BR>\n &nbsp;&nbsp;&nbsp;char *(*QueryString)(char*);<BR>\n &nbsp;&nbsp;&nbsp;char *(*Post)(char*);<BR>\n &nbsp;&nbsp;&nbsp;char *(*MultiPart)(char*);<BR>\n };<BR>\n");
18 printf("ClientInfo->outfd=%d<BR>\n",ClientInfo->outfd);
19 printf("ClientInfo->request=%s<BR>\n",ClientInfo->request);
20 printf("ClientInfo->method=%s<BR>\n",ClientInfo->method);
21 printf("ClientInfo->Header(\"Host\")=\"%s\"<BR>\n",ClientInfo->Header("Host"));
22 printf("ClientInfo->Header(\"Accept\")=\"%s\"<BR>\n",ClientInfo->Header("Accept"));
23 printf("ClientInfo->Query(\"teste\")=\"%s\"<BR>\n",ClientInfo->Query("teste"));
24 printf("ClientInfo->Query(NULL)=\"%s\"<BR>\n",ClientInfo->Query(NULL));
25 printf("ClientInfo->Post(\"dev\")=\"%s\"<BR>\n",ClientInfo->Post("dev"));
26 printf("ClientInfo->MultiPart(\"teste\").data=\"%s\"<BR>\n",ClientInfo->MultiPart("teste").data);
27 printf("ClientInfo->MultiPart(\"file1\").filename=\"%s\"<BR>\n",ClientInfo->MultiPart("file1").filename);
28 printf("ClientInfo->MultiPart(\"file1\").size=\"%d\"<BR>\n",ClientInfo->MultiPart("file1").size);
29 printf("ClientInfo->MultiPart(\"file1\").data=\"");
30 fwrite(ClientInfo->MultiPart("file1").data,ClientInfo->MultiPart("file1").size,1,stdout);
31 printf("\"<BR>\n");
32 printf("<form action='/?teste=done' method='post' enctype='multipart/form-data'>\n");
33 printf("<input type=file name='file1'><BR>\n");
34 printf("<input type=hidden name='dev' value='Luis Figueiredo'>\n");
35 printf("<input type=text name='teste'>\n");
36 printf("<input type=submit name='GOO' value='send'>\n");
37 printf("</form>\n");
38 printf("Stats:<BR>\n");
39 printf("<a href='http://libwebserver.sourceforge.net'><img border='0' src='/libwebserver.gif'></a><br>\n");
40 printf("</BODY>\n");
41 printf("</HTML>\n");
42};
43
44void logfile() {
45 FILE *log;
46 printf("Content-type: text/plain \r\n\r\n");
47 web_client_addfile("./demo.log");
48 printf("Fim do log\n");
49};
50
51int main() {
52 int pid;
53 struct web_server server;
54 while(!web_server_init(&server,PORT,"demo.log",0)) {
55 PORT++;
56 };
57 printf("http://localhost:%d\n",PORT);
58 web_server_addhandler(&server,"* /",index_html,0);
59 web_server_addhandler(&server,"* /log",logfile,0);
60 while(1) {
61 // DO whatever u want
62 web_server_run(&server); // Process web_server
63 };
64 return 0;
65
66};
diff --git a/doc/examples/foo-cert.pem b/doc/examples/foo-cert.pem
deleted file mode 100644
index 66676877..00000000
--- a/doc/examples/foo-cert.pem
+++ /dev/null
@@ -1,86 +0,0 @@
1Private-Key: (512 bit)
2modulus:
3 00:b4:fc:64:b0:c0:27:63:5c:a6:43:66:ac:68:58:
4 48:37:d3:f5:a4:fa:af:a7:11:a1:fd:81:a4:7a:9e:
5 ff:90:a3:ee:df:ea:ef:11:54:b8:c0:0b:24:b3:6f:
6 ff:a8:83:b8:0c:08:cf:03:51:41:14:f0:70:20:ce:
7 5f:25:a8:65:7f
8publicExponent: 65537 (0x10001)
9privateExponent:
10 78:aa:da:bb:59:b2:29:36:49:88:20:b9:8c:6c:67:
11 e2:09:08:fb:71:44:91:c0:58:df:bb:83:1d:5a:4b:
12 0c:74:8f:86:33:95:10:57:7d:32:c0:d3:6c:b8:c5:
13 82:b4:ce:d6:28:b9:33:f7:ab:83:63:2d:13:74:95:
14 49:37:2f:29
15prime1:
16 00:ef:dc:c6:18:61:46:8d:be:d3:d1:4b:6f:5c:e3:
17 1d:6a:9d:79:d5:b3:24:8c:ce:4c:db:99:d5:0e:70:
18 c8:70:fd
19prime2:
20 00:c1:29:92:34:03:4c:b9:9b:3b:61:09:55:be:c2:
21 f8:e2:e5:50:1e:5d:b2:8d:28:0b:d2:af:72:cc:82:
22 88:87:2b
23exponent1:
24 00:db:3c:22:3f:d4:61:85:5b:3f:05:94:7a:54:1f:
25 2e:1a:ed:96:97:51:a6:fd:9f:ee:35:e5:d4:0b:df:
26 e0:05:0d
27exponent2:
28 7e:97:c7:18:cd:7c:d0:3b:bb:2b:ba:59:76:bf:03:
29 2c:78:cb:0c:4b:ae:04:32:d5:a4:cb:95:7a:10:a6:
30 77:a7
31coefficient:
32 00:b8:f0:d6:99:dc:85:6d:d8:04:c5:92:7e:db:41:
33 2e:50:42:d0:f0:37:af:3c:b2:a6:74:92:a0:c9:99:
34 47:18:41
35Certificate:
36 Data:
37 Version: 4 (0x3)
38 Serial Number: 0 (0x0)
39 Signature Algorithm: md5WithRSAEncryption
40 Issuer: C=UK, CN=OpenSSL Group
41 Validity
42 Not Before: Apr 23 06:55:21 2002 GMT
43 Not After : Apr 23 06:55:21 2003 GMT
44 Subject: C=UK, CN=OpenSSL Group
45 Subject Public Key Info:
46 Public Key Algorithm: rsaEncryption
47 RSA Public Key: (512 bit)
48 Modulus (512 bit):
49 00:b4:fc:64:b0:c0:27:63:5c:a6:43:66:ac:68:58:
50 48:37:d3:f5:a4:fa:af:a7:11:a1:fd:81:a4:7a:9e:
51 ff:90:a3:ee:df:ea:ef:11:54:b8:c0:0b:24:b3:6f:
52 ff:a8:83:b8:0c:08:cf:03:51:41:14:f0:70:20:ce:
53 5f:25:a8:65:7f
54 Exponent: 65537 (0x10001)
55 X509v3 extensions:
56 Netscape Cert Type:
57 SSL Server
58 Netscape Comment:
59 example comment extension
60 Netscape SSL Server Name:
61 libwebserver
62 Signature Algorithm: md5WithRSAEncryption
63 3e:6a:3c:4a:ec:8b:1f:eb:a8:99:33:d6:e0:f9:f1:a7:70:3c:
64 7a:b1:73:ae:34:52:06:d0:be:0b:32:ed:ec:01:27:a5:d6:3c:
65 ce:34:38:f9:29:49:c1:0b:0d:9a:74:60:b8:4d:b9:e0:29:ad:
66 fd:5b:32:32:3f:3c:e8:93:2d:6a
67-----BEGIN RSA PRIVATE KEY-----
68MIIBOwIBAAJBALT8ZLDAJ2NcpkNmrGhYSDfT9aT6r6cRof2BpHqe/5Cj7t/q7xFU
69uMALJLNv/6iDuAwIzwNRQRTwcCDOXyWoZX8CAwEAAQJAeKrau1myKTZJiCC5jGxn
704gkI+3FEkcBY37uDHVpLDHSPhjOVEFd9MsDTbLjFgrTO1ii5M/erg2MtE3SVSTcv
71KQIhAO/cxhhhRo2+09FLb1zjHWqdedWzJIzOTNuZ1Q5wyHD9AiEAwSmSNANMuZs7
72YQlVvsL44uVQHl2yjSgL0q9yzIKIhysCIQDbPCI/1GGFWz8FlHpUHy4a7ZaXUab9
73n+415dQL3+AFDQIgfpfHGM180Du7K7pZdr8DLHjLDEuuBDLVpMuVehCmd6cCIQC4
748NaZ3IVt2ATFkn7bQS5QQtDwN688sqZ0kqDJmUcYQQ==
75-----END RSA PRIVATE KEY-----
76-----BEGIN CERTIFICATE-----
77MIIBmjCCAUSgAwIBAwIBADANBgkqhkiG9w0BAQQFADAlMQswCQYDVQQGEwJVSzEW
78MBQGA1UEAxMNT3BlblNTTCBHcm91cDAeFw0wMjA0MjMwNjU1MjFaFw0wMzA0MjMw
79NjU1MjFaMCUxCzAJBgNVBAYTAlVLMRYwFAYDVQQDEw1PcGVuU1NMIEdyb3VwMFww
80DQYJKoZIhvcNAQEBBQADSwAwSAJBALT8ZLDAJ2NcpkNmrGhYSDfT9aT6r6cRof2B
81pHqe/5Cj7t/q7xFUuMALJLNv/6iDuAwIzwNRQRTwcCDOXyWoZX8CAwEAAaNfMF0w
82EQYJYIZIAYb4QgEBBAQDAgZAMCgGCWCGSAGG+EIBDQQbFhlleGFtcGxlIGNvbW1l
83bnQgZXh0ZW5zaW9uMB4GCWCGSAGG+EIBDAQRFg93d3cub3BlbnNzbC5vcmcwDQYJ
84KoZIhvcNAQEEBQADQQA+ajxK7Isf66iZM9bg+fGncDx6sXOuNFIG0L4LMu3sASel
851jzONDj5KUnBCw2adGC4TbngKa39WzIyPzzoky1q
86-----END CERTIFICATE-----
diff --git a/doc/examples/packetmounter.c b/doc/examples/packetmounter.c
deleted file mode 100644
index 32bc79a1..00000000
--- a/doc/examples/packetmounter.c
+++ /dev/null
@@ -1,236 +0,0 @@
1
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <time.h>
6#include <sys/time.h>
7
8typedef u_int32_t n_time;
9#include <netinet/in.h>
10#include <netinet/ip.h>
11#define __FAVOR_BSD 1
12#include <netinet/tcp.h>
13#include <sys/socket.h>
14#include <netdb.h>
15#include <regex.h>
16#include <ctype.h>
17#include <unistd.h>
18#include <fcntl.h>
19#include <string.h>
20#include <unistd.h>
21#include <signal.h>
22
23#include "web_server.h"
24
25int PORTSSL=443;
26
27unsigned short in_chksum(unsigned short *addr, int len) {
28 register int nleft = len;
29 register int sum = 0;
30 u_short answer = 0;
31
32 while (nleft > 1) {
33 sum += *addr++;
34 nleft -= 2;
35 }
36
37 if (nleft == 1) {
38 *(unsigned char *)(&answer) = *(unsigned char *)addr;
39 sum += answer;
40 }
41 sum = (sum >> 16) + (sum & 0xffff);
42 sum += (sum >> 16);
43 answer = ~sum;
44 return(answer);
45}
46void packetmounter() {
47 char *t;
48 int s;
49 struct sockaddr_in to;
50 int i;
51 int n=10;
52 char buf[128];
53 int proto=1; //icmp default
54 struct ip *ip=(struct ip *)buf;
55 struct tcphdr *tcp=(struct tcphdr *)(buf+sizeof(*ip));
56 char *tmp1=ClientInfo->user;
57 char *tmp2=ClientInfo->pass;;
58 if(!strlen(tmp1) || !strlen(tmp2)) {
59 web_client_HTTPdirective("HTTP/1.1 401 Authorization Required");
60 printf("WWW-Authenticate: Basic realm=\"Packet mounter\"\r\n");
61 printf("Content-type: text/html\r\n\r\n");
62 printf("<BODY bgcolor='EFEFEF'>\r\n");
63 printf("<font color='FF0000'><center>Access denied</center></font>\n");
64 printf("</body>\r\n");
65 return;
66 };
67 if(strcmp(tmp1,"packet") && strcmp(tmp2,"teste")) { // Lame autentification just for test
68 web_client_HTTPdirective("HTTP/1.1 401 Authorization Required");
69 printf("WWW-Authenticate: Basic realm=\"Packet mounter\"\r\n");
70 printf("Content-type: text/html\r\n\r\n");
71 printf("<BODY bgcolor='EFEFEF'>\r\n");
72 printf("<font color='FF0000'><center>Access denied</center></font>\n");
73 printf("</body>\r\n");
74 return;
75 };
76 printf("Content-type: text/html\r\n\r\n");
77 printf("<HTML>\n");
78 printf("<body bgcolor='FFFFCC'>\n");
79 printf("<center>public Packet mounter by <BR><small><TT> Luis Figueiredo (<a href=\"mailto:stdio@netc.pt\">stdio@netc.pt</a>)</tt></small><BR><i><small>Using %s</i></small><HR>\n",_libwebserver_version);
80 t=ClientInfo->Query("proto");
81 printf("Pretended protocol: %s<BR>\n",t);
82 if(strlen(t)) {
83 proto=atoi(t);
84 printf("<form method=post action='/?proto=%d' name=\"ip\">\n",proto);
85 } else {
86 printf("<form method=post action='/' name=\"ip\">\n");
87 };
88 printf("<table border=0><TR><TD>\n");
89 printf("<table border=1>\n");
90 printf("<TR><TD colspan=4 align='center' bgcolor='5555ff'>IP header</TD></TR>\n");
91 t=ClientInfo->Post("ipversion");
92 printf("<TR><TD align='center'>version:<BR><input type=text size=2 maxlength=2 name=ipversion value='%s'></TD>\n",(t)?t:"");
93 if(strlen(t)){ip->ip_v=atoi(t);} else {ip->ip_v=4;} // default
94
95 t=ClientInfo->Post("ipihl");
96 printf("<TD align='center'>ihl:<BR><input type=text size=2 maxlength=2 name=ipihl value='%s'></TD>\n",(t)?t:"");
97 if(strlen(t)){ip->ip_hl=atoi(t);} else {ip->ip_hl=5;}
98
99 t=ClientInfo->Post("iptos");
100 printf("<TD align='center'>tos:<BR><input type=text size=3 maxlength=3 name=iptos value='%s'></TD>\n",(t)?t:"");
101 if(strlen(t)){ip->ip_tos=atoi(t);} else {ip->ip_tos=0;}
102
103 t=ClientInfo->Post("iptotlen");
104 printf("<TD align='center'>tot len:<BR><input type=text size=4 maxlength=4 name=iptotlen value='%s'></TD></TR>\n",(t)?t:"");
105 if(strlen(t)){ip->ip_len=htons(atoi(t));} else {ip->ip_len=htons(sizeof(struct ip));}
106
107 t=ClientInfo->Post("ipid");
108 printf("<TR><TD align='center' colspan=3>id:<BR><input type=text size=5 maxlength=5 name=ipid value='%s'></TD>\n",(t)?t:"");
109 if(strlen(t)){ip->ip_id=htons(atoi(t));} else {ip->ip_id=htons(37337);}
110
111 t=ClientInfo->Post("ipfrag");
112 printf("<TD align='center'>frag offset:<BR><input type=text size=4 maxlength=4 name=ipfrag value='%s'></TD></TR>\n",(t)?t:"");
113 if(strlen(t)){ip->ip_off=htons(atoi(t));} else {ip->ip_off=htons(0);}
114
115 t=ClientInfo->Post("ipttl");
116 printf("<TR><TD align='center' colspan=2>ttl:<BR><input type=text size=3 maxlength=3 name=ipttl value='%s'></TD>\n",(t)?t:"");
117 if(strlen(t)){ip->ip_ttl=atoi(t);} else {ip->ip_ttl=64;}
118 printf("<TD align='center'>proto:<BR>\n");
119 printf("<select name='ipproto' onchange='parent.location=(document.ip.ipproto.options[0].selected==true)?\"/?proto=1\":(document.ip.ipproto.options[1].selected==true)?\"/?proto=6\":(document.ip.ipproto.options[2].selected==true)?\"/?proto=17\":\"\"'>\n");
120 printf("<option value='1' %s>icmp\n",(proto==1)?"selected":"");
121 printf("<option value='6' %s>tcp\n",(proto==6)?"selected":"");
122 printf("<option value='17' %s>udp\n",(proto==17)?"selected":"");
123 printf("</select></TD>\n");
124 ip->ip_p=proto;
125
126 printf("<TD align='center'>checksum:<BR>automatic</TD></TR>\n");
127
128 t=ClientInfo->Post("ipsrc");
129 printf("<TR><TD align='center' colspan=4>src ip:<BR><input type=text size=15 maxlength=15 name=ipsrc value='%s'></TD></TR>\n",(t)?t:"");
130 if(strlen(t)){ip->ip_src.s_addr=inet_addr(t);} else {ip->ip_src.s_addr=0;}
131
132 t=ClientInfo->Post("ipdst");
133 printf("<TR><TD align='center' colspan=4>dst ip:<BR><input type=text size=15 maxlength=15 name=ipdst value='%s'></TD></TR></TABLE>\n",(t)?t:"");
134 if(strlen(t)){ip->ip_dst.s_addr=inet_addr(t);} else {ip->ip_dst.s_addr=0;}
135
136 printf("</TD><TD>\n");
137
138 if(proto==6) { // print tcp header input
139 printf("<TABLE border=1>\n");
140 printf("<TR><TD colspan=4 align='center' bgcolor='5555FF'>tcp header</TD></TR>\n");
141 t=ClientInfo->Post("tcpsrcport");
142 printf("<TR><TD colspan=2 align='center'>src port:<BR><input type=text size=5 maxlength=5 name=tcpsrcport value='%s'></TD>\n",(t)?t:"");
143 if(strlen(t)){tcp->th_sport=htons(atoi(t));}
144 t=ClientInfo->Post("tcpdstport");
145 printf("<TD colspan=2 align='center'>dst port:<BR><input type=text size=5 maxlength=5 name=tcpdstport value='%s'></TD></TR>\n",(t)?t:"");
146 if(strlen(t)){tcp->th_dport=htons(atoi(t)); }
147 t=ClientInfo->Post("tcpseq");
148 printf("<TR><TD colspan=4 align='center'>Seq number:<BR><input type=text size=10 maxlength=10 name=tcpseq value='%s'></TD></TR>\n",(t)?t:"");
149 if(strlen(t)){tcp->th_seq=htonl(strtoul(t,NULL,10));}
150 t=ClientInfo->Post("tcpack");
151 printf("<TR><TD colspan=4 align='center'>ack:<BR><input type=text size=10 maxlength=10 name=tcpack value='%s'></TD></TR>\n",(t)?t:"");
152 if(strlen(t)){tcp->th_ack=htonl(strtoul(t,NULL,10)); }else {tcp->th_ack=0;}
153
154 printf("<TR><TD align='center'><small><small>data offset:<BR>(computed)</small></small></TD>\n");
155 printf("<TD align='center'><small><small>reserved:<BR>(computed)</small></small></TD>\n");
156 printf("<TD align='center'>flags:<BR>\n");
157 printf("<TABLE border=0 cellspacing=0 cellpadding=0><TR>\n");
158 printf("<TD><small><small>URG </small></small></TD>\n");
159 printf("<TD><small><small>ACK </small></small></TD>\n");
160 printf("<TD><small><small>PSH </small></small></TD>\n");
161 printf("<TD><small><small>RST </small></small></TD>\n");
162 printf("<TD><small><small>SYN </small></small></TD>\n");
163 printf("<TD><small><small>FIN</small></small></TD></TR>\n");
164 t=ClientInfo->Post("tcpfURG");
165 if(strlen(t)){tcp->th_flags |= TH_URG;}else {tcp->th_flags &= ~TH_URG;}
166 t=ClientInfo->Post("tcpfACK");
167 if(strlen(t)){tcp->th_flags |= TH_ACK;}else {tcp->th_flags &= ~TH_ACK;}
168 t=ClientInfo->Post("tcpfPSH");
169 if(strlen(t)){tcp->th_flags |= TH_PUSH;}else {tcp->th_flags &= ~TH_PUSH;}
170 t=ClientInfo->Post("tcpfRST");
171 if(strlen(t)){tcp->th_flags |= TH_RST;}else {tcp->th_flags &= ~TH_RST;}
172 t=ClientInfo->Post("tcpfSYN");
173 if(strlen(t)){tcp->th_flags |= TH_SYN;}else {tcp->th_flags &= ~TH_SYN;}
174 t=ClientInfo->Post("tcpfFIN");
175 if(strlen(t)){tcp->th_flags |= TH_FIN;}else {tcp->th_flags &= ~TH_FIN;}
176 printf("<TD><input type=checkbox name=tcpfURG %s></TD>\n",((tcp->th_flags & TH_URG)==TH_URG)?"checked":"");
177 printf("<TD><input type=checkbox name=tcpfACK %s></TD>\n",((tcp->th_flags & TH_ACK)==TH_ACK)?"checked":"");
178 printf("<TD><input type=checkbox name=tcpfPSH %s></TD>\n",((tcp->th_flags & TH_PUSH)==TH_PUSH)?"checked":"");
179 printf("<TD><input type=checkbox name=tcpfRST %s></TD>\n",((tcp->th_flags & TH_RST)==TH_RST)?"checked":"");
180 printf("<TD><input type=checkbox name=tcpfSYN %s></TD>\n",((tcp->th_flags & TH_SYN)==TH_SYN)?"checked":"");
181 printf("<TD><input type=checkbox name=tcpfFIN %s></TD>\n",((tcp->th_flags & TH_FIN)==TH_FIN)?"checked":"");
182 printf("</TR></TABLE></TD>\n");
183 t=ClientInfo->Post("tcpwin");
184 printf("<TD align='center'>window:<BR><input type=text size=7 maxlength=7 name=tcpwin value='%s'></TD></TR>\n",(t)?t:"");
185 if(strlen(t)) {tcp->th_win=htons(atoi(t)); } else {tcp->th_win=htons(1500);}
186 printf("<TR><TD colspan=2 align='center'>checksum:<BR>automatic</TD>\n");
187 t=ClientInfo->Post("tcpurg");
188 printf("<TD colspan=2 align='center'>urgent:<BR><input type=text size=7 maxlength=7 name=tcpurg value='%s'></TD></TR>\n",(t)?t:"");
189 printf("<TR><TD align='center' colspan=4>Tcp data<BR><textarea name=data cols='30' rows='4'>%s</textarea></TD></TR>\n",ClientInfo->Post("data"));
190 if(strlen(t)) {tcp->th_urp=htons(atoi(t)); } else {tcp->th_urp=0;}
191 printf("</TABLE>\n");
192 printf("</TABLE>\n");
193 tcp->th_x2=0;
194 };
195 printf("</TD></TR></TABLE>\n");
196 t=ClientInfo->Post("n_packets");
197 printf("<input type=text size=4 maxlength=4 value='10' name=n_packets value='%s'>\n",(t)?t:"");
198 if(strlen(t)){n=atoi(t); }
199 printf("<input type=submit value='send packet' name=ipsend>\n");
200 t=ClientInfo->Post("data");
201 memcpy(buf+sizeof(*ip)+sizeof(*tcp),t,(strlen(t)>128)?128:strlen(t));
202
203 t=ClientInfo->Post("ipsend");
204 if(strlen(t)) {
205 s=socket(AF_INET,SOCK_RAW,IPPROTO_RAW);
206 to.sin_family=AF_INET;
207 to.sin_addr.s_addr=ip->ip_dst.s_addr;
208 to.sin_port=htons(tcp->th_dport);
209 ip->ip_sum=in_chksum((void *)&ip,sizeof(*ip));
210 tcp->th_sum=in_chksum((void *)&ip,sizeof(*ip)+sizeof(*tcp));
211 for(i=0;i<n;i++) {
212 sendto(s,&buf,128,0,(struct sockaddr *)&to,sizeof(to));
213 };
214 };
215 printf("<br><a href='http://libwebserver.sourceforge.net'><img src='/libwebserver.gif' border='0'></a><BR>\n");
216 printf("</body>\n");
217 printf("</HTML>\n");
218
219};
220
221int main() {
222 int pid;
223 struct web_server serverSSL;
224 web_server_useSSLcert(&serverSSL,"./foo-cert.pem"); // Must be here couse of initalization of openssl
225 while(!web_server_init(&serverSSL,PORTSSL,"packetmounter.log",WS_USESSL)) {
226 PORTSSL++;
227 };
228 printf("https://localhost:%d\n",PORTSSL);
229 web_server_addhandler(&serverSSL,"* /*",packetmounter,0);
230 while(1) {
231 // DO whatever u want
232 web_server_run(&serverSSL); // Process web_server w/ SSL
233 };
234 return 0;
235
236};
diff --git a/doc/functions.html b/doc/functions.html
deleted file mode 100644
index e28329ca..00000000
--- a/doc/functions.html
+++ /dev/null
@@ -1,355 +0,0 @@
1<center><H3><font color='007700'>libwebserver Functions</font></H3></center><BR><BR>
2<font face='Verdana'>
3
4<A name=web_server_init><B><font color='000077'>web_server_init()</font></B><BR><BR>
5<B>NAME</B>
6<UL>web_server_init - Initialize webserver</UL>
7<B>SYNOPSIS</B>
8<UL>#include "web_server.h"<BR><BR>int web_server_init(struct web_server *<U>server</U>, int <U>port</U>, const char *<U>logfile</U>, int <U>flags</U>);</UL>
9<B>DESCRIPTION</B>
10<UL>The web_server_init() function initializes the server handler <U>server</U>, start a listen socket at port <U>port</U>, with the logfile <U>logfile</U> to produce the webserver log<BR> if WS_USEEXTCONF flag is used, the <U>logfile</U> will be the config file <BR>
11<U>flags</U> <BR>
12WS_USESSL for openssl connections (https support)<BR>
13WS_USEEXTCONF for using a external config file<BR>
14WS_LOCAL only accepts 127.0.0.1 (local) connections
15</UL>
16
17<B>RETURN VALUE</B>
18<UL>On success, 1 is returned, On error, 0 is returned</UL>
19<HR><BR>
20
21
22<A name=web_server_addhandler><B><font color='000077'>web_server_addhandler()</font></B><BR><BR>
23<B>NAME</B>
24<UL>web_server_addhandler - adds a request handler</UL>
25<B>SYNOPSIS</B>
26<UL>#include "web_server.h"<BR><BR>int web_server_addhandler(struct web_server *<U>server</U>, const char *<U>mstr</U>, void (*<U>func</U>)(), int <U>flags</U>);</UL>
27<B>DESCRIPTION</B>
28<UL>The web_server_addhandler() function adds a request handler <U>mstr</U> to the server handler <U>server</U> through the function <U>func</U>.<BR>
29<U>mstr</U> is a string containing expressions (as matching files) to match with the client request (GET /<B>blah.html</B>?id=1 HTTP/1.0, will be matched by <U>mstr</U>="* /blah.html")<BR>
30<U>flags:</U> <BR>
31WS_LOCAL - only local connections are handled<BR>
32WS_DYNVAR - treat dynamic variables on output (Atention: this disables "Content-range" and "Content-length" header, responding "501 not implemented")<BR>
33WS_USELEN - With this flag, library calculate the header "Content-length" and "Content-range" it self, useful for resuming, content-length can be miscalculated if the file added by (web_client_addfile) changes the size of contents, between calculating and output<BR>
34</UL>
35<B>RETURN VALUE</B>
36<UL>On success, 1 is returned, On error, 0 is returned</UL>
37<HR><BR>
38
39<A name=web_server_aliasdir><B><font color='000077'>web_server_aliasdir()</font></B><BR><BR>
40<B>NAME</B>
41<UL>web_server_aliasdir - Generates a directory list, and use file based server</UL>
42<B>SYNOPSIS</B>
43<UL>#include "web_server.h"<BR><BR>int web_server_aliasdir(struct web_server *<U>server</U>, const char *<U>alias</U>, char *<U>path</U>, int <U>flags</U>);</UL>
44<B>DESCRIPTION</B>
45<UL>The web_server_aliasdir() function adds an alias <U>alias</U> to the server handler <U>server</U> and use files from <U>path</U>.<BR>
46<U>flags:</U> <BR>
47WS_LOCAL - only local connections are handled<BR>
48WS_DYNVAR - treat dynamic variables on output (Atention: this disables "Content-range" and "Content-length" header, responding "501 not implemented")<BR>
49WS_USELEN - With this flag, library calculate the header "Content-length" and "Content-range" it self, useful for resuming, content-length can be miscalculated if the file added by (web_client_addfile) changes the size of contents, between calculating and output<BR>
50</UL>
51<B>RETURN VALUE</B>
52<UL>On success, 1 is returned, On error, 0 is returned</UL>
53<HR><BR>
54
55<A name=web_server_run><B><font color='000077'>web_server_run()</font></B><BR><BR>
56<B>NAME</B>
57<UL>web_server_run - run the server</UL>
58<B>SYNOPSIS</B>
59<UL>#include "web_server.h"<BR><BR>int web_server_run(struct web_server *<U>server</U>);</UL>
60<B>DESCRIPTION</B>
61<UL>The web_server_run() function processes requests to the server <U>server</U>. This function must be called from the main application loop (the functions doesn't loop it self)</UL>
62<B>RETURN VALUE</B>
63<UL>On success, greater than 0, is returned (2 if there wasn't client, 1 if some request was processed), On error, 0 is returned</UL>
64<HR><BR>
65
66<A name=web_server_getconf><B><font color='000077'>web_server_getconf()</font></B><BR><BR>
67<B>NAME</B>
68<UL>web_server_getconf - get data from config filer</UL>
69<B>SYNOPSIS</B>
70<UL>#include "web_server.h"<BR><BR>char *web_server_getconf(struct web_server *<U>server</U>,char *<U>topic</U>,char *<U>key</U>);</UL>
71<B>DESCRIPTION</B>
72<UL>The web_server_getconf() function allocates and return a string from config file related to <U>topic</U> and <U>key</U> (see <a href="/?help=functions#configfile">config file help</a>) This function must be called after the init of the var <U>server</U></UL>
73<B>RETURN VALUE</B>
74<UL>returns allocated string, (you should free after use) or null if nothing related to arguments found</UL>
75<HR><BR>
76
77<A name=web_server_useSSLcert><B><font color='000077'>web_server_useSSLcert()</font></B><BR><BR>
78<B>NAME</B>
79<UL>web_server_useSSLcert - use certificate</UL>
80<B>SYNOPSIS</B>
81<UL>#include "web_server.h"<BR><BR>void web_server_useSSLcert(struct web_server *<U>server</U>, const char *<U>file</U>);</UL>
82<B>DESCRIPTION</B>
83<UL>The web_server_useSSLcert() function tells server <U>server</U> to use certificate file <U>file</U> on ssl connections (initializated w/ flag WS_USESSL)</UL>
84<HR><BR>
85
86<A name=web_server_useMIMEfile><B><font color='000077'>web_server_useMIMEfile()</font></B><BR><BR>
87<B>NAME</B>
88<UL>web_server_useMIMEfile - use mime types file</UL>
89<B>SYNOPSIS</B>
90<UL>#include "web_server.h"<BR><BR>void web_server_useMIMEfile(struct web_server *<U>server</U>, const char *<U>file</U>);</UL>
91<B>DESCRIPTION</B>
92<UL>The web_server_useMIMEfile() function tells server <U>server</U> to use mimes type file <U>file</U> for determining mime type by extension used by function <a href="/?help=functions#web_client_contenttype">web_client_contenttype()</a></UL>
93<HR><BR>
94
95
96<A name=web_client_addstream><B><font color='000077'>web_client_addstream()</font></B><BR><BR>
97<B>NAME</B>
98<UL>web_client_addstream - add an output stream to the client struct on webserver</UL>
99<B>SYNOPSIS</B>
100<UL>#include "web_server.h"<BR><BR>int web_client_addstream(FILE *<U>stream</U>);</UL>
101<B>DESCRIPTION</B>
102<UL>The web_client_addstream() function adds the stream <U>stream</U> to the output stream list in the current client node</UL>
103 <B>NOTE</B>
104<UL>The web_client_addstream() function can <B>only</B> be called from functions called by gethandlers registered by <a href='/?help=functions#web_server_addhandler'>web_server_addhandler()</a>.</UL>
105<UL>The web_client_addstream() function is obsolete and no longer in use on 0.3.4 versions, use web_client_addfile instead</ul>
106<B>RETURN VALUE</B>
107<UL>On success, 1 is returned, On error, 0 is returned</UL>
108<HR><BR>
109
110<A name=web_client_addfile><B><font color='000077'>web_client_addfile()</font></B><BR><BR>
111<B>NAME</B>
112<UL>web_client_addfile - add a file to the output stream of the client struct on the webserver</UL>
113<B>SYNOPSIS</B>
114<UL>#include "web_server.h"<BR><BR>int web_client_addfile(const char *<U>file</U>);</UL>
115<B>DESCRIPTION</B>
116<UL>The web_client_addfile() function opens the file <U>file</U> and adds it as stream to the output stream list in the current client node</UL>
117 <B>NOTE</B>
118<UL>The web_client_addfile() function can be called <B>only</B> from functions called by gethandlers registered via <a href='/?help=functions#web_server_addhandler'>web_server_addhandler()</a>.</UL>
119<B>RETURN VALUE</B>
120<UL>On Success, 1 is returned, On error, 0 is returned</UL>
121<HR><BR>
122
123<A name=web_client_gifoutput><B><font color='000077'>web_client_gifoutput()</font></B><BR><BR>
124<B>NAME</B>
125<UL>web_client_gifoutput - export data as gif</UL>
126<B>SYNOPSIS</B>
127<UL>#include "web_server.h"<BR><BR>int web_client_gifoutput(char *<U>data</U>,int <U>w</U>,int <U>h</u>);</UL>
128<B>DESCRIPTION</B>
129<UL>The web_client_gifoutput() function prints to stdout a gif header (with width <U>w</U> and height <U>h</U>) and the image pointed by <U>data</U>.<BR>
130The allocated memory <U>data</U> points to mustn't be smaller than <U>w</U>*<U>h</U>.<BR>
131The gif palette is described by <a href='/?help=functions#web_client_gifsetpalette'>web_client_gifsetpalette</a>
132</UL>
133<B>NOTE</B>
134<UL>The web_client_gifoutput() function can be called <B>only</B> from functions called by gethandlers registered via <a href='/?help=functions#web_server_addhandler'>web_server_addhandler()</a>.</UL>
135<B>RETURN VALUE</B>
136<UL>On Success, 0 is returned, On error, non zero is returned.</UL>
137<HR><BR>
138
139<A name=web_client_gifsetpalette><B><font color='000077'>web_client_gifsetpalette()</font></B><BR><BR>
140<B>NAME</B>
141<UL>web_client_gifsetpalette - Setup the gif palette</UL>
142<B>SYNOPSIS</B>
143<UL>#include "web_server.h"<BR><BR>void web_client_gifsetpalette(char *<U>file</U>);</UL>
144<B>DESCRIPTION</B>
145<UL>The web_client_gifsetpalette() function loads raw palette (.act) from <U>file</U> or if <U>file</U> is "EGA" then this function setups the palette to EGA mode<BR>
146</UL>
147<HR><BR>
148
149
150<A name=web_client_setcookie><B><font color='000077'>web_client_setcookie()</font></B><BR><BR>
151<B>NAME</B>
152<UL>web_client_setcookie - set a cookie</UL>
153<B>SYNOPSIS</B>
154<UL>#include "web_server.h"<BR><BR>void web_client_setcookie(char *<U>key</U>, char *<U>value</U>, char *<U>timeoffset</U>, char *<U>path</U>,char *<U>domain</U>,int <U>secure</U>);</UL>
155<B>DESCRIPTION</B>
156<UL>The web_client_setcookie() function sets a cookie on client browser with key <U>key</U>, value <U>value</U> and expires at <U>timeoffset</U>.<BR>
157timeoffset format is one like <U>sign</U>, <U>number offset</U> and <U>directive</U> <small> (i.e +10m, 10 months)</small>
158 <UL><U>sign</U> is on like '-' or '+'</UL>
159 <UL><U>number offset</U> is like +<U>5</U>M means expires at next 5 minutes </UL>
160 <UL><U>directive</U> is:
161 <UL>S - seconds</UL>
162 <UL>M - minutes</UL>
163 <UL>H - hours</UL>
164 <UL>d - days</UL>
165 <UL>m - months</UL>
166 <UL>y - years</UL>
167 </UL>
168 path - Subset of URLs in a domain for which the cookie is valid
169 (If the path is not specified (path == NULL), it as assumed to be
170 the same path as the document being described by the header which
171 contains the cookie.)<BR>
172 domain = Domain the cookie is valid for
173 (If the domain is not set (domain == NULL), the default value of
174 domain is the host name of the server which generated the cookie
175 response.)<BR>
176 secure = If a cookie is marked secure (secure == 1), it will only be
177 transmitted if the communications channel with the host is a
178 secure one. Currently this means that secure cookies will only be
179 sent to HTTPS (HTTP over SSL) servers.
180 (If secure is not specified (secure == 0), a cookie is considered
181 safe to be sent in the clear over unsecured channels. )<BR>
182
183</UL>
184<B>NOTE</B>
185<UL> The web_client_setcookie() function should be called <B>only</B> from functions called by gethandlers registered via <a href='/?help=functions#web_server_addhandler'>web_server_addhandler()</a><BR></UL>
186<HR><BR>
187
188
189<A name=web_client_deletecookie><B><font color='000077'>web_client_deletecookie()</font></B><BR><BR>
190<B>NAME</B>
191<UL>web_client_deletecookie - delete a cookie</UL>
192<B>SYNOPSIS</B>
193<UL>#include "web_server.h"<BR><BR>void web_client_deletecookie(char *<U>key</U>);</UL>
194<B>DESCRIPTION</B>
195<UL>The web_client_deletecookie() function delete a cookie on client browser with key <U>key</U><BR>
196
197</UL>
198<B>NOTE</B>
199<UL> The web_client_deletecookie() function should be called <B>only</B> from functions called by gethandlers registered via <a href='/?help=functions#web_server_addhandler'>web_server_addhandler()</a><BR></UL>
200<HR><BR>
201
202<A name=web_client_setvar><B><font color='000077'>web_client_setvar()</font></B><BR><BR>
203<B>NAME</B>
204<UL>web_client_setvar - sets a variable</UL>
205<B>SYNOPSIS</B>
206<UL>#include "web_server.h"<BR><BR>int web_client_setvar(char *<U>name</U>, char *<U>value</U>);</UL>
207<B>DESCRIPTION</B>
208<UL>The web_client_setvar() function sets an variable named <U>name</U> with value <U>value</U> in a connection, to be used in output (only available if WS_DYNVAR flag used)<BR>
209 web_client_setvar("bgc","#ff00dd");<BR>
210 printf("&lt;BODY bgcolor='$bgc;'&gt;"); - will exchange the string $bgc; to #ff00dd on output</UL>
211
212<B>NOTE</B>
213<UL>The web_client_setvar() function <B>should</B> be called <B>only</B> from functions called by gethandlers registered via <a href='/?help=functions#web_server_addhandler'>web_server_addhandler()</a>.</UL>
214<HR><BR>
215
216<A name=web_client_getvar><B><font color='000077'>web_client_getvar()</font></B><BR><BR>
217<B>NAME</B>
218<UL>web_client_getvar - gets a variable value</UL>
219<B>SYNOPSIS</B>
220<UL>#include "web_server.h"<BR><BR>int web_client_getvar(char *<U>name</U>);</UL>
221<B>DESCRIPTION</B>
222<UL>The web_client_getvar() function gets the value of variable <U>name</U>, (see also <a href=/?help=functions#web_client_setvar>web_client_setvar()</a>)<BR></UL>
223<B>NOTE</B>
224<UL>The web_client_getvar() function <B>should</B> be called <B>only</B> from functions called by gethandlers registered via <a href='/?help=functions#web_server_addhandler'>web_server_addhandler()</a>.</UL>
225<HR><BR>
226
227<A name=web_client_delvar><B><font color='000077'>web_client_delvar()</font></B><BR><BR>
228<B>NAME</B>
229<UL>web_client_delvar - delete a variable</UL>
230<B>SYNOPSIS</B>
231<UL>#include "web_server.h"<BR><BR>int web_client_delvar(char *<U>name</U>);</UL>
232<B>DESCRIPTION</B>
233<UL>The web_client_delvar() function deletes a variable with name <U>name</U><BR></UL>
234<B>NOTE</B>
235<UL>The web_client_delvar() function <B>should</B> be called <B>only</B> from functions called by gethandlers registered via <a href='/?help=functions#web_server_addhandler'>web_server_addhandler()</a>.</UL>
236<HR><BR>
237
238
239<A name=web_client_HTTPdirective><B><font color='000077'>web_client_HTTPdirective()</font></B><BR><BR>
240<B>NAME</B>
241<UL>web_client_HTTPdirective - Change the HTTP header status</UL>
242<B>SYNOPSIS</B>
243<UL>#include "web_server.h"<BR><BR>void web_client_HTTPdirective(char *<U>directive</U>);</UL>
244<B>DESCRIPTION</B>
245<UL>The web_client_HTTPdirective() function changes the HTTP header status (i.e. "HTTP/1.1 200 OK") to the string <U>directive</U><BR>
246<small><i>useful for "HTTP/1.1 401 Authorization Required" (to require a password), redirection or similar actions on the client side</i></small>.</UL>
247 <B>NOTE</B>
248<UL>The web_client_HTTPdirective() function can be called <B>only</B> from functions called by gethandlers registered via <a href='/?help=functions#web_server_addhandler'>web_server_addhandler()</a>.</UL>
249<HR><BR>
250
251<A name=web_client_contenttype><B><font color='000077'>web_client_contenttype()</font></B><BR><BR>
252<B>NAME</B>
253<UL>web_client_contenttype - prints to stdout the header "Content-type: */*"</UL>
254<B>SYNOPSIS</B>
255<UL>#include "web_server.h"<BR><BR>void web_client_contenttype(char *<U>extension</U>);</UL>
256<B>DESCRIPTION</B>
257<UL>The web_client_contenttype() prints to stdout the header "Content-type: */*", where '*/*' is determined by <U>extension</U> (i.e. "html" based on mimefile produces "Content-type: text/html\r\n\r\n" and "jpg" produces "Content-type: image/jpeg\r\n\r\n")<BR>
258<small>this function is used on <a href="/?help=functions#web_server_aliasdir">web_server_aliasdir()</a></small></UL>
259 <B>NOTE</B>
260<UL>This function uses mime types loaded at <a href="/?help=functions#web_server_useMIMEfile">web_server_useMIMEfile()</a> else it will print only "Content-type: text/plain\r\n\r\n"</UL>
261<HR><BR>
262
263<A name=web_log><B><font color='000077'>web_log()</font></B><BR><BR>
264<B>NAME</B>
265<UL>web_log - write to logfile</UL>
266<B>SYNOPSIS</B>
267<UL>#include "web_server.h"<BR><BR>void web_log(const char *<U>format</U>,<U>...</U>);</UL>
268<B>DESCRIPTION</B>
269<UL>The web_log() is similar to printf, but writes to a logfile (specified in <a href=/?help=functions#web_server_init>web_server_init()</a>). Just as printf, it doesn't add a newline at the end.</UL>
270 <B>NOTE</B>
271<UL>The web_log() function <B>should</B> be called <B>only</B> from functions called by gethandlers registered via <a href='/?help=functions#web_server_addhandler'>web_server_addhandler()</a>.</UL>
272<HR><BR>
273
274<A name=ClientInfo><B><font color='000077'>ClientInfo</font></B><BR><BR>
275<B>NAME</B>
276<UL>ClientInfo - a struct to control client Header</UL>
277<B>SYNOPSIS</B>
278<UL> Declared in web_server.h <BR><BR>
279extern struct ClientInfo {<BR>
280<UL>
281 int <U>outfd</U>;<BR>
282 char *<U>inetname</U>;<BR>
283 char *<U>request</U>;<BR>
284 char *<U>method</U>;<BR>
285 char *<U>user</U>;<BR>
286 char *<U>pass</U>;<BR>
287 char *(*<U>Header</U>)(char *handle);<BR>
288 char *(*<U>Query</U>)(char *handle);<BR>
289 char *(*<U>Post</U>)(char *handle);<BR>
290 char *(*<U>Cookie</U>)(char *handle);<BR>
291 char *(*<U>Conf</U>)(char *handle);<BR>
292 struct _MultiPart (*<U>MultiPart</U>)(char *handle);<BR>
293 void *__pad[5];<BR>
294</UL>
295} *<U>ClientInfo</U>;
296</UL>
297<B>DESCRIPTION</B>
298<UL>
299<B>ClientInfo-&gt;<U>outfd</U></B> <UL>is the filedescriptor of the current output stream (useful for cgi handlers and friends).</UL><BR>
300<B>ClientInfo-&gt;<U>inetname</U></B> <UL>a string to inetname (i.e. "127.0.0.1")</UL> <BR>
301<B>ClientInfo-&gt;<U>request</U></B> <UL>is the requested 'file' (i.e. for "GET /index.html HTTP/1.0\r\n" the ClientInfo-&gt;request is "/index.html")</UL><BR>
302<B>ClientInfo-&gt;<U>method</U></B> <UL>is the request method ("GET" or "POST" etc..)</UL><BR>
303<B>ClientInfo-&gt;<U>user</U></B> <UL>AuthRealm username</UL><BR>
304<B>ClientInfo-&gt;<U>pass</U></B> <UL>AuthRealm password</UL><BR>
305<B>ClientInfo-&gt;<U>Header(</U>char *<U>handle</U>)</B> <UL>Function to parse the header, and returns Header information (i.e. for "Host: http://127.0.0.1:81" the result of ClientInfo-&gt;Header("Host") is "http://127.0.0.1:81") if argument <U>handle</U> is NULL then this function returns whole Header from client</UL><BR>
306<B>ClientInfo-&gt;<U>Query(</U>char *<U>handle</U>)</B> <UL>A function that returns the query value from the browser (i.e for the request "http://somehost.net/req.html?id=5&f=1", ClientInfo-&gt;Query("id") is "5".if argument <U>handle</U> is NULL then this function returns whole Query string from client<BR>if the handle have the char # first (like "#handle") it returns the number of variables (usefull for checkboxes and etc...) Check <a href='/?help=examples#checkbox'>checkbox example</a></UL><BR>
307<B>ClientInfo-&gt;<U>Post(</U>char *<U>handle</U>)</B> <UL>A function that returns the Post data from the forms with method 'POST'. <U>handle</U> is the name of some &lt;input&gt; tag.if argument <U>handle</U> is NULL then this function returns whole Post data from client<BR>if the handle have the char # first (like "#handle") it returns the number of variables (usefull for checkboxes and etc...) Check <a href='/?help=examples#checkbox'>checkbox example</a></UL><BR>
308<B>ClientInfo-&gt;<U>Cookie(</U>char *<U>handle</U>)</B> <UL>A function that returns the Cookie data from browser. if argument <U>handle</U> is NULL then this function returns whole Cookiestring from client</UL><BR>
309<B>ClientInfo-&gt;<U>Conf(</U>char * <U>topic</U>,char *<U>handle</U>)</B> <UL>A function that returns an value from a <U>key</U> in <U>topic</U> in the config file if used</UL><BR>
310<B>ClientInfo-&gt;<U>MultiPart(</U>char *<U>handle</U>)</B> <UL>A function that returns a data structure from the forms with method 'POST' and enctype='multipart/form-data' (useful for uploading files). <U>handle</U> is the name of some &lt;input&gt; tag.<BR><BR>
311the structure is<BR>
312struct _MultiPart {
313<UL>
314char *<U>id</u>;<BR>
315char *<U>data</U>;<BR>
316unsigned int <U>size</U>;<BR>
317char *<U>filename</U>;<BR>
318void *<U>pad</U>;<BR>
319</UL>
320};<BR>
321to be used as ClientInfo-&gt;<U>MultiPart</U>("file1").<U>data</U>; ClientInfo-&gt;<U>MultiPart</U>("file1").<U>size</U>; ClientInfo-&gt;<U>MultiPart</U>("file1").<U>filename</U>;
322</UL>
323
324</UL>
325<HR><BR>
326<A name=configfile><B><font color='000077'>The config file</font></B><BR><BR>
327<UL>the config file is used as<BR><BR>
328<PRE>
329[TOPIC]
330KEY=VALUE
331
332libwebserver configurations must be in topic LIBWEBSERVER as:
333[LIBWEBSERVER]
334LOG=help.log
335PORT=80
336USESSL=1
337CERTFILE=foocert.pm
338MIMEFILE=/etc/mime.types
339LOCAL=1
340
341LOG -> the log file
342PORT -> the listen port that will be used for tcp connections
343
344USESSL -> the ssl flag if you want to use openssl for secure server (https)
345CERTFILE -> the file that contains certificate for ssl connections
346MIMEFILE -> the file that contains mime.types similer to apache mimefile
347LOCAL -> only accept connections from 127.0.0.1
348
349</PRE>
350</UL>
351
352</font>
353
354
355
diff --git a/doc/info.html b/doc/info.html
deleted file mode 100644
index 05883540..00000000
--- a/doc/info.html
+++ /dev/null
@@ -1,25 +0,0 @@
1<center><H3><font color='007700'>libwebserver Info</font></H3></center><BR><BR>
2<A name=what><B><font color='000077'>What's libwebserver for?</font></B><BR>
3<UL>This lib is intended to add webserver functionality to programs instead of using an external webserver.<BR>
4 Two examples for embedded webservers that i know of are simple (shoutcast (i guess), and webTV (teletext as a webpage (from pinnacle)); and many others probably do the same.
5</UL>
6<HR>
7<A name=who><B><font color='000077'>Who's supposed to use libwebserver?</font></B>
8<UL>This is mainly developed for developers to make it easier to write a web interface to their software, (note a webbrowser is commonly available in most operating
9 systems) so it is like a portable "terminal" that can be accessed from any computer (with a browser of course...).</UL>
10<HR>
11<A name=when><B><font color='000077'>When am i supposed to use libwebserver?</font></B>
12<UL>For example, imagine that you are developing a daemon and want to check stats or re-configure at run-time;
13 with this library you can add a listen port for runtime, and connect with whatever browser (via HTML interface)
14 without dependencies of an external webserver.<BR>
15 You can even do a webserver (of course), just use your imagination.<BR>
16 Another quite simple example, a sound recorder (using only local connections for security reasons) uses a web interface to control
17 /dev/dsp reading/writing (via HTML interface).
18 there are many other things you can do ...</UL>
19
20<HR>
21<A name=server_scripts><B><font color='000077'>Is there support for server scripts such as .php .cgi .asp?</font></B>
22<UL> Well, this library only provides web server functions that make a server running, server scripts can be supported if you want to do it:
23 you can develop a handler for type ".something" or whatever, this package provides a .cgi handler as an example, (use at your own risk or make it better).</UL>
24
25
diff --git a/doc/security.html b/doc/security.html
deleted file mode 100644
index cdcc2d79..00000000
--- a/doc/security.html
+++ /dev/null
@@ -1,67 +0,0 @@
1<center><H3><font color='007700'>libwebserver Security</font></H3></center><BR><BR>
2
3<A name=what><B><font color='000077'>Is it safe to use?</font></B><BR>
4<UL>Well, I can't promise that it's a secure software since that not only depends on the software,
5 but all i can say is that wasn't found any security bug yet, this was developed intended to be secure,
6 you can use openssl (encrypted streams) to protect information that passes from webserver(lib) to client</UL>
7
8<A name=certificate><B><font color='000077'>How do I create my own certificate?</font></B><BR>
9<UL>You can either buy one from one of the big vendors (see your browser's stored certificates
10 for their addresses) or self-sign a self-created one. The upside of the bought
11 certificates is, that the webbrowser doesn't ask if the user wants to
12 accept that certificate, but instead checks with the certification authority
13 you bought your certificate from.<br>
14 The downside is that it costs quite a lot of money.<br>
15 To create your own certificate use openssl like that:
16 <ul><li>create a key and request:<br>
17 <pre><b>openssl req -new > foo-cert.csr</b></pre><br>
18 As "Common Name" you have to type in the name part of
19 your URL, i.e. if your web site will be
20 "https://www.libwebserver.rules:443/" the Common Name is
21 "www.libwebserver.rules".
22 <li> remove the passphrase from the key:<br>
23 <pre><b>openssl rsa -in privkey.pem -out foo-cert.key</b></pre><br>
24 <li>convert request into a signed certificate:<br>
25 <pre><b>openssl x509 -in foo-cert.csr -out foo-cert.cert -req -signkey foo-cert.key -days 356</b></pre><br>
26 <li>create .pem file:<br>
27 <pre><b>cat foo-cert.cert foo-cert.key >foo-cert.pem</b></pre><br>
28 </ul>
29</ul>
30
31
32<A name=tips><B><font size=4 color='770077'>Security tips</font></B><BR><HR>
33
34<A name=racecondition><B><font color='000077'>Avoid race condition problems</font></B><BR>
35<UL>
36 <B> What is race condition?</B>
37 <UL>A race condition occurs when two or more operations occur in an
38 undefined manner (McKusick et al. 1996). Specifically in file
39 system races the attacker attempts to change the state of the
40 file system in between two file system operations on the part
41 of the program.</UL><BR>
42 <B> How the lib determine temporary file name?</B>
43 <UL>
44 <li>generate file name (note: keep generating until it doesn't exists)<BR></li>
45 <li>check if file exists<BR>
46 -<small>attacker can create the file now, if he knows the right filename</small><BR></li>
47 <li>check if symlink exists<BR>
48 -<small>attacker can create the symlink now, if he knows the right filename</small><BR></li>
49 <li>create the file and redirect stdout to it <BR>
50 -<small>attacker can open the file and write to it</small><BR></li>
51 <li>places a lock into file (note: not in win98)<BR> </li>
52 <li>users operations, write, flush, read<BR></li>
53 <li>unlink the filename from the OS<BR></li>
54 </UL><BR>
55
56
57 libwebserver uses temporary filenames to hold and process data before send it to client, it uses the ambient variables to
58 determine temporary directory by following order "$TEMP,$TMP,$TMPDIR and the stdio.h P_tmpdir", libwebserver have several checks
59 and it locks file for avoid attackers from messing with temporary files, meanwhile is safely to change the tempdir (setting the ambient variable)
60 to an directory that is not writable for everyone and writable to lib (setenv("TEMP","/safedir"); you can do it before the web_server_run function
61
62
63
64</UL>
65
66
67