diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/examples.html | 445 | ||||
-rw-r--r-- | doc/examples/SoundRecorder/include/debug.h | 24 | ||||
-rw-r--r-- | doc/examples/SoundRecorder/include/soundbuffers.h | 39 | ||||
-rw-r--r-- | doc/examples/SoundRecorder/include/soundcard.h | 31 | ||||
-rw-r--r-- | doc/examples/SoundRecorder/include/soundmixer.h | 23 | ||||
-rw-r--r-- | doc/examples/SoundRecorder/src/main.c | 296 | ||||
-rw-r--r-- | doc/examples/SoundRecorder/src/soundbuffers.c | 86 | ||||
-rw-r--r-- | doc/examples/SoundRecorder/src/soundcard.c | 49 | ||||
-rw-r--r-- | doc/examples/SoundRecorder/src/soundmixer.c | 104 | ||||
-rw-r--r-- | doc/examples/cgi-bin/index.cgi | 1137 | ||||
-rw-r--r-- | doc/examples/cgi-bin/simple.cgi | 14 | ||||
-rw-r--r-- | doc/examples/cgi-bin/simple1.cgi | 125 | ||||
-rw-r--r-- | doc/examples/cgi.c | 100 | ||||
-rw-r--r-- | doc/examples/demo.c | 66 | ||||
-rw-r--r-- | doc/examples/foo-cert.pem | 86 | ||||
-rw-r--r-- | doc/examples/packetmounter.c | 236 | ||||
-rw-r--r-- | doc/functions.html | 355 | ||||
-rw-r--r-- | doc/info.html | 25 | ||||
-rw-r--r-- | doc/security.html | 67 |
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 | |||
11 | This example starts the server with one handler for all requests pointing to hello_world() | ||
12 | that 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 <stdio.h> | ||
18 | |||
19 | |||
20 | void hello_world() { | ||
21 | printf("Content-type: text/plain\r\n\r\n"); | ||
22 | printf("Hello, World!\r\n"); | ||
23 | } | ||
24 | |||
25 | int 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 | |||
49 | This 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 <stdio.h> | ||
55 | |||
56 | void 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 | |||
63 | main() { | ||
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 | |||
88 | This example uses the struct <a href='/?help=functions#clientinfo'>ClientInfo</a> for fetching the input from the client | ||
89 | using the Query("img") to send the image <BR> | ||
90 | and 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 <stdlib.h> | ||
99 | |||
100 | struct image { | ||
101 | char *data; | ||
102 | size_t size; | ||
103 | } image={NULL,0}; | ||
104 | |||
105 | void 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("<HTML>\n"); | ||
115 | printf("<BODY bgcolor='EFEFEF'>\n"); | ||
116 | printf("<form action='/' enctype='multipart/form-data'>\n"); | ||
117 | printf("<input type=file name=image><BR>\n"); | ||
118 | printf("</form>\n"); | ||
119 | if(strlen(ClientInfo->MultiPart("image").data)) { | ||
120 | printf("%s<BR><img src='/?img=%s.jpg'>\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("</BODY>\n"); | ||
130 | printf("</HTML>\n"); | ||
131 | }; | ||
132 | |||
133 | |||
134 | |||
135 | main() { | ||
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 | |||
158 | Here 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> | ||
161 | user: "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 <stdio.h> | ||
167 | #include <string.h> | ||
168 | |||
169 | |||
170 | void 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("<BODY>\n"); | ||
177 | printf("<font color='FF0000'>Access denied</font>\n"); | ||
178 | printf("</BODY>\n"); | ||
179 | return; | ||
180 | } | ||
181 | printf("Content-type: text/html\r\n\r\n"); | ||
182 | printf("<BODY bgcolor='EFEFEF'>\n"); | ||
183 | printf("You entered in your area\n"); | ||
184 | printf("</BODY></HTML>\n"); | ||
185 | }; | ||
186 | |||
187 | |||
188 | main() { | ||
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 | |||
211 | Here we setup a server and we use the <a href='/?help=functions#web_server_useSSLcert'>web_server_useSSLcert</a> to use specific certificate file | ||
212 | and we start the server with the flag WS_USESSL for secure connections (libwebserver compiled w/ openssl)<BR><BR> | ||
213 | |||
214 | See 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 | |||
222 | int 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> | ||
234 | All 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 | |||
248 | This 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 <stdio.h> | ||
256 | #include <math.h> | ||
257 | |||
258 | |||
259 | #define GIFSIDE 320 | ||
260 | char gifdata[GIFSIDE*GIFSIDE]; | ||
261 | void 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("<center>Generated a circle (click inside the image)<BR>\n"); | ||
281 | printf("Pressed x=%s,y=%s<BR>\n",ClientInfo->Query("x"),ClientInfo->Query("y")); | ||
282 | printf("<form><input type=image border=0 src='/gif?img=circle&x=%s&y=%s'></form></CENTER>\n",ClientInfo->Query("x"),ClientInfo->Query("y")); | ||
283 | }; | ||
284 | |||
285 | |||
286 | main() { | ||
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 | |||
313 | This 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 <stdio.h> | ||
320 | |||
321 | |||
322 | void 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("<form method='POST'>\r\n"); | ||
327 | printf("<input type='text' name='user' value='%s'>\r\n<BR>",ClientInfo->Cookie("username")); | ||
328 | printf("<input type='submit' name='send' value=' GO! '>\r\n<BR>"); | ||
329 | printf("</form>\r\n"); | ||
330 | } | ||
331 | |||
332 | int 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 | |||
357 | This 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 <stdio.h> | ||
366 | |||
367 | |||
368 | void 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("<form method='QUERY'>\r\n"); | ||
373 | |||
374 | for(i=0;i<5;i++) { | ||
375 | printf("<input type='checkbox' name='number' value='%s'>\r\n<BR>",txt[i]); | ||
376 | }; | ||
377 | printf("<input type='submit' name='send' value=' SEND '>\r\n<BR>"); | ||
378 | printf("</form>\r\n"); | ||
379 | |||
380 | printf("You have choosen <font color='FF0000'>%d</font> numbers: \r\n",ClientInfo->Query("#number")); | ||
381 | for(i=0;i<ClientInfo->Query("#number");i++) { | ||
382 | printf("<b>%s</b>,\r\n\r\n",ClientInfo->Query("number")); | ||
383 | }; | ||
384 | printf("...<BR>\r\n\r\n"); | ||
385 | |||
386 | } | ||
387 | int 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 <stdio.h> | ||
419 | |||
420 | |||
421 | void confexample() { | ||
422 | printf("Content-type: text/html\r\n\r\n"); | ||
423 | printf("<PRE>"); | ||
424 | web_client_addfile(server.conffile); // add help.cfg file to output | ||
425 | printf("</PRE>"); | ||
426 | printf("ClientInfo->Conf(\"PERSONAL_CONF\",\"PORT\")=%s<BR>\n",ClientInfo->Conf("PERSONAL_CONF","PORT")); | ||
427 | printf("ClientInfo->Conf(\"PERSONAL_CONF\",\"IP\")=%s<BR>\n",ClientInfo->Conf("PERSONAL_CONF","IP")); | ||
428 | printf("ClientInfo->Conf(\"LIBWEBSERVER\",\"PORT\")=%s<BR>\n",ClientInfo->Conf("LIBWEBSERVER","PORT")); | ||
429 | |||
430 | } | ||
431 | |||
432 | int 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 | |||
18 | struct 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 | |||
31 | struct sound_buf *sbuf_init(); | ||
32 | struct sound_buf *sbuf_add(struct sound_buf *list,char *id); | ||
33 | struct sound_buf *sbuf_select(struct sound_buf *list,char *id); | ||
34 | int 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 | |||
20 | struct soundcard_setup { | ||
21 | int rate; | ||
22 | char channels; | ||
23 | int fmt; | ||
24 | }; | ||
25 | |||
26 | int 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 | |||
21 | void 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 | |||
19 | int PORT=80; | ||
20 | struct sound_buf *SoundBuf; | ||
21 | |||
22 | void 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 | }; | ||
60 | void 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 | |||
74 | void 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 | |||
264 | int 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 | */ | ||
16 | struct 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 | |||
26 | struct 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 | */ | ||
43 | struct 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 | |||
69 | int 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 | |||
17 | int 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 | |||
14 | int SDMAX=_SDMAX; | ||
15 | #define ADJUST_VOLUME(s, v) (s = (s*v)/128) | ||
16 | |||
17 | int soundout_i=-1; | ||
18 | void 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; | ||
8 | my %POST; | ||
9 | my %QUERY_STRING; | ||
10 | my %COOKIE; | ||
11 | my %img; | ||
12 | my $stdindata; | ||
13 | my $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; | ||
25 | if($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 | }; | ||
35 | if($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 | |||
61 | while(<STDIN>) { | ||
62 | $stdindata.=$_; | ||
63 | }; | ||
64 | #print STDERR "stdindata is $stdindata\n"; | ||
65 | if($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 | }; | ||
75 | if($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 | }; | ||
85 | if($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 | }; | ||
94 | sub 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 | } | ||
133 | sub 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'; | ||
157 | 7494648393164f108c007e00002020401478c5789042788461ac80946c8492658cd58c82336c4644fa88119a7ae07e32b56ea0958c74478e96b2e896f1cd98238882724494649c7297cd7a33ac31244b7c718e94888e87148e7414aa54035e91d5ae83b4cd99337c77837b46f10680e18ab2a34b8e117a85d28e753835a2037a90032c48c59d7b03ac83775c7303ca89f06c75948c9197da8752ac60478e86d88d7ca3ababcb346aa6da7b41d356a41f48f38ca697be71298e72688e7398bea0e82f79539c87968e57a7a5be36aa65950f75aa7aa1549aa3a38e8524d553d07c75178893915faa237f5078f541127f76c88a84f47f91a89d82d77f94388d81158c84558d83247c49236d40a7ddddcd8d82746c4823265441ca87f47d7d138d93e76c4a12fd8806ea76068f95084f4b339d75347f62d89d81d77f93689b45d58881329d7065678ab27778120e79d57d76b3ab84e52e7a75ececcc2b8de04c8b027f77a49d74e73772018656128da6288f76e3abb5e5187c43ba80f58d74159d87c68d87336a83858fd0688dc0c7efefcf030313d87e33276972f37976158b85e9e9c96697d1d34725a77b730d5e62d395743655b1687571488d33d957631988720689a3292949478380194f43e55813264ac4515151e56745ac4c12fa5fb1578131ec8d4215a6e1282848856d16a3a3837a82d5a96b01b4a57155a7d3ba81267f7c739f6db3cc0f12d95444f853734f88960a8cb16780a1979401e986407982432554c1a99513fe79466f82858f74f38f73c48f7514776542f4b6653a88433a69c2c463e3ee6ac5e8aa426879f177c7e1d98d029970146fb1458f8727a96183d4a815269270d49a35e4b9f5fd7b056529c69b8582ab72d6a766808994819d9473ab90749b71148d856769d3c09b8076bb83866fa0858b77f0ab8765ab86e5d455354cc9923cc8233cca32e5d84306ca55a7a787997e82e59bd5db84b24b9273bc82357e76f59c83456db2f9bf8685c98673a484846bc6e1e5d1c1e9c793ecdc82f3e69524c7e40bbac0bb71078bb383bf95fa9993043b58743b69533fc8b34fcb538cc6048ec2a4acc194ffffff12efe0d41646560277964786027494d40500129f4010a000ff00c2000000004f108c000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b7efc0a34b8e1d4ab4b9e3d8a35bae5dcab5bbe7d0b36bce9d4bb6bdebd8b37beeddcbb7bfefd0c38b0f1e4cb8b1f3e8c39b2f5eccb9b3f7e0d3ab4f9e4dbab5fbe8d3bb6fdecdbbb7ffe0e3cefb8f1f4ebcb9f3f8e3dbaf5fcebdbbf7f0f3ebcf0beb441b2651c2898bdf288fbe7742840820a32e80e18742286c0296452470d1c806154c1321e133745811440aa0c270110f7c9136c603c8814b09191c5042ca1b704035814908e2e2cb395c32e5ca3e5031c44821a0d35dce8d2c409e4a3b5c50714016f8d3140c0424d173cd0ad871e5001c44f11a0c22c45966c58748b28bc141b4c2cb4c221489b8c89534c3888c31001248c8493881e6a81d40c9d40e0472e0b38d9b34e9b3421b7621e7ef9e7230c7230b3c9145c1af242a982a42e0082060840a1880e02388541d453c1a7802a8842a9882240501739f4b8f26c8336d8736e8b3653d3ef814e09ef54e1994e29d4e3915e495562485ceabb679f568921c89b8499766a948cc08c212104002f4e29bc82bd0611bc427cc54e66c9d4cc957ed9a76e9c720a0ea0ab301a6822aa8eb0bae246f1e7bf152a9052bf5cb2fa02490db5fa0229e4a96438f064821a5839068aacd3605b005c60b14b96b0914609044c9357c51dd073605e3ab0e303e3295ca3056f16d4925a4538e6bab5cba44ad3034aca4239e42319a8495c4592c891aa8a2308b2eac145249054490cbcfc0a8893c6c31f40052db984b8157e2d872e997af1e7c5305b4de7c8b3eef185b1aa8a8c72dcb5f2527f6eb815b06032ca033ce034c75814a04e3bbc5c91f6cd1f7c12f8ce369c24e9c923efc0b27dae23cc9b224398fb7ccecd3ffccb40d1ce0d547a9338a9bc4008983bc8c3839c5e37891a93549433dbd27ba7e4d2a75d482308577845c9b8e653b01b2f6403228622bb6222880fafbe8f5e7af50806fdbe8422af2fb85c4841a58110c2aac14e4831df4f3c07d2f4c713dce1b747180de2f6be2fec322367c1a48c974534fc40310ed24619642fdb4ed0958da2569213b035c0c281e0074c11909b3528efb372e14f63b804947e0e4930d613dee405b40a201a6972c10300707abf34ae415921dd983877063140184326e85e53fe97f4842d93412e63d586f8b7eebfe5532c73eb2fdbae208eb32dac8d79248f50e2127c0778e0578bfbd99fc041efffb1a1a969133846c23c815989c938071ea8bcd58cc01f331844cd483020a1079680c50e20b18f0c80e40546ba358cb1a673b311883ed0809bf4eece530248c0f478b903e568012b50d1c500a7f58f2c93c70c7051124650624ded6f6d1f73484a0c46542599290125c8c38cf866aa8bf540a2480101080490a40e16ff8d1ce849c5b8a8a4ba3d44ee4f78badf1e5031c541a44d8b6ced902832784e0cd13a7a74e3e24209fe814efd2413116f5bfcb71fb26434c294c4c42f0322470c5031de7740850c2a815c0318902a11d888082d37b3815a9ee499a447df18e1264236de812430a1cab2f3df975e246e0ee052cc163171a93e142304b4578f0c70d5ef8e28a1012a005006fc48f88578c2812278cb9d369082ba34d18123fb84aa2e98b9848013d296ccd9da42e4554a35e0449619802a292892150493fc9bbbe88e1e205fcd3ee1812ff4d54045617ba25854cb71a8c38327e7c0998ae459041964c008a191a270c24a14dcb4110ca9a15fc574528dd4a708331236c17634650dfc97882ce3ab378c626ba75a3e124ec17e0578a38818fce20508b0801f58f3f71adb57834a0a72b520fd619d09b7c3453720865424490a35a8ab38521a45a664cc502d39ca08aadfcba6eea3206522885981ba855ce395a09877ca3836f2bfe564241248a25134809cb58c62040b90eb2f5989611a68a6bc15e0128434a14088efd251022e93a3dd9432a8a61c73512220450442109083c255dc98f9788218ba660d0d146f809d55cc24d0d68630a00123f0f506f021f80880ca2d7a0de1044cc02080fa00412a34c4e96f29c21c1c51d6bc197106d8c69210e607f0b225bf4746d0e302643752b39d58cbde5a9a8b70e846aa19b922fa1251ac1697139711d0860240ca5f7450a204083381ae128d4e6d64eb9d20f7c40a91901fd2440b14269f226960119d486e220f55c04467613b8638234910f8380b2441ef4d58442804429b2c06f0730fe2444812ed88a0e6e041a3e6b269c9edd693da3246be15a484c5260e2557e1d1996c93c5cecde58c8b1259518ac2ee103bc3074a81352762ef346e039063329b24646b8093ae1a2830c10cf1058a0cf181076842834c6ba72c10f92b9c112fd78732cc8f0c70ad152e3ce4445cb933848512b3b8e5cc8360a58380d0caba3ed13af6ead38b1844400d5d48c5e037076dbea4670553f69e9c32d3a904b00529865433a1b1908d5ca02bc065a47f2c2dd01bc26650c5a0b967406135216e24a98d4c357b9332500a3ba0ca065048130eade09e657bcf40b62fd64a005006688b71d8b6a809adc070903c932e0ebe917d89d68d3a84f855614ec2c44a4d801c993bb248ee55f7bcb5c7af809de9a6210778bb006be273742c0ae667779591d09748c2461106c1532dcc7ce89134076c1f66f420ad0d092841efca0df0b2c206818388a534eb5c2fd311ab324f8e0b64450437514108c198e674542cb9ee968a32e0f2691f47b26d9e984ca4d71aec60542298fb388f4d7accc320b875de27d350c50ef20494dc5505f02748b71dd1982c43c1b047817b1a1289de302bb8d1ebf886c712d888bbcdb11ea8108640a10d0d3841830df0a5c9c781d486886bbaee70094cc532676b33dcbbecc0b8c87d02a7803836981638950f0820347e842219e950b73542516777afcdf7a7f369c0eb18129caf9421fa87ea78bb328e08684e7ca638550f0a1232845c01ed75ced1184e688099bf8e53216086460230c10e08d286122a0c334e4f927c1084c7f91990b43cf12d86db744aef0a70228d186f3b0a0050c32cdd5f563cb0f1970c30e51d8095432e91fc0a64a7fe4b4bc692562c316ceb2ebe10b7eeb7ff7e6b7d01a10bb7240240635c24d21ae7a08be7de7a11e004404400d35b0460b034b04b0d01c439d28d2c311b5d187d7676bd7ef77b0170170630d103e7d11e36a42d30fb49e7f00795fa0317320fc09e5b15a15260d62a41d18d185109d7700d117008e0250910440f50f37630d013401201a02d01e3b324f0026c21f00f80358ae7be0f28e086706707b07b00d36b0f40c03818554d62468e62c18b381b5510ef0e11148c109107b02655287b7d11234be3e42040f11cd3105795320320c40c21930188a30838930a30930a38ef868968b68c11ef0700227448fd7848c015e0fa51d0c24d24d21a78a98795a11428a58c587b0f405b0c10460d011887a8260a30c035a8b31d88ef02164161b5e11d88f887b0a588100a2d110303d0b23de3560d70f11bd3fe0e20be04c8cc0320c21a30ac8ac8ba8ca8841fa87760b8d18d11fa5650b77f68a58d012d0b245d01d0e45dc03109209989b44e8f804c8911630630e982657b0f507b0710e01bc8dc8c03f40c316e06e06506762d8e11316700df0c105b06b8670e00e11a05b42950770560c606d0f118f0d97d97ad0de0e508009c82f8242825a11158d217f89f8af8316745c112d0df87d86b8d014d4f205104f0ef0d147849113403114e89efb4f09e97711c30af09e8428ae0d854201f8710674242f401495f8811c091218e07498e05766765103b8a684d60096b87b0509b42e50ad0fb86d0cb4e118f0b599d09509d09d0800ad0c21242420719124f50911920549d218492488e0987c49c117763164270095b0d011b54f05104e3784b50270811a100c8211d97b59c598f0a47711af0c30b89739630810e30065324d01669710974699911c60221849150250248700650bd77009765795b05a9e11be3909b094f0406d11950789720f599d0cf0419b213d04207b9420f509b98697116d0c60560f21d69c99e990a9c112503d6876050ff8779c01603ef09206e0523e790f8611340c40f29389e0958ef9789889611a89b89c30010d50630b70810b25e018b99b99b9b40ae0b40811fb92211502f93f9500250f38d11910250dc3650ac96b0d777a9730e50b098594f0817d1172080a720e10d301a62a6b219420307e0b73e30ee9611c60fb9878e213f9b1a5f97f9b116c7af9527ac9c10d01d14e405235056224d9411c405607d9311ea9fa990add9411670630a89410d60d10d10a602e9011b7321a41ab40af571156004091a021c60150c20c20b1a8e0e114407c79c7dc33c055a7a9770d00c60dc04f07925d4e1190ad307204d3b70b05b21570013b749f59f561a64a7708e7e2171ab4ad4a3f9f4ac1101825ac77df03c0d01df0b50c10725469140cb9311efa10e2aa10cf72110b990a80ab70720511018b56810d50c30d10d60410b3a111b74030a6aba0af54c0511040e6ae50770221560560c4ac4aa70150500e11b58d585a9c773c07d0e11d00d006d0b5ad5a2d0f11c0ad50d3036a76ac21b70e30b704654c0d5019541171a5603aa909f21fb96aa8aa1500d0150d11f98faa009df0d015226227b9974b4051a1115f0c602e656078a3119d0c0a7209ea4d3411460710440a56c70d500107282e72117f4ba0e30195bfaf9a211560e6a909a095aa6aa7701daa70daa6da5a96b02bae116d0920d204165d05105e0b69c11aea36a3cae30030c219f4d1b7ca3b0195af5ae0974710460c10930b10360682f70d206efe03106d095a640cca64099907a0da50bc4a2f9d11e98eaaa0b399910bb9fda24ba84a05640640d000d93101d0f20ed87006d05f0ffaf10770cc0c6088a111c0aeba26ad50cea4b5b10df0a307253d08222fa350d10411d1bba07ca12b4c032bf5052b72b92bb2bd2bf2baca3aa6aa5bad0030b770b7b1dae11ae8a58f985b0b0be116e0d20400829dc06e08e04e0f1136a4d3e30570a1bc1ba6049b03669bd9ac6bae01a8c10a30b00b102147600503108e0920d00ffa77074b87bf21d2a7ab8aad4a5f9327050616c00b00df07c7e00810630c30840cbb060bf06a06a07a06a0bf0fb6639ae81706da6b0d01f50b4064824b34a7f47f4a053d02704ab58efb510f20400ef05e08e05f0c20770de0ad02e6376db4ebae8b2ca09b923801a43ed2360830bc3b50a703d026bd30c70611a60d50fc579b22bb40b9bd9bf9b4501ab3ab5ab6408ab8ab87b9202e8121c40040cc0b7b83b4dad11d89810e00f083a8718d117a4400d168e02f9c20f111db1db24bc2149b49b1d5db003689b32b420f4072be9bc00450f70e168e095a56064056087bb50a0cd21632d6ac7b37aa201bb2bbc003c0ff8c5863abbb840060ebb0cb7a02cbbf0840db06cbe8941c7b0910d01265fdae9a7f4b733fb270523e40ef0a1c4f0a8b2f98008009d0e10cf0f105604e0c8b211570b60a0546a22c24a9746f0149c03188372b30450b30360ef788d110d572c92c22bee8d2c930f2c13c33c53c63c93c920bc322163274acc00daf6cc11b3a01045cf080d09dad117605107f8d1cc20800cf0f11570b73fda030805c2193aac01d5fac03621185a93cb509e0e40f219a0632320d0c0dacaac11a3a010a9c010c70f08bcbccbdcbfda642211cf0750750a6cf10800e6c311cb821ac7392341ab01b15360d7cb30f700fb8e070b9111d523682c02b44a11184b5237bc360360221fc039c59cd6c11cc1179a99c4ccc070d0e11050e40cd7c07cf0e10b63e11923fcbaccc2107033690dd602bc4112d9bc32d7e219a00fcc403206aa3fcd112e77fc4ccb60d010d3149f50249349311a6c76cc20fbc1110fa6efb940d32ce01782d203601e85abb4a81190d1bc02bba0ae0d0dbc36382217f09a0abcc4058a4e053b5fcc50d10cd0010dd0c70c705c7bd7a702fbcf02fadd066be11ab9f508e31b2c21ac0990130130336d60a603b0611e4082bb15f2130304d14d34d79ca1182076574dd10b1dd01bc73f84602607113b9160d8721162265d77c6f038ad01fe53106e0920150d00fdb6ac511d5df5d82c89b6116b5e76121aa04d0f3dabc78a65bb11070ed0ed0cd0c503500108d0b604b9c11feab60c70922b3a45dd11f4008d699140149c21d5d3bdfac82c711b1597276d194f3d632e0699d911070070820c50cd0cd0350dd0e10d01b10727618260087ec76113ad16ef03117104f414928a75d140211d32a69d00b4a770ad0a8d3114bdac0fc5f8d611d722212037f0340ded5f0120e11b9ded0c504cd3507508d0f10e11b56922a602e764df1106812df40242c21c90a50a50c8d1d5df551105329dd211f4533ded3405f051b9119902fd4fd6cd20db017607d6b304537d0e0e1ddc1d211ba897c12d3114e303bfb94ace5043a01180ee5d1d53b0af0e3093d711940587121a267c39121200161fd1cdc9d4cddd07fde1129ac3069afac79af113f8bc8a30c21a80a8070e13082033e911cd6e21b557128c30b0f3e5e0d1171e24e91edd0d01c767d686e053911b6042e6d4322260dc8aa8411dc06d0eb9c60b7bcf0f5931113eeffac06d739e309110ddf11da0096ec40b05081fd4303f0b8e3f0c50b2064ed11c303b0840ac0bf08208406fae11e62f4eac89e0c218a035e80e336410b0e611a3ed21b46a939c578e88ec11610070a8ea8eb8ebb6c01cf9803bcdb00618a116fb2119d2843bc8e9e311a6971a77e0ebad0e20f2ed0135e55efac8fb4c017018e221b46da01e56606201d4e11fae430070b8eed0a00cd0900e11db0fbb6a0ac006079e840f11072830b159e0930f32f9ea8060e55e89e5ae5416949ae1e50d4254eaefaecdecdeed04beb016d86e0df0250a30c9b75cd21453554372e621ce31167effaad0ad0f59b5911170e0f079e79af7ec31a403de1e5552cfec115e45efe4c8ea00e8ee110cb0cbbf0d2f060828d114f7c43eecb218a08a060e0f013091da41ee002002f1e52d4d1143061062fc8e856c01150f4da77f4de03e21f72d04b43511b2e7abe2ede071f01183f55e06da9c299a31934b554de2000d498eb8e2be3f0a0020fb112cbb2fd2fd2ff11e7c78213c7a3f9e0aec90a1f65ebad741212ee006f2e5ac6b1152f1bec8ed01c200d0c20c077e0f03d5fb21e43d7c17ff70c6a31f51f9d0b5956ef012fe55ee6da60af08100deb315401126c3e5524f66f76fb8ea00e11e4cb6fc2fbf0f1101485317f78250ec904bf93fe6d97f6411b00af5c37123af08f28f64fd0176c800c6eb70cf06e9e21930eebcdc7a32bf51ef1fca559e2e49f8f09f085f67f8207bfd10810810c313a01b0bb27937f32f724fa0076f5ef55574fc11aafb6fbf00609eee119e0dec360ab5ab509fb21f600f067f77fc4e9411b0edf0ef00139e8c11a6ffc0e14489051e2cf7436edc350115223c48e18f870b8c7020405341d3e74098057c6947e42d5ab1392ff484f856ee863d69d462eb319f85a14e40f0e5624141a3040c081e6e052a0274d1564c8c59ba6430a828488215aecb7af1f4d5535bf09021e1c3aae7429723dd486146fb684f6ed816626bd6b76783b175e624908439e2d6a37116459a1134e510cdd02c4153d1828edaa274ec616c267c6c579f236663a98fc62b47bd3920f80a88d372efc15d9443d1a3ecc9d38fcff65ca66db262e7e35951cc6dea6325ff393d025cee4792624abbd603f5e3e2c01e0c1e98249bfc0e80394296e7071d1d1d5af4f7ec7a0a5bbe5112bb90e92cd8b150a0822af148bb07ada75cab777a88bc68d8b48933f447bb99c97afce0d9fcf3f3b6abe484934e01062d00625bc76795181cde25b814bae587855c68832e8bdc8896c8860a3ce01ebbdeebe6e23582d231db12f2db6ee938eec390619a160c34a2930314fc68360d1c5d2421f8b0e28c38349981ecbf7a03688f953018d07a1f0b109ba109fac0af62bc68523192041f7280c183fcf8b6ea90036425a29f660914e794d210537dc4085b4d4996387895a24cef0c7837e6bb1e60324f4e0b3cbd62b318221f6c3a0e74e245cbde93f3cf022b608111913bcc33f33639dcee042e2c4483058c4260872a3d8c8c58e48e16f0e72fcb1634324e2b6a5582d8061ee040262698281fc0df9c601aa9b54b988b019a1011978cc140d0432537129d77a2db4d3be54d053ab8a3fc937848bda70c63f43283401d33955b1e74b1a86a0279cde0ec544f3354b90f5fc3970858498536f3b46bed40471531d2f64936b0e1d24b86e6d8d343a9281ae0ee3253b5d35ea9062841ca9418d8828d061265402423712047732e3283f38dd164c88b4e9775e136eb9840d844219fcad9670b171e51b7318fcad086d60f1ce4212c0b635b92abef1c65b1e012efc2a882ac0b89120cea0808966a73abda9054f3622ff12484616f4e49956fcc5679d5867aed09e834ea3df751145e6b966d0e7a78e2a0e588b8638b127f4025118555ea61aca66e1ee09266124a6afa01c6320a67dfca75134c0a52e22420800c4e84221b445efc899f0037791b1891b9fc0ade26f8a3ec9968405ce63e6ceeb10f6dda914ccc9660d147c8e82822b8032e3ea0e327fe8f3367f9367546227687c3273662facf3bf0ee8f0a9f75e56fc14a3eaf5e483154eaffca10d3c8040ae0f0ea0a80e03135fe1e60d6c949be58dbdf968dc19db103a14ac887780432e25d567961138c0d12e2460997c91329159b59d5eac0cc066c80efa97f1879d7e247b702dd434f0b894d8738b1043d6cd1a100133b8edac26e8908ce0d1411400208d6c63e70f1c10bb34c0914c0d40f3421e36b8baadff887093ac9528b6881274918c13204026e818f19d45fbcf5ffaf71260d192047430065800e740a812a311fd503b1cf8b34de2d7f28f3cb00a0c737f9ce042cf0e78706d0a2cdd9300307fb9b4c07684b0d10702e2580a3223887190468e03118704c4d3cf84e004293037cc867c76ab01ab534d16a1a816c831e33c5892c90c3087b82853048d283b4719a045833ceda506e005234850160614903c0b6045ea1c10b689b091e90e2481621670d48e745def147c248d1508690074105f2f7ca740238ef8f10222a0093130f41213981796893ca98150ee1f3aa4b0111cb10e12eb846638296d89b862f50f28a0c81e386e8f8c92f499a4704a33d9271712e0268b38c14e064227c3b412c00608c5223608db4c30f15f28e0378a040a18c20020989a7986de1028be990e61250e844c0c1029750d60202a0d00086b0eb9f202a831c9031059cf1639768f3cf16c0ef068410a000d069681c5af2522011aa2b10138c3d59a30130e0469838c1044fc347cb76d13918c8e5ee05e200d270a3450f74042b089128af19274aa8c4aae09e925692b43ccf674b79054051f60b0844329cf0400b04c827909a8490052df2293922c2086c82f5ae2570011c107b8aa8e08c07ef10234e047ab30c1c204e9b50934d3d00f904c2d11c1b8d17422c71eb89b8f342bdc83049320aa20592438911839b08e447b6854ac1250b5866ae5c2061cc7c908ca15047c40cf1a15e2695822a8164236470521f8684fc0c94688514a0250474104a0b25692112c013d892b4810c00c1c60a901f4d18e0e20a30fb251810368c1c61aa66f44c60591bb233ae7542b3ed3049750aa2d20054ec54829aa276f124256823852dc4caeed620dc8bf6ba6e303168880440c983da519f1c206da93039179d24e67c052d33cb084a51082034e7b0d0510b41a17c5864c4f61448a5cd4630b108eee5570b00c1857170e48d2841a0b55107077f70f38ee61261b59beff5cf2021171204e8b20b36f7c10cc170051c07b004ac3b0c92a51aba3822373e0d1b095e0cf5973462860cd8b2c4290cdada0438d4ae156c0d67a1718964012cc71021401e2071093c477b0a30f8a3124ab01828f3cc1650a3ff6dec910924604fc5b8b54d2c616b850c608107602431a79bc08d0437bf1930e08477abb08d10516bcbdd3ceb8f31ed5e5e990d47612438377c518e1ff8fcb9e558c3d0d54e145b230501f583919f092a35463044b4ad474d7b50dc0ebd40ca1052af824c200f87340b1e035ee6859b0cef0e86c52abe1d508a467b32d59024ca0a20fdad9f7ba7ed33f9ffc18e1471ad0d88e6e6e00e8c1043f8832df70820a85e0a787aef4b87c159e713c8d003e0b4c022d096084042e11fa87545584ad0e3301020e016f7851e00fbd59681aa2d6068bdce400b632c297734f5a7c399826180ba501f1de040410ae10ac71072b50c562c2995cc140810ac16092f4979994076e9ee2bd90dc658094910050c9b510a047ee74f34a0df0e04608305b02a7d28614b81647b70db4fd0c81630285413706dde15196b5984feef44cb5ed0e8a7bdb1210c8d7bfbff0486a283850e40fa3b410a14aef78a2532a19371f0c03db0a04b1a30d68ab73cd1e2a3525e662ed4e2b45c9e1dc8664baca1bfd211d0860fbe7388f2f1dd8c6c6610aef8e2e916c0769b0ca979d93866f606ce58e380ec37eb00b200efd5a0c104d760a8e6474ab2dfc07d83380a7c018ee92366b0a70aa351252ee38fd352910e8b766dd2d3f6b44428640c870c30461328118d2ba21da32f30519117ed4339e1d142a0d00e0610a1071ab1758107414a06e8c23512dde40d14a994016e593c0c70eef59fbf75e82f02090e5e03f8e6ff012f78e6f9169e058d00c9b508e9be78f33b50f33f3be70143ff360c0040042dbd28e78e2b5c8138a0094b61811a8e04680eb87bb43a7b840c400604e3e7b9928281301dbc2b083243803828308a6b38835a512c08dd1b10800d70b14530e10869d1ce288e35825426211d2fd02b0c532c332c2cb9f8230f205802e84b85c38389789200f36182000828ef202003fbbcb3b8af3cf3d18e70728c18f03d2cf7824b5e21db50043ce93304404b5050c5a360cb9b704b2880cd209ab5c0ac3a28a086106224f17e3f3cf3404c04414c14424c24434c34444c44454c54464c64474c74484c84494c944a4ca44b4cb44c4cc44d4cd44e4ce44f4cf4405c05415c15425c25435c35445c45455c55465c65475c75485c85495c954a5ca54b5cb54c5cc54d5cd54e5ce54f5cf5406c06416c16426c26436c36446c46456c56466c66476c76486c86496c964a6ca64b6cb64c6c264048d64e6ce6ce6cc6407c07c554f6427c27427417447c47cc4437467c674f6457487c87c444774a7ca7cd64974c7cc7caa1b74e7ca74d7cf7ef40849b8e7c184f7c08438c384f80a74340678b40008b4067034028c284484a8c384774730050000d8cd8400005073098477ca84194d74a74738684e84e8cb48f8409c67c19479c47ca7cc8449449405069c09c794c9cb6ca7434899ce9c884b9467cc941a4964b74678e9c9946700ac69c1a46ac564e7c39c3acd8cb405ac5ac6a4ba426ce7c8ac994aacaacba4face5c1848a4dac9a4eac0acfac3bcc542843a4da4d8c4ac2b43b44bc8b4954984e946b4008f9c7b43749bcdbc75409499c8aca947749100508acb40050910284eb45c455469439c8a459477c0488ac0484cc5c4bc4254b94c8ce94f8c6747cc1bc594b7cbc41d4054aac58c68c784cb4ef6741b4dac18c1d47dcd4ccb4b749c4bb4d84acc67cb402b40487dcdd4b4c8dca74910ad4e844c4674d8cf64edc3e4844fd4a7cfbc0ec0c437c2e4e644e49ec64ce6ca206849a4678a288dc5d4bbccd427c5b47b4ddc9ec1fc34ce6cd688acd68cbc0e44942ecd843e42f48fc044e6c9dc9cc7bc5f4e8c6f48ecb7c8f4ef4f3cd64af4da4bd4aacbf47fc7ec20ddfcefc40d3f00480785fc070ea4205df4274cfc8e4505b0d0e0040205ea46e4ad4908cf40087fcb05115db860dbf4f40aa40ecbfc1ec274a0540d11d71d3b0005ad41050a491d00d67c6151f481dd1d7a880501580d0e477cc15e152252a0f1d2b4738ee40d430590d22572d09832d7b4bef1dd84a1df0d01d725c2d48882d7bc1c4a9c51512d30dc25135588d255e428c61d13d43538880da25335e7443553d43520d7057355bc6b471d83dc25d0da35984dfcc35935705e3de3df1df3553d0ec63514da74cd4c3d245c25ee449444d445e7c64d835e05e8c0f4945984a4d835bec2c4900decc4509cd4dc35ea4f4804874db4804831d7bc15df35b94940205940aac65d24509c74dee40a4a5d64528cb55ad4fec6d4d5dd5dca4f1d30506d065165b7ce55c5dacc365a4de7456d7c4d4d66d655e7485dbf495536d965a6de7435d9cc555665d65d5d05d77c075d6d17d27547df7844d4756753805ec67587d4805ac875a7d48c98ca75c7dc75d7dd7925e7de75f7df7508d08518d18528d28538d38548d48558d58568d68578d78588d88598d985a8d84c08000b3 | ||
158 | EOL | ||
159 | $img{redball}=<<'EOL'; | ||
160 | 749464839316020002007e0000dcf6572eb90a9e1b4bae8babbe9bdbbe9bcb9e3b6b6e7aaa0e39799da7f72df5567cf465bdd829fe9cbc2f4d6d2f3d5d1ffc1d0fbcdcfe5c8cdefb2c9e2b5b7ebafa6e4a8a3ed91a0e49995dc6179c94151f0d2d5fdded6fedfd5fadcd3f6d8d2f1d3dee4c6ccedb0cbe6b9b8efa2b6e7aba4e0a4a2e89c90e1959ed98d81dd5369da8e85fddfd6f1e2e7f5e6e8f6e7e5fcded0f8cacde1c3c7eaada5e2a6a3eb9e91e3979edb8f8cd38885da6f67c24a4adb8f88f8e9eafcedeafeefececbebae4b7b8ecafa3ec90a1e4989fdc819dd4898adc7185db6177c1484bc2767bf3f4fcf6f7f3f5d7d1fdcfcae5b8b8eda0b6e5a9a4ed91a1e5999fdd819dd58a8bdd7288d57a73d26760c3494ffffff1fec0dfe6c8cdeeb0cae6b9b8eea1b6e6a9a4ee91a1e59a9fdd8296dd637ec25851e69a96dd6274d56b69ce364beabcb8d47a76dc6274d46a6fc25857d87d7adb7088d37876db6173d36961db5168ca3141e79b9cd1868ad97e77d17773d26861da506ac24944e1a5afde829dd68b8bdf7489d77c77df6575d86d63d06660d85e5cc84f46e6aaaceabdb2e99d91e29692de5460d65c5dcb4256e8aba7e9acafde839dd78c8cd08589d97e75da6073d2696fc35a5ccb4254e2a6a5e3a7a2e79b9eda8e87de6474d76d62df566ec0575bc84f40e2969fdc8099d87d72dc526fc55b5dcd445ac44b4bd1868ada7f78d37974d66c60d85f5ec1585dca4159ce3545db6077df6475d86e6fc45b5bc64d47c83f3cc15859d57b77d07574d36962dd5360d65d5ec0565cc94055c53c3bc44c48ca3241d95f5fc3595dcd435cc64d4ac04746c43c3cc74e4ac14947c73f33ca405fbf3648c54b44d86e66ca3248c34a42dd5468c93046ce344dcc4357c63e38ce3541dc5269c14847c83046cd3541c24949cd354bc54d4dcb415bc74e48cb3342c44b41cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab2312ef4137474696f60457e63756365727964797e2f6277600129f4010a000ff00c200000000020002000080ef00ff90c1840b0a1c388031a2c58801040010308041030700142050b081a1460d0c1c30801142c482041a2858b08123860d82073078e0c1c3c700111248881142a48983182258a068b2854b071f2c54b081f1024c09142760d8a163e60e8c1a321ee0f0d2874f0f1d3874b0f0f0a6ef00214c28091244a88193284e062970c1c54f052b4494f071c1894319022c9c3182154ac41a255cac51c26034c78e0f2c7c29c2b4c7cb8e0f14bc61e2d5cbc7103164c016b2368c41c23d4894cd9b57fe6eddbd7ff60e1c58dcc9143403d44870855b275fa065c2953b865daa953c6adc04732326048f0036861d3a947963d7a1517cb183174ecc1a320be888011104efc70f0f236ecca97337eece967ee0e9c1974fce118c7a0c40901102c3062f189c7c093259472581d78f1f70021880238012588046800178c40124c011431a5431114c012c4078001e5c106202298845648a12b922b80322053242001508802348021c61214802388050001428324380125c3209442290e139052374526980479832e505032410f3880c5880f341032050e583289441990a0a90e064851b9072d9012e9c7220d0143c105109041001e4471e40014109051c1043441720821a051f788244ac13a0925a89220d92248906149033401f4871f44013349061890244620a011e74428a4a2668a2a0ca2ca4b2ea804fa84188c50620d061041f5041ef610d062c508884182482e78d1f68510b4c297cc12b4923b0d2205d2f842216c9053801150811580153c9016422f886245442f68d27b4e08b4e2abce2cbce1dbc0465cd0d70a063c012548125c01630a0d7cd0090e0f70a265cd2390b1a8012d6032ebcf240972838f192cd044c4126c4144cd0928f183442648829a0c2930b1a00031c8033c0135c41427cf1670e05405142711838d1f781129851878911b0e2a8003594926cc138c8149ccb277cb164451e3b11f6cd1088a187c62398a2974e2484035a412b70d1acc14bc033078a165c5da60c18740266c42c98c1a0cc1ab4b12c813b7cf2dc424ecc33b689136891b64c19380276052d9c82ba8c2bb0c4323cc130d443c094376c0ec68c197c02a8cc148092ca492cb8f24cc43c2df34d0325dc82378e148c22598725a4b23b8537d06339f049d863bd0735a492694737c8734bc735afce4b7de4050400b3 | ||
161 | EOL | ||
162 | $img{yellowball}=<<'EOL'; | ||
163 | 749464839316020002007e0000cccbf61e4da98eed1b9e2e8bae0e9bae1e9b8efd3b5ead6afd1d298d7c971ddbe56c1bf4adccd8ee8e9c1fce4d1fce2d0faefcfe8eacee6e5cce4efb6ecdba5ead4a2e6dd9fd2d494d1cb68c2b944f1fdd5f2fed4ffe9d2fde5d1fbe0dde6e4cbe3ecbae1e5b7eddea3e7d0a1e4d89fd1d09dd0d880dcbd58dac984f0fdd5f1f0e6f3f5e7f4f6e4ffebdfe8e8cce6e1c6ebd9a4e8d1a2e7db90e3d39ddeca8bdbc284d4c966cea149dbca87f4f8e9f7fce9f7feebe4ecb9e0e4b7eddca2e5db90e2d39edfcb8cdcc389d9cc76cfa14accb17af8f3fbfaf6f0faedc7ecdca5e9d4a3e6dc90e3d59ed0dd8cddc58adacd77d5c472d1c16fb9a24ffffffee7e5cce5edb9e0e6b5ebd6a3e8de95d2cc6dc7b253dfb468cfad3ae2e9b7d6c475d3cc6ec8b156d5c779d8ca77d5c275d2ca62dfb360dbbb57ceaa30e3d79bdbc089d8c876d4c172deb160dbb959c1b24adacf78d7c776d4cf64d3c762debf5fcab85bc4b84be2eab0e2d19fcab65cc5bb45ead8acddc784d1c96ec8b35bc4ba43e8d2a4e9d3a1e4d696d3cd63d0c66dc7b05ac3b74fd2d291dcbc5ec9b55cc6bd49c1b44adac18cc5b944d1c76ac2b546cda73bc5b058d7c573dfb264cba53ac2b34cc9bd4bc4b649c1b045cba43bc3b642cca94eb8af37c3b443d0c865cdaa37cfa247cea835c0be36cca537cfae38c0b145cdac30c9a14cc8bb41cba441cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab2312ef4137474696f60457e63756365727964797e2f6277600129f4010a000ff00c200000000020002000080ef00ff90c1840b0a1c388031a2c58801040010308041030700142050b081a1460d0c1c30801142c48202082450b07103460d82012868d0a183470f011e30880122e0c802152c4c906882258a851c2658a861d1028b87142164c09133864d0b173212e0e0a2278e8d1a3278a0e0f0a62f8e1e3a2cf0021448c01c044e061970a1658e03274c88e851a1a30219002a742152b48943172f40a4419260f3478d0c267c199274670b8d0a79a451b222ea0611c481a461d25099029e0177e6ddbb977f6fdfb187071ec2b58b01ce211e1065dac5db2851b46dc2a55be5ebc6103303ccb07101a34b81a54f862d5ad4f964da1266c0992366ec8044302e3440f0d183efcbc8933b6edcc9b3b76a153b6c60b963e640e8820314244080f0a38eff8127469c39c9db1074c127cc1474d120d10d38d131c70e244084448118b0f1c40674f08e19077845348710b920874e1209e1224f050080f2c702105121c70f208050068e4df028de196420b60f1c6891d78f120df10388020480500f002451020f0504802088003002b44025207805802388204701258804044c070050246f0d38512663941c1013c214281214831206e856c1288422a8804b8cf032450700c0e342122421e30c07045032cf0180b9e44a15d56175669c88c6ff060c409061c8013450a4c51a445013c8061090c4490d6a2a054c1d8ce8d7422e8c3220142d4cd1ef39ac0f3c2185c21f38c00aed1d40d098a81194c163842780e1484d1e6c42301414343152cc0040310d20133490bbee153cb12649ac7c618528197052add04484d0e489043401d44ab140d062831534a1340c13600bcd6b1d745269c528941456cb1964d02483120b01feeb13442005ca195432298206f62299c52ca614a9060a688134c31a1f01268a107871b6802c7c02c6c12474aa6ce91b9c14c947236871054cce5c81b64c195c8c56820660e106452998b17687290d7278c7195c1df5091638c1b50b1a089cd7012974eb0a482c05e1b546db5491c6cc1a33d188012984d149c522a0b4ffc829789178891d60d18744d98032e8092f849286f046a05171e8c9298422e741279c91f80a297f1e8872e4050400b3 | ||
164 | EOL | ||
165 | $img{greenball}=<<'EOL'; | ||
166 | 749464839316020002007e0000574c95699de76afd29aa0e99ea1ea9ca1ea97afd49e9cd98f87d67d71d0696ac74e5dbc3c82d378b4e9a0c7e2beb7e0bcb6eda9b5eaa6b5e4a0b3ee92aedd8d9dd6879adf7197d8727cc35b5eb936caebb6cbeab5cae7b1c8e3bdb7eea4b4e3afa2ed99a1e694aedf899ad38499dc7e87d47685de6869c64880df68caebb9caedbdcbe2cdcde2c7cae9b7b6e7a0b3e0a1addc8a9bd4849adf7098d77a85d07483d86f6dc25856b73980d17fcce5c3dfe8c5deebcda2ed98a0e59a86df6584d96f71d2627dc25757b63471cc59deefcddee3dbb7ecad9cd7869adf7298d97b86d17684db6f73d26970db586bca485daa37e7e7e5b5e4ada3ec9aa0e793aedf8c9dd8869bd0837ec35067cc3e6ccd4657b43ba1ea9068cb3c7ecf5e72d16870d9517ec15d6ccb4669c44455b23398db7283d66d72df577fc85b6bca4569c2485cb53183d46c71de557fc65d6dc05a6bc84b53c63e9dd88da2eb9f88d57369c04b54c730acdb81aedb8784dd6168cd3b52c73b9bd48c9cd58399da747fc45f6ccf4f57ca3a50c7376ac54268cf3c55c8395db63382d7607dc0595fb63353b23e54cb3a71dc5c6ccb4151b0385eb53955c83a52c5375bb43152bf2a51c63b55bc375ca9365ab7317cc15452b33858b73354b53253b0375ab53552b5375ea93658b33854c73454b33951ba31cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab231cab2312ef4137474696f60457e63756365727964797e2f6277600129f4010a000ff00c200000000020002000080ef00ff90c1840b0a1c388031a2c58801040010308041030700142050b081a1460d0c1c30801142c48202082450b07103460d82012868d0a183470f011e30880122e0c802152c4c906882258a851c2658a861d1028b87142164c09133864d0b173212e0e0a2278e8d1a3278a0e0f0a62f8e162d2cc0f1f308401127078c30d0b247019224447ca0d0d1c88400146f802942a46903962e4e981cf0d1630b8d1540a419d1c26342d82256a059a26500b0e62750b41c4264a30c59b47de2e5dbc7928f5dc38fa461d2407b44870855b275fa065c29d39763d27ec2c56067971e2024786134b8e1d4ab4b9e3d8a53cbc7103164cc81184604c7880e1a3078791376ef6dcb993776fc2366ec8d043964d80c1150628488001e1478bff134e8c297253fa163d68b1f64a107804174f027c40f18b01181101811118b0f1c40274f0458e442cc125101fb920474d1209d1224f050080f2c702144121c70f2080504f022cd113850081e1564207640186881978e120de17705120480500f002841020f05048020051770f1844f152c68d48f1f78209600218804334c07005022800d34f035c892088041c101302142020e3c21ff5e81680238012588046885032450700c04105045cf903c1051c80614f1e6e215684775c59952c10bdf314421428e91345074451744501381a4242152cb9b8631d6c12b36e14802298804a88213705aef23850848518485023c7a378214382ae5c22d68d0c880247002a78a1d8c04d40d0a449033cc094c3bdc690ab2e153ca1e509a1446185271578327dd04084d0b4890438f0a4c9be30d062c2153491040b1f5cfaad6a197c32094422941416ca1564d0f3c2100ff0deea104420d4c9175c12c80698ae4219caa5015214891e5001c4c5c04871660b170bf114cf1868024f212078a1364527095279c71d44bcd2f71764b175c7c16820260d1c5c323989c89424998027540d14381638b1950a1a088c9700257cdb98862c05d195c4d9548186cb1637a138002488e1e8442b90b4ff8615788128881964a147c2d42322c9422d988d30972f90220a012d5b3c1a4a0222a8cde7ffd0831410100b3 | ||
167 | EOL | ||
168 | $img{blackball}=<<'EOL'; | ||
169 | 749464839316020002006c0000747474545454646464848484b4b4b4d4d4d4c4c4c4a4a4a4e4e4e4f4f4f4050505151515252525353535454545555555656565757575858585949494959595a5a5a5b5b5b5c5c5c5d5d5d5e5e5e5f5f5f5060606161616444444262626363636464646666666565656868686969696a6a6a6b6b6b6c6c6c6767676e6e6e6f6f6f6070707171717272727373737474747676767777777d6d6d6575757979797a7a7a7c7c7c7d7d7d7b7b7b7f7f7f7080808181818282828383838484848585858686868787878989898d8d8d8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff12ef4137474696f60457e63756365727964797e2f6277600129f4010a000f700c200000000020002000070ef08f72838485868788898a8b8880132b2e219c2722271d040c868f143636353431333e2b292724212118999f753a3ea9373830af2d2a272523202e1c0c8c1a3b3c3d3c3b30bf9033a92627af1b1113098c193b3e3f304f3e34c633bc25abcb181ec780163a3c3f3142414f3c3a3735313f2cd6a12f1c19161e020681373a3d304246880102d3addb3a56b699d3b0210141a0153af99347ae8d9b3872f41ed390f00001271c94a153b68d27863c8dd8ed7368f0c1a02b00386444961c68513a17c849235981a244870b04fdf141f2260d0c173278b2d10b461cba57b27970d0718244070b06280a21e26681da163e6885f40a4419a975f2345580d0618aa31efc2e5875a123b6c7a2b1fc61e211cc030bc60a0c080291a2858b87103268265c03e58b061a229924aa651b6205562258a851d2e0fb8fce8b5ca88cac05088ebc09de2040aa2489831a9750b061d266f8e25ac640f5b755f72305050e0802d042a4c908d924372f257b840a8dda1a7a405dcad3ef980126441f7d7cf8b982142644883dc12ab50a001c270f0028a0c70119d948cf9f1e340fda76edae38fdca724781461c70f10801241860e8720270b1460e79e7d612060c102490280c60c18702066820a70a064771450e0e209041040c00ff112f0460a1c6061270a0e60a103871c973dd30d6d88522b758c4011c508106091409f3e5033250214409e130602229831800a3ee80145061c49352886422963e20a0020c4a3998c00c084026a8911069e0430a4620016e83162260c30072c9766b5a527940c1030c39c800060c20a4e20a5aa9422e9104b9ba80000c106041042698e4a57ba44a29e4aa8402000b3 | ||
170 | EOL | ||
171 | $img{msg}=<<'EOL'; | ||
172 | 749464839316410041005a0000000000ffffffcfcfcf6f6f6f0f0f0fdfdfdf7f7f7faeaeae4e4e4eefefef1f1f1fbebebeededed8d8d8d8f8f8f2f2f2fcecece5e5e5efdfdfd9d9d9d2d2d2dcccccc9f9f9f3f3f3f6e6e6e0e0e0e3d3d3ddcdcdc6c6c6ccbcbcbafafafdedede7e7e7eadadad4d4d4d7c7c7cdbdbdbababab9999994f4f4feeeeee1e1e1ebdbdbdececec8c8c8cbbbbbbbfbfbf5f5f5f8e8e8e2e2e2e5d5d5dfcfcfc9e9e9ecdcdcd6d6d6d9c9c9cdddddd0d0d0dacacacffffffffffffffffffffffffffffff12ef4137474696f60457e63756365727964797e2f6277600129f4010a000f300c2000000004100410000609a0cf907834000888c4a010180c159a466350f4861b9101c080558a43050301e088e22fb903826180643ccb4c60c1f08444231a45ccfd085e201819131a1b1c1d155d7e171f102911222b132425264b462d4e172820292a222b2c252d289f4c462e2f2820313a22333c2d2d189e417106262431353633373d13b856a2762836393a3d1424bd43c4c8b0d275bf3d7cc856dec7b2d7d2c6b6dbd4b3cfdbdad553e4e7b4464becede69f31400b3 | ||
173 | EOL | ||
174 | $img{sair}=<<'EOL'; | ||
175 | 749464839316410041005a000093590253c8d163d8e12348b1f2a7a1b21781e1f4013358c1f2c7a1c22781829661420641127521e1e40103d7a1c2378192a661521641228521c194f022b531a164e071d3c04143b0545b624153b011d29024da42e04270e33a22d04270a0b150b3b912a0c150703130e29791b0d15070414040b0202328b1a2e671b0e16080514040c020b20771727651b0e15042f541026521d1c4012113a0f08280b0f160a154e061b3c03113a0f09280c0026080714000000000000000000000000000000012ef4137474696f60457e63756365727964797e2f6277600129f4010a000f300c200000000410041000060660cf90784c2a1f88c4a2796404089641c08050304587044241b06430ae87042221b247241163a275265c2712260a91d017305d0788d16a6c3f14402c4e112225432b44252625472829492a2b274c2d274e2c894f203132423334339c45363738393a3d6bad61400b3 | ||
176 | EOL | ||
177 | $img{forum}=<<'EOL'; | ||
178 | 749464839316410041003e0000ffffff000000efefef4c4c4cdfdfdf151515dbabdbffafff0000ffb70000ff0000b797b70000b7ffffffffffffffffff12ef4137474696f60457e63756365727964797e2f6277600129f4010a000f000c200000000410041000040370f9c94bad702beb55bfdc160404699582e7027a5914624979a0f0e2b0b0441e6f4d9f23c8a7739c9e1f20c1882b90042104462060303f74d3c100653c1ca54a404bbd8a7d759ce2baf5039e25a5e7fb161763b7e73cdb784490cc110a090d7e787b01890a8a887c0e8820580c060c08069c01100b3 | ||
179 | EOL | ||
180 | $img{home}=<<'EOL'; | ||
181 | 749464839316410041006c0000000000acacac989898cececededede8e8e8e4e4e4e9e9e9e0e0e0ecdcdcdeeeeee5e5e5e1e1e1e8d8d8d4d4d4daeaeae6e6e6edddddd0d0d0dbcbcbcfefefe2e2e2e9d9d9d5d5d5dcccccc8c8c8c3c3c3cbebebe7e7e7eedededadadad1d1d1d4c4c4cfbfbfbbbbbbb0f0f0f3e3e3e6d6d6ddcdcdc9c9c9c0c0c0c7b7b7bfdfdfdbdbdbd5c5c5ccbcbcb8b8b8b3b3b3b7d7d7d9b9b9b2b2b2bdbdbdb4b4b4bfafafa3d3d3d0b0b0bcacacafcfcfc7f7f7f5b5b5b1b1b1b8a8a8adadada4a4a4a9a9a9a5a5a5a0a0a0a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012ef4137474696f60457e63756365727964797e2f6277600129f4010a000f700c2000000004100410000708c08f7283848586878f7000038a8b88828001010e819e88859599839f859203089b978d9405060591a583a706080908968d9a070b0c090d0e099481bf001c0117b21319ba9002041cb51116171218191a199d941b1c151d1e171f1ec021222895c3230c1427d52f1627202822292d809305042a2b2d800c282d2e2f269985a80b203004c0915c668b0a1538f1006590068d000d0489088143e60e0585be65e000a3a141bd1c3074f058fbc14038821978f8e1f341e2b66914021410e30840112a0be9ecd9f8a7e0a0400b3 | ||
182 | EOL | ||
183 | $img{equipa}=<<'EOL'; | ||
184 | 749464839316410041002c0000000000dbabdbffafff0000ff0000b7ffffffffffffffffff12ef4137474696f60457e63756365727964797e2f6277600129f401046007000c2000000004100410000300687abcdef0d18941c9a4b1e977bb02409d10a8c5330836a2c8b0016bc1cae9c4932e6fb51fe230001168a80a068407c0801818351bc6e318e9d858a89e46b1abb67595bb2be779856862bbed24936fea8d3839b8242e5ae94413d9308ee7a709000b3 | ||
185 | EOL | ||
186 | $img{conta}=<<'EOL'; | ||
187 | 749464839316410041003e0000656565750a30867a3074893097fa20a86b20b9eb10ba5c10cbcc10dc4d00edbd00fe2e0074994074994074994074994012ef4137474696f60457e63756365727964797e2f6277600129f40104600f000c200000000410041000040a70f9c94100a83b5014ceb9d40c03474416c1808a196d961290b59bf008e50824b85ae9205f423ae8e453ca89a01b958a27a49c87697215a905c24198595f63dd67f0684a8c2c5409b0403b8ab616b743515fb4018e10c9442b50f30a7c32260c4c11881b3b5f1c6788898b7a658400855f4f10087b1f551b9911100b3 | ||
188 | EOL | ||
189 | $img{jog}=<<'EOL'; | ||
190 | 749464839316410041002c0000000000dbabdbffafff0000ff37573700003774994074994012ef4137474696f60457e63756365727964797e2f6277600129f401046007000c200000000410041000030e487abcdef032894964553bccc1cbecd70401083933196a7f50280568fd04a0d1a3ab0ba51e5fe13bc767b3d4be5abe14648c7927941ed561924216a78cdea0cd2c54b4aea77930e608b384797190000b3 | ||
191 | EOL | ||
192 | $img{bg}=<<'EOL'; | ||
193 | 749464839316410041003e0000935902651902c4290237e802243902d7d80219b81296f80268c802934902f50902a3490264390200000000000000000012ef4137474696f60457e63756365727964797e2f6277600c20000000041004100004066018c94badb83bedc17802c51a51c0400241320581385702490640211e654f15512b493ac0c0b29c0d6080e40160bc0f59c7526268665e9049e4a5e43822b089a4e04cba1e41da0101c3a8238b8901a0860820a823cf4da8f40eb31703030c0d168788898711100b3 | ||
194 | EOL | ||
195 | $img{logo}=<<'EOL'; | ||
196 | 749464839316091005007e0000ffffffffffccffff99ffff66ffff33ffff00ffccffffccccffcc99ffcc66ffcc33ffcc00ff99ffff99ccff9999ff9966ff9933ff9900ff66ffff66ccff6699ff6666ff6633ff6600ff33ffff33ccff3399ff3366ff3333ff3300ff00ffff00ccff0099ff0066ff0033ff0000ccffffccffccccff99ccff66ccff33ccff00ccccffcccccccccc99cccc66cccc33cccc00cc99ffcc99cccc9999cc9966cc9933cc9900cc66ffcc66cccc6699cc6666cc6633cc6600cc33ffcc33cccc3399cc3366cc3333cc3300cc00ffcc00cccc0099cc0066cc0033cc000099ffff99ffcc99ff9999ff6699ff3399ff0099ccff99cccc99cc9999cc6699cc3399cc009999ff9999cc9999999999669999339999009966ff9966cc9966999966669966339966009933ff9933cc9933999933669933339933009900ff9900cc99009999006699003399000066ffff66ffcc66ff9966ff6666ff3366ff0066ccff66cccc66cc9966cc6666cc3366cc006699ff6699cc6699996699666699336699006666ff6666cc6666996666666666336666006633ff6633cc6633996633666633336633006600ff6600cc66009966006666003366000033ffff33ffcc33ff9933ff6633ff3333ff0033ccff33cccc33cc9933cc6633cc3333cc003399ff3399cc3399993399663399333399003366ff3366cc3366993366663366333366003333ff3333cc3333993333663333333333003300ff3300cc33009933006633003333000000ffff00ffcc00ff9900ff6600ff3300ff0000ccff00cccc00cc9900cc6600cc3300cc000099ff0099cc0099990099660099330099000066ff0066cc0066990066660066330066000033ff0033cc0033990033660033330033000000ff0000cc000099000066000033000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff12ffb0e45445353414055423e203301000000012ef4137474696f60457e63756365727964797e2f6277600129f4010a000ff00c200000000091005000080ef0059d2318ac80e04385070e1458909022c78c012a3c884172a5c5871b126cd8a1b3a44e8f1d365409325466c0982b46ac39a2b52bc794216a9c894376adc595317adc564c4021b18f35951b283497af40a3078a05f974595055a54b72f44ab479a1d9ae4392156a85f9e6dba14dba559a165be8d6a263a2a53ba6bb2b5ea56ba6bd8b051e25dab06fee752ba7fcab59b673b20ecb281f2fd2cb77de0e3c96307362cf891fb58c395277468891166edca9b337efce93438e1d2ab439e3d6a353ae5daab53be7dea363ce9d2bb63d60d5c4befcddb478ee63a34d7f4de91c3b2fe2efb98f2d4edbd830f5e3cb93374e1d9af178e7d587677eac5bf37fedd9befb4fae8dfbb87be6e7a79f0fae1cf8fdedefcfaf7f9e9cbb74fcedebcfbf3f1f3dfcf25514a3d08e25e450ed4702182392860e2890e38e0648d0e4880a4851258c0e58a166841975a5d78655885498840d88626988228872aa892298c2eb8e26c8b2ac8d2ec8636d8832c873ae8932d8c3ef8e3609b3a09d3e09646198420933265f7954126057555585d39a0508a4d49322496562414159c5949d5669552a8d497915e5916214a529985aa936a95d62557627970989f52a957ab9772d9f59063769967ef917af9b520aa7a0a96ac958e0ab62c99821ac6e3ad8289976e9805e6e1e6801268b9a6a616680a67a1ae7a2a69a4ae9ac92aae96aa93d8855e14efa9978e5545a51da361655c1ea7beda3b6359bacaabadafbe78fb5371cafa745fa7caea3c5da8ca0b9ca3bbc20bac65b4ce4b2d25b9de6bcb27b3c67b6ca5b0ee7b4e64b1ea7b6e69bea637f01f681141784026a40218c123fe122849218802788eb284025a0224fa921f2dbcaeaae9eb405c8a7033cd0da0b283c21b9ad035c80f4caaea4752d905a145ce2318c5322f8c188515585162b51234ac2885332fbc008e697d57db69708527841f5ee6faf1b23ca4ec49d57fc997761570d9dce51371d502c28377373b6c54b4694d089a52c51de4f5d83b0683f4d4ba27cbe1d5c9dc57d6db374733f371ea8dc497774b9d15aeae13550158cf2bc05650864defa0650b2f2b5179534d956481d0ec151e4a9b965c5391b5cc03007d85188b446870e48b0e99d5ea9f1e8935e9937eb9b5e0af8e2a79e59f9e995798950837b3db2cbc7dc31b957c4050067ffca5ef80ce9be2eeea575a659a0223980de5bbb69b6c34b5cfeabc8fd2b3feb2afe7c7a82df2f5cb8b1d72f3db6f8d6feadb5f8c67f9df4f6ba1f891391ba230bbc0e717c0be2e7d0c978aede9e6cc9fcefa214528fd1fb49911deb92af928644801bb551e37c7205110b35004909001246f3d49aee35b04b0530d04d041b8e92e2bc08d10ee250190b4fd2266eb6849026697bb6927812e6b510d56b2619f9000661323f852bc052c951041ca08240a1df496ef14951490ad6efb1f8ddea1d4b6e8da6c3bb2026e9ea668167989ec688926da96c63791ad69ca8f618227ccf292c3c0313a885473151f13c5a01164a81d1bccc05c3857123dab602013721d17f0cfbb60ff85118851454248401ebd119f73b804c2c0f718486cbccf4799a2c51622d738dd53af8029a0e23650188d3ee1bf8da368062f560582942ee636b925292f496ac452a237563465211b880b3212b9c125c916d35650b7495a232000f36584e4a7301bdd8c00757aa24b2446b78899a1f7274c19dfba41650f3213650ffa54e05af6eb4b24c0401a8429d011a6c4221ce1989201c5a8c851e24b4d230a097c372dbc09079d357dcc8d71dfc51303ffef1411a13e373cfb4d72d41549990dc96261b7e892b8b517fc49a254fbbf12bc38d4921ad130974c7e1afe00dd465090449ac08fd42bc7501bbdc2e9755984a42f562802849206730911e24d3a7d0b6400e324c0918331d2501f8602eb9201004b3f4ac83ec4407d8821b4634228809b0620742f04a5eb409ac015a69989a54d7aad44aa5113a2162c78018dd2ce05d09cd51dc001d8191bf2a4659008bc4468739993540142b812340ea22b040b0b120b32c5b3591cec885207507cc37a9be72558191b2037a51f82a334420966e7050a02a14db98a8022006a0919392686bf405a72f264a632a3b9ae3a4e8389e395618689d9ce0d8a717b95a35792be34eff183f72e7dcc89354629be4a08e57323b8a14609775019fcc99a7b0a4e5df9dcc30c5322637418416789c1182cbca40dc2af5e156a92a66682b1a283c3526643b5a21a05374d6cecce8acbe642f296ecbbe55f6966941ba58674ea69e2dc0ce84a34d480621d6d390cae111359a184b376a75966e0191b592896e69587cd4a28ce56188d38d09944c8c3e1699409b8ba97d7203d3ce44a99138cf56aa04f2c09086513d0a08a38a4c90248ae40d8831bc452fb458bf6d0ece8cb18dd107e67818c9d553303d346853aac39e033423c57d880847020bbd82be06730d70fbc66abe2929369a2dec51c6ca18074ba433ba0a5ddb8a05431ad4b586eb6a24cd4efd71c9b168a1a9fccb6ee95a7ddc6e2cf92ba5911dd0384798c018d53d2cc6582b602eb4ac0ff605bcb55ebfa24c1bc8c580f5a99f36ca438922dc4f03a67eaf2390b2487b7eccf1a6b8109ef0ffd4ccb2cd90674d85a122abba37393a95c4c94ad14077e6229f995f4e26db1b98a3a103abe3c4d81689b6743865750b3650f19e5ffad712b15a37b7ea8c25a82ad2b65ad98b35fdbc2f7ca4680c4fa140628438d85dccd3ccea921a63a45ada0058810ab360058595514609e639e8c894dc461020f85564ec4f35868e5e1bf032bb1ee5d29d226b46611ea855b4a1be99a62b501af353232e8fa1b21a629263db8f8ba014ca2a99175a7ffd8e6e9628ce1ef06713be03be88a651e43e63950569fa238ea22ba28ca13203fb604b70268e36ffbce5fecc71eb09d30b14335a6e23fbadba932d8a90ebade49fdc803db2772626d5e68d8263572a49a993bad4db85b07cb40e2dbdc188aeb591550bb5a49a2e55983854021308824a38b5e5f634813239627fbccf84178a14ab824288529e47d409b274b71322e735beac799244b895138a62cf2eb5b273fe2a92d760fc4550565d9d38346f8ac4c398da457cd5584ad7de1c94a8100a1737f94c2f5978326c6b71653f14325fb50bbf1715e8b5eda973e92df2b34c146bdc97ddec9b1b77f9a3da5dcda57a27ecbe45ffc9fa90edbec3faee27ccfee25f7aa01fe0db5c3eff08f1f5be55b35b1d34d591bfde85dd1bd12ad630ea99eb53a77ea6f36a607c5a99e89f0533fce53dcbadfa366815723abc8633a95694a33445ba52c6743b14d070e28e7dc5973e075a60772b59438833181813e5d61ca50349c7257645e910b3126ba6008877651ba7818fb6c20be3f27f23d50ef3a713c15b7d55f23df6ab7af6b015e6c75d06363097c97a515372464a1c57a468a6ba35385a6d66e91ba6418593ee73c78478659a32a42766261532f54487918e5b24cd54f4763d310153b4c24021e55827025ec6223113f67cc31835b7e51c250c61257d61646f7825141568bc5707c07d11c86b61995387157c14ac1258197b58558e87af1f01df7ef444a38da3f78d978e73d31772572182725a5067c760572e7587202cf5dc3f23704df6a722d57d6ac07382c64542672775343742563c39a6ba8394522e14265514e13244d01537f76221d13992115d45e05182512682538183ed5f745214c8ea1314a31bc32752043b7d72076708a619674f5891dc5301dc47655538a6868a27925bb8511a27df3ac1d68b67ea8ce2481ea81963c5423e278e7b866503222876c3976e47e065d21927c72e2416248571b440f5807cc31e5964a57152cf77348e1544248c66796576e456d1e09f57928118d315f7a27216057461dc42b4ef5f33e071e2035180f31d76b84383438c72bb61b7fb5f23696009ad72c35b5a28defb5a078e3866314098758748393ac79d76c78d73984318587f6c39398da8878ec73e51f5d331a1d11b336d6db5f39901249be87d0da0108d05b29851035e75ed5a91dc4335822af7bb24f7172d137f75511000b31008045053a8d19a41ad54a5a72c212b88c2bc4a821e3bb8818bb3326c88288865a79cd30a7a09265607024e95a54b88a39ea2c143486017a8ba5408e12a272b40c33221a8668801ef5180556d42016436fd6891369358929c01dc4080ad89e5869499139c655f8fa2f24a390a39f5c15446d39a899a1b481a3131b13c992812b63928b9687d94d64727682163e774b35415c89640c52d7034974b99034a27f599d6741a85bf7e493c340ef9dc4481643f67353306383ee7ca0ed8851e85533488508d53af1591a447a63e38f15d5692a571f94795d59f49f3253957cb8658333c55ec2a079b6ea42491e89b58a65a69075527444e4608ac0828575183a85788c51420434a74424ba60b3706cb75342493011b79915202b03230d0e28611a175733a6a21409a476b93e72317471b1f2a1b9ca66c74043b8b55f74647db86d76d8743c66ca5243c17716c38d225b9b86323066d933417b56b7709ec68f73216732b0c35ba3de4e4a2967774431526690221000d9d127412e415a651035559dd963ab72687954d294925f7f130a7908c444896f9b53679fc8be2489497258918f66fb6b18f080b2421799ef0a4436639e489016250838186e4eb4358f5a01aa71100ba019a482a01bd632879a5c6939520294420fa53a8685cc5046193721d9a377211fb24869f9cb9f21e193329b9976dc5076cb8a133b47c84c9fa9ec9ee8b264f8c0853a607322bd6016406ca3b89b09102194ca01a44155759e48815624e7123eb4c35c73e73b856725517b5ed40413ca394335314341a20f35459a56da32c4ee49e6b34123180b152541875c681a08a448d2ab050c45c9711b53b381737810d23e7afa714c3a2d20cae68cc8095fc7f44d28ee34586d7941c73ce6ad4b34ce62305508772c583a9ba501100567ac69c6f85848572891650d37717c346c8922723ff2550944bc0bef1bde6f40650c20723823d22201de6923c73923ac4111901f40fe4880af2523358b9632b523050f59319ba5d78609eaa1899aaaf4398d04ea9dfa211005d72aaa3b80d21881179a15d7aa58b983a3159952895ba7c816acf11244214199669fafb66b64196090b273a316229739f5b5182835793935f4275c36fc2b49b6af572c7d29ba6593a7ae051a1c5bbf9148c38264628279db9174698f97cd2cfa1c5eb90e5e05fd78065faf48346d28a87607bc02c9be237b435e961a7d6bbb7c556d8236a0b2e91535d9397ef97088a3ff1df945be57fb360b80b9f82f3a09c975abb0bd475521c6ab9486a5545be6ae54595c45ee85c55897754f437969bdf4c8ef45393f38e7cf6376fd8c9b4493d7fbae5b024df672bbf6cb3804a8808bf58787b9378b7c7317c69f3a493539f48be9353f076fa2152c855b0c3a43a072c7019daaae9053e19466e9370c5499c8ad7e6a949d07d2ad91962ff3ab2bb3ca1a6a9fa163273e8837489737b451ddb466884117531e1ab497ca331e087d30070e531ad6249854a6980d70621c87a54220d3c53fa983c6336837d10842cb064127fd2f02128fd5265444b386265c9395ffac15f7b81c8f4ad7e083f8757933ee90c34e1bfaaeba95f717ca85774816b5764ebc2c1cbb4a6a60587cbe65307e82df995ceba9648f6e433161a3d89fd3c4400a345e53976009d5c7b6e116363e5b64ef0076bb9dab2ab81df133aa183cbe683bb85321805bd8137b114ef8f7b0b99f806c70c65870abb6fb387b88832cf874d206c3916b6758a6616cbbab4be8762cdb95911570171acd6cf22a494b96f855c91b6cb42c88b055087a2cd866a32c8e63cfbf7b563da7e190a15497f929561243a90bb76a18acb77541ccb616648ce7874c93c0eb31a4e65a09c6b7008075062308a579a381026acb0cf08ee949b0b94790f9ecc599cd13d29973b9ff956ce4c2c5bf8acbdf75fa5ba49146387930b3363a4b95836aebc6a75cf5412cd429721eadbc7016c6ca004b4f2d50b70823823ce3009e3ac326c9ea496c3acaeb80c3dcfebf77f7c4ac2e1389779e9b3eb9ef0b3396c75bb02d8a127c18b9c9fa42ebb5c56b0e234b6e24a5a9b117b1c971180da0e0d9174f2080523823050b2bba9e1cf0796bd72dc7d7b73285bee9bd336c795c0565cd49daaf8b368a97689d09f2de63f09bf83db207405ccc988de32cbe2de6cafcd4bc72d81e39ec9533ee7da3fc89917dae0d1802034f2650d50823ce60133aa95cc54d89aaa705ffb9ccc6c718c2ddf6c59f91d4543daf936cbc9c9ce2cb7b819b2112116ba9b57d5f5907514907d6abc3a661c8f8728bc69b0c5712231d06d0e0d7c64f231d51d1d408d997bb25a1c8b74a3f507da5c582f09114b79a9cdbcbd34c9ec9b9cb7b8fabc879b0244c375bfd514ac32dab91c7fb75ef7315836fbbf57c3a709b2dd1cfeb80565825bc01e733b06d004dca040314bc5054d650f40f7db20100fcabb9417c89f3cf7b45709d8e360c7fdc113ba5d926bc91afc1d877af9891cc555ccb399e5abcb72e452bc64a6a141c16c29788c1b686335bab57bd9b833763c7aa7d01d02b0dadcdcd50a7064d13008d520600f6cabc6cc80496bdb887cf9de6cc0ddd2b82177ac3c8590a2ecd6c339d2e5f8cbb811fd8088389d0900c5f7ee3566c2efeb34c32de1a5185bb9fdf3c2bc67a68361aa74a74f0d5a0503edcc5041db20f40013600520039afdbfcbdb454d9c76d7a39d647a45c69d8f8d4ec4dd7bb47cab7acec295db3cefd0a1d5cde3cf94bae9cef907ef628b2dc9db897bf938213299dbaaeac753d77b29e1efe49eda2308d700eea88726c88b92ef2e65814c60e83d92c98b37ed4d43213ed0217ca0c8a63ec3f97dbe6a366d07dcbfa586efcb81e298d4469e4cba3d7dd12719dafc6988917d5da00d087d14ba70d7d823b2b51b01334484bccd4527f416306d50cbc9a827ae064ec931af8b8fd0653e7b9800684ea7e90937c47d9f969eafad0bf4bae457ec0bdde9e39f65c5879d0c89b8936488845d994126d294d1e6c6ba0a7dddcfdc623c2008d600e742fac2d27e28b50852de0e5a41fcc84cebf47ab58c200923a66c488b4654e827abaa63cfd6665bc06529b27e1ab15628bbacc729f5507e19cef89fb6d52f2e5c0f233b00d04ed4e9d8ec5012e823b5e013100f9ad6249b54488867267a10d01ce61f3e48bb6e81826c38714e8eb1fdfc128ed0444f68748c7221b116cfce50ea3af9e3170bb67cebb018eac9e9f9b0f5a54bae1770b3c2fdadb171162ce51d08d5b869ee4dc7caf6c2a76d3cc20fdb6032cdb65df21073d8998dd3a42ddaa35d457191f3987c1092ac9dd2fe8085a82ba02f53a7ebe6d62a47f1d76fad410b30d03b06c63f29c6180a70bfef40230efefd42dd5bc5a804a30e8bcfe5c559b3efb0cbae1deb86c90c26d9631e1298f8df7ecac89d61faebafcc6d68d2173ba9fb1bb3c9bc9c1d94b88fddbbb6248294dadca0503d509ed74efd09e55ae1dd4e0cd3c67958e945b00dfabc188deceee2d4ecffc0926af5eb2bb0cf4cb19947630c55ce8c64ff5f5a5a3d46bf6f90442f9dc643b3d058776cc3f233edcad6c600334d750001c5ca85191f485ca851a22082b564ca123478ac4951388bc81a44a8617265cb8b192674b812f2a6419915229456e055e840911732a419a2d2a9cc8e216264e81132ec40971f3a84f90138a54d9f0d42b4292319e8c2ab395e350a62156f4e922dae2dd8c1f52352a04b467cf8251be5d69f0b1295d8413c6a4fac6dded48a24fadc5abcacead514184f60a1830ba0244852491497a263d285aab5976dccaa6b1f9ca8a41523e3b833464c5bd6d624ea955796cefc9c24ba26ee962d9ed47cf27332eea17b866dac4177ac42d6af0fc6e9aa9cad67bc2b63764a4c632de1dc1d07e4fcf958b3eba9bb33e469ca8ee53653bee60a34a75f471d33095cf54800658231c59f2f0ffa793738efc17fbab77ade5d7263b7a947afb8b2b3b356e097a6afdc872cdcf3aae7b3caba10b931e0eaffcfb3d89a4c8b25c69aefad23b45b1b02b6f03cb96eb7e8247be8b1a0d32f6abb60a9bb859db4faeb850b200b512086be726986c3ac9b6944b50704a94438d03c4d25bafeca5038b2da7b6dad26d2fb1d61342d14898fb7c48c321d27a84b707f3f0d7462fda8c40c60784bfebc90b345c8834f20430b84b0d52a139af2d5a235999ef56ea864694130135854eecfa380123065021c320e6dbf152390b9bc13cc0a4b24b4e3207d2cd8d4e86e3223936090cfae343fe4a225ebd1d3bbf69c82b238ae145fe1cf159bb49252553cbda83b190c6f6d27f8da5ec743f64564db2d9650ab2a1aeeeace6faebca00fa488138b3fc2d903236d245445bcc5515ac805d1d4d3e41d42375d5b055ac1317d3d1beacd5b8b42965dc4b53e434ac633df225bc47b0116d1ae5b6d4bcb5b9de298ce7b031a6bd64b1c53b53c65429e661b6ee244a49cb209deafa284604845830aeda27ed8d4edc47ebe9c7bac20cdaa258217294b5b8f8bd055d56974ccc21cd7b255aee3e57f545315d4925e6b04e731bb9b6ef43953624d0615b9cc936590f9333176035919e68dbe65c36f900ca4891d15b9e35475735ae7cd8d3be0bb60b93c89fa2d73330a9edf906eb5bbc79d8269f1d3511c477d29da9d403edbb375ad6443a5c2bbfb5b29e329f153a72cbbbc5c17860e6929e2fc554f2e26f098f9881012bc05ddca7435d24971ad8ac3572f64fa57ec69ed15f3eba0f52c97b1abfee4b3e6491bdbf25c556755d372a3e684392dddb6b71e6245aa28172c2fb6d418f437c654bbcda89b040a665e1661702910a0484941ed9d9b1bd023974eb147bd1480317fc792a91cccd983f6b9ffd3f5231ded9dccd2d6713355bf3d79974c7c20624ddcbd1dbc07e52645bde04b3a9d568ef096af3325b5c41ca868de5001758ee02b850deae419ccb7133011d8e84fc1115ef8559baad110977172af127e97f695947ece500b4c1f60e67129ddab4571126791c406febd0dfd4477a3df9ef8473fb22d7fcd7c912d4954e41885505f001d58715101c65d2a5d37488043d75beae5d6a3018fc843e25b5266d6ffa0d9482e23e2bdd01bf592b0a0cee5353bb718e4460aa6a1bbe57ef3f0afee583049b1ef0187da7354ba556a2c26592b66593ed4be8694cd95f48d81a3f75029d3a4300ea7e5326150ecb4a454b612ffeb69b3f91edea65f1306da208dbbd0afbe24d0c76dcfe57b9241ab178470be12888e583c194ab636cc227d11507e5af22ea8bac62a47bcdc6290cce5da03e25691edcbe82a64fcdd804971a79da0fa629c44df6ef766adf08ea698f331e69e13bac0d04a807abb61a4b0e73d45168c2a4264d8949ca925aef42177873422af8af304b4366ea041fb195a09f7fea625111465d238e11f037d25f5ddcb8cbc74682944064501ace7794b32198466832a8e7334933b8dd39ce7de44c091d48974f2e6dcd9c1a6a4994b681c31e139f8005ea13de683733dde6e4786bc4eae2437f31a1cded610550ef1907fb9e8283b2ac52de50d2b5d490f9ab6568cb080000129f4010a000ff00c2e0000000281005000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b7efc0a34b8e1d4ab4b9e3d8a35bae5dcab5bbe7d0b36bce9d4bb6bdebd8b37beeddcbb7bfefd0c38b0788ca401ba048cda402b26568fc6650d7512f4ebc997377edadad538e0d50d47becc75ef859518d55f5b65cdf8b4ffe1e7cfa02f5ed4f5b9f9ef8357be2efdfbf8f4a7ef53b68e517ba8777f587558e70f1f70adc7dacf79ed479c957c28e700428a0676efd67f0ad7ac957550b070eb751e58e95684f1770165765c78af9a01000042276626d718ca7d12e7af500a2c881366662a68cd118180027508780eb8036f889dc8a1a02be502750028f9b7b2ce8b2429a4a56f36d724249ded19000699525633a5382ad8252e822ee826e8929df8102b2302480e159226b9e6246566776f14944237c2a88f2aa09729933e384720a45aa07560058e46916b2002a8c1aa8026e865e3a09af72922ace9a9b2cb8a9e6a3fd4a0d148f768779e59c8e8a4a20905822279a60afe93aeaeb9ff57a7ae471528712e5961edaf89f7c524854a51c28d92c299ca4c953aca654a94be2b599381d9097ca2a1c25b291f98ae1b0227ba99c9d5a572ee9b8e6abaeeabce6bbb650400129f4010a000ff00c2d1000000371005000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b7efc0a34b8e1d4ab4b9e3d8a35bae5dcab5bbe7d0b36bce9d4bb6bdebd8b37beeddcbb7bfe99ca401ba044cda402b265e73a665cc7511f2e7c197275e2adad536ecc50d379e8c75859514df3eff5b658d78b3fdeddfbfa00f1e73f5b7f5e783479eed7dfaf6f99fdf53b64e38fa2de3f577558d7ce1e759db7dace75ed375c947c28d70041860a46afd57b0ac76c947550b030ea711e48395580f167c064765c686f9a01000002646226c718c97912d76f500a2c78d2a3622a588d108180027507740ea8c26e8d8db861a027e502750024f9a7b2cd8b241964e26b36c7e32399ed090005955626f2a5342ac8e42d8e1ed8e5e7978de8df1b2ff138cd149e16a9a6616166672f1390422782a78b2aa057289f2e28072f905aa03560018226516b2cf19881a98c16d825e2ac8ae7e821a8e999b2ca869e5afed3acc138b767739e4988e7a0a2f8422175a6f9b4be92aaaea9bf56a3ae37d4277d1e4921eca489e78523814a51c28c9eb289ca4b913aba654990be1ba8928dc9f83ca1adb24b781e94ae0bc126bf89b995a47ede8b4e69b6ee9b8e6ab0450400129f4010a000ff00c2c2000000461005000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b7efc0a34b8e1d4ab4b9e3d8a35bae5dcab5bbe7d0b36bce9d4bb6bdebd8b37be63aca401ba040cda402b26567776658c7510f0e3c987173e79dad534e8c50d277e4c75859510d92f5b654df7efb2fbe9d7bfa0eedd12f5b5f1ef73377eadfcf9f4fe87df53b60eb7fa2befe3b7519f8e1d7a8da7dacd71ed271c937c28c70040820e166fd4770ab72c937550b0ffd97d0e3888548ce1578063765c582f9a010000c1a16e16b718c87512c72f500a2c6892e06e1a484d1f7180027506700e98826d828da821a023e502750020f997b2cc8b240924206736b7a32295edf80004915af5b2a5302ab8a42c8a1ec8a5e69c7dd89f1b2bf1288d139a169966ae5d5657ee129c321742a6872aa017279b2e18c62e9c4aa0f4600d76f5116b28f18841a88816c8e4e1a88ad7a820a4e989b2c9829e4abed2a8c12877667f8e3948e6ac92e8022071a6e97e91a6ae99647f55af9e279426791e39e0eba979d745228d3a51c28b9ab279ca4a9d2aaa65489cae0bf79189c9e8fba0a9b23bc71d90aefa8125b489a955a37ade7b0e68b2ee8b4e69b5150400129f4010a000ff00c2b3000000551005000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b7efc0a34b8e1d4ab4b9e3d8a35bae5dcab5bbe7d0b36bce9d4bb6bde4aca401ba04cbda402b265e6b46654c751feedfb187071ec8dad532e4c50d175e0c7585951cc31f5b650d77b1f9e5dfaeffa0ce9db0f5b3fdd773275e6d7cf8f2f38fcf53b6cd37fa29ebeba7517f4e1effd3fdacc7ddd17db927c28b7004f7ef1f52fd3730aa7eb927550b0bfd8790e28d75388e1474062765c48ee9a01000081ee5a16a718c77112b7ee500a2c58522e5a1a380d1e71800275057cfd88426c877d98e0a02fd50275002ce987b2cb8b24f8e36d5336a7632191ede800039d4ec572a53c1aa8642b861eb865e5917dc85f1b27f1184d1296168926eb595647ae1198320702a5832aa0d626972e08862d984aa0b460097ac5d06b24f17801a78416b8a4e0a48ac7682f90e979b2c88e8e3a7ed1a4c11837657b8e2908e5a892d8c12f6d96d93e90a2ae893f54ab9e17045425751e29a0eaae69c70521893a51c28a96b269ca49992a9a654798aefa479085c9d8bbaf95b22b171c9c9eea4124b9799915a276de6bcd67bede7b0eaf810100129f4010a000ff00c294000000741005000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b7efc0a34b8e1d4ab4b9e3d8a35bae5dcab5bbe7d0b36bce6bca401ba048bda402b26566326650c751eecdbb977f6fd28dad530e0c50d073ecb75859518cffe5b65ccf6b0f7e1d7afa0ae5d7fefe5b1f9df63173e2dfbf7f0f977cf53b68db6fa27e7e3a7515f0e9d7dd1fdaed76f1e9b917c28a7004e7af9c5eed27ff997ab917550b07fd7750e18375284e1370061765c38ae9a010000416c56169718c67d02a7ae500a2c4812ab561a28cc1d718002750478fd78026b8d6d88a0a02bd502750028e977b2ca8b24e8a3ea5f269723209dddd800029946a532a5381a98242a821ea825e4976db81f1b23f1080d11921679e5695556376e109432f6c1a48f1aa09625932ef7462c944aa074600572a5906b20f168c0a68016a864ef908ab7282e9cd969b2c78a8e2a3ed0a0c108f664778e19c7e4a492c8812e6996c9fd9f9e9e79fe53a79e071424711e19b360e9a469b7c420853a51c28992b259ca48952a8a654694aeeaa69f71c9c87bae91b21b761b989eda0123bf6989d4a172de5b8d66bade6bcd26610100129f4010a000ff00c245000000c31005000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b7efc0a34b8e1d4ab4b9e3d8a35bae5dcab5bbe7d56959026518a6b590465ca0c60ccaa7faaad6b177e6ddbb5fa5bb6dbb7b020e3c37fa0b2b2a8fddb6da293defdccd934f511d5afcdb60edaef3de0e3cf9377eeed3e28fb66daabce55bc9cb3fa27ebb7af6b0eb51b7be0cd6f07617e1006fdd7a6da78c1f73edd63c551c20d7cd90840ea5606879c5f72c951c0e97a24000044896d482e5028d9285ed97108a001a7866d48706271f50208c51dc5d7c1678a269502e182806718c5108497bdda082ea063ed8361b82edb8d3a674320054a19161886d45832ef852e3882e3905e75c2ab7ca0c7df53714e38a5e69d5949acd87d36c89b568f0278a289915288cf589d6609a2019108c906918da4b7516287163862e09c76f9bedf95766775ea0c1e1a88287086f6df1b9ec11a446e90964ad26585b95ae6277b7e6ac52b7a825a0c9f8dc93844e084a27573be529df9c8650b036eba152b2e5a88f9a516568a8ba85bf9f6f22da77aba1ce759665a4b6389ce95f5a293cd3b4d65b6de5b8d66b6750400129f4010a000ff00c246000000c21005000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b7efc0a34b8e1d4ab4b9e3d8a35bae5db095902651826b590465ca0b6abca27faa8d2b967d6bd7bdda5bb69b37b02edfbb6fa0b2b228fadb6daa83cedd8c5933f51dcd9f9db6cd5a3ceedfb79ef367ceadbc27fb66d2abbe557c1cb2fa23e3b79f0bcdb51a79ecb56ff6613e108cf9fe5d974c1e7fddc6fb551c20c78d9f700e75206775c5e7eb95180e87a240000438d5d38ed5024d9181ed87108a0c0a68a5d3830617de50208c519c5c78166862665c1e082805718c51084877dda042ea023ec8751a8edda893a570320014a09551786d448f1ee812e2842e29c4e4582aa7ca0b79f527d3e2865e59159396cd77936b85b558b0268a2889d42788f579966f8a2009108b945908da4a7116183162822ef8876e97ede91765735ea081e0a48277c76e69f1a9ac10a046d9c863a926481b94aa626777e5a852a76824acb9e89c92804ef70a2457e5199f9b823650b0f5eaad42b2a5a78b9a512567a4ba557f9e6b22ca37aaadbe455664a0b6285ce65b5a19fbd2b0d64b2de4b4d65b2450400129f4010a000ff00c267000000a11005000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b7efc0a34b8e1d4ab433665288550a5d6520951b26a1d2ba9dba653b67dfa167c61b6deadce9d28c67ee7db2caca8ddf5fa5bafdaab6b072e6c75c174eb5fa9576eaaf67ee2e2d5a35fca6dfaef95b5e8a75507de4cba47f9efdbaa5f652e99bd66d9b9547700cebdb4d0feb5e76f6d9b551c28a72d1e7afd45cfd57fbdc78b95120677a240000c18155288d502ec108bd577108a060258e4528dfdf67e50208c513cda721e4802635616f72883718c5108c671dda0e1ea0c26b8b49888d59833247a2200b32f8949586dc28916d8b1618e161964e1522297ca8973fd077361805649541290c56733e98fad3850a48a207974a582fd5936ed8a28e8100a9841f7dac87b0ef7d0e08c16e827ec91e5d9b6e37d4ea0216f9e7a5767ec63f9894c9e9a3eb968e1a32e28ba13a46a471764a25a8708a2a6b1d83c118a36e7a92151edf83f1a8650b09569a742b2b24526859a51c4e5aeaa251f1d652aaad629a7be15f5e2aaae08fbe35552099b51bace2bcc63bece3b21504000129f4010a000ff00c2880000008010f4000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc8933b6edcc9b3b760cca8550a1d18ca496b2f9bb686652844396b20b167a6ca7d653ba55faf4b59a2c2654599d45fa95badca759022dab16fa85e0c3ae5bb6dac6bbe0408ea4c6fddb9973f6afcf9b53bd8c57ef3b8a2bcbcf676add9554f0d18c5f59ae7d3b308517e5967f7e2d9430a4e4ebcfcfaf845776d4b2fd5177cd86650020bd87efda00000864dd78f1873ad512e9515e938ff14834948ca0172a1e680a57bb567b2400a2000f0278249480268670ee7a02c6dfd98a2400b22b80497850a02222281b16881ea073aa8a3605e2ea70322714668a286874ee8dd1180e988fe198816f782a1915af4e2618ce9e714a98822e8d5a797f9a7ba50270a581b1f691aa84fd99c39b82d9886adb934af7932d9a35a9062b9fa198c0e2727af9d3948a4ed68cdc8c2ce9e0ec988ee49e5f8d826907af73962a9e9d6702094366829e6af7218a4ef8976c76e19ac9289ca13932f6eaaca6f4a62b787a8707eca14158fadb9ab2152a9b7332a6fb61b6ce1b8c62b0060400129f4010a000ff00c2b90000005f00f4000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e5cc8b1b3e7c0932b4e9c49b2b5ebc89b23b26518a3702b2f9da4668ab995902ece9da8a65d3a79e5b2dca655ae0d65aa0b85155a5f1db66de5b9e5528c33d65db2a8be62a7dea5b28d8a3010ab2ba17fd63e7c1862f4e6d06b07adc2aa41ffe5df7efe5765bc737024d75e974f9e006548fe97d39337fc0868b7ffedefdfecbe6da556ffd1c57665002aa5778fda0008e7935c72f967d9d51cd951fd1289f92863138ca8f6c99c6202475bd47b2400a200090a5853138a1e66106d740aa67f588a240052a9833168ff902c1a08ba94821ea013298432d482697a2a07b3e48a2058146d87d9f7ad1789e97821ed722209b46c482ef76e1d7b328822ac8752691f1975a50210248ba9d631298ee589f21a8cc1780a5a9d32e733ab9d2d89a5a999a97860617c62e903138446c62c5b8c24d9806b928ab43edd878a49a62e7d8e0a3e1c610ae8e2e48c865a97af7446e837ea70e97a69a696a9199669a6a2c446a97c127277a66ba439389a5a94bed4c91a7d2a869befa0c60b2ce0bc6504000129f4010a000ff00c2fa0000001e00a4000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb873faeddbc7bfafdfb0830b0e1c48b0b1e3c8831b2e2bca401ba0409da402b26561b2565897514e8c3992756bc44dad53cc8950d66fc4975859510a38e5b654af1b6e3d9a75fa06ddab7e5bdd1bf1376fcaaf6fdecdb377f53b60bb1fa23dfb357511e8b98fdcdddae87cedc19d33b01e002ab47a96c74eff57fd29d375161fcf677ffe533c3f62d8db3b593f2c5540000ce76abfed18667970e2c500a2ca79f1c4ee9874a13718002750a60ddd78f518f2de72e9023b502750020c9d6b2c08b2448216b4706f6a02685bd380008812ea4bf9530f9f7a1208aed08a2ea892d189c1b2bc1678a178ae5d863e94d2696eb168c02564f9a77f9a0142b8bfd57c3229c1aa0f1600d4aa41e5b28c1c74e9c78e508e1e5985a17a52494b9c8b2cd726e89bbd6989167746a6f5e7845ea9c62280f146176297b95967ed87c599f6e66912a69ed78eddf96291742267d0a51c28f8a82b8ca4e8df9e9654c8c7e4ac295799928f8a499827a9211907e3a8e19a139e852a76aaeba800b6ca2becad5504000129f4010a000ff00c2fb0000001d0024000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4d9a45baa5dba853ba6ddac5bba7dfa063ca8d1b46bca9d3b863daad5bc6bdabd7b073eacd9b47beaddbb87192b214ca209f5b218ca859cbc49591e55e7ff6061c3890b15b67dc0b16149891b0e51656583e1a7da594eeb88b2f5eccb243f6ef97d25f7eeba89136e2d5af47fc4d7dca97edbba827bebc5506b969d93357baadf931ff56cc206308fd0cd62de8c5c953066c55854fe2dbcb9fdc7eaa52b1f5c65aafe3c651100086fa9cd7570a0d3dd53ce00a22bf9799cd1ab46dd1800d51bcebbcb9f9f135a70d9021a50275002ea196b24c7b2cf700eb45fda68f9183a5f700838f06b49e953ed1b780ab78d5c781668b25d77b1b29b917699288dd88426a4b1e46ca918af9062e1675e9a0f2a689e517a2ad8a0aa0d0600b32b4fc5b26b9772d1876ddb7c0619642d684af82a188b2497056499a5296891753e56d463824669a5ad7ed9f5f5ed85a119466985bd49d562670a567d538cc5b9821d621a17bf951c20b887a68cac98be1a965c78a660ae2117781e7d720977a2ab29c8e56f96d94a331a8312368967ae9e7a0a68a9750400129f4010a000ff00c28c0000008c0003000080ef00ff90c1840b0a1c388031a2c58c0b1a3c780132a4c9841b2a5cb88133a6cd8c1b3a7cf80234a8c1942b4a9c398235aac59c2b5abc790336acc9943b6adcb98337aecd9c3b7afcf90438a0d1a44b8a1d3a8439a2d5ac4b9a3d7a053aa4578ca401ba0485da402b2656aa7da8ca2cea2ca957b27deaf53d234b67d2c6851446fc27d5165658adbb60fa5b27b757c6cd9b57758d5cb87fa916eb75bce95ab28503165b68fa95bdb55751c55c37ba43e1cf87aa1e65299f29dca769543600c9b334d8cd654726da76ba0b0dc2815bae8acaf0bbd1d66da8ce6ca220008bdf43732e04e716f2e6c10458d62ec4377b67b793010ab22773b0f1e0d79a1f6d28cf6c60ab2086170e51ec7507fee945a32eae3e10b6700be9df153e6d6772f2fbcb6b3faf6f5152d156ca8563a9c57e5d600608341e7f65263ed57c5df65b907a20387f9172ad1831e97a28a710068641b6dac46bbdb6dbdc6cc5a722e8819598b1ef5dfda02c5b8e2a16626853a948379a8aed7863ed83dde6851f841a061260920a4603ae846197271d6ae5a6a4a0519db73a167650b0906597f1b24022754a51cfd19e52251a9855d969d125976615f0ee8a5ec6f6635502c7765d9a7ee9c76f9e7ef9086c410100129f4010a000ff00c29c0000007c00d1000080ef00ff90c184070e5365809590a5518a1a5978f0758595150b2a5cb88133a6cd8c1b3a7cf80234a8c387011ea214d0d124ca2b2a5a8c790336acc994376e5bb9909550249e0fac346121b525ca944b8a1d3a8490ed4c99335602040172a057994baa5dba85592ec29a39163cb205f12bc69006866d3b863d68c5ac4312f4b218022b09a46dcaadbb873f2b5656d01e247a15ba00dab002fa1e3c959dedc65e6dbe751b47750082b88b2b562aa89f62c39d01018df936754005139f2b9e3db633bf5d9e03eef4ab10447164d4bb6f546bdaca13639c33eab61c2494796bd4c98b2eb6d7dfa3e8a652439d9d5c3af9eccbb9517e491575c0600a2200479e0e11e9f1f4ea0db2cd0c2474f0f0fce5fe25ddd4b7f76b2c2c93081dde3ffdd1f93dba766e1c946108e7402a5b45e65dde492585311c6cd51801265aa927f5502e35383515611e6894d25a91f6d9951c0e452917862e158bda6e49b60119872eb889d144ed5706d5814905036e8435b55e1060a1e8a3609135e6905026e1b83110524e29135e4db1295503925639e497616d4985669a5e69c5679e5e7906a4910100129f4010a000ff00c2fe0000007900f0000080ef00ff90c1840b0a1c388031a2c58c0b1a3c7801b1e53187d6264cb8813361c985153a2ce8a1b2a541941d2a7c398211a9c49a2f428cf7f2f2ea4692391ec469b2f664c791390a9429e3f6e8438325720dd84173ae45a70f763d189336ec41a057aefc2a559966dda523b20de9253a27d48065ce8d0be3166058aa5bbab5e9569b6f48954da215cab6dde7c6bb57e2cdcb089fef5ab365fe0ecb745f6f5ba877f60e29c1582844bc7bde0e3c27fae749c779ee255cd2baa15193a5179e5ca9fd6a60c89b37562c98d5b368cd4947d63d7b903be4dda57bfe9bf8d7b750e58f960729e7727ecbd9c33b16ecfc73bce5c2d71ad5dadcd437e2bba59717cc4c58b2386dd1e5cb1ffed8d97165e15bb7dd1fda987c6ee9655e7efef8dc64f5ebefdf87497f564102d4402a410100129f4010a000ff00c2fe0000007900f0000080ef00ff90c1840b0a1c388031a2c58c0b1a3c7801b1e53187d6264cb8813361c985153a2ce8a1b2a541941d2a7c398211a9c49a2f428cf7f2f2ea4692391ec469b2f664c791390a9429e3f6e8438325720dd84173ae45a70f763d189336ec41a057aefc2a559966dda523b20de9253a27d48065ce8d0be3166058aa5bbab5e9569b6f48954da215cab6dde7c6bb57e2cdcb089fef5ab365fe0ecb745f6f5ba877f60e29c1582844bc7bde0e3c27fae749c779ee255cd2baa15193a5179e5ca9fd6a60c89b37562c98d5b368cd4947d63d7b903be4dda57bfe9bf8d7b750e58f960729e7727ecbd9c33b16ecfc73bce5c2d71ad5dadcd437e2bba59717cc4c58b2386dd1e5cb1ffed8d97165e15bb7dd1fda987c6ee9655e7efef8dc64f5ebefdf87497f564102d4402a410100129f4010a000ff00c2fe0000007900f0000080ef00ff90c1840b0a1c388031a2c58c0b1a3c7801b1e53187d6264cb8813361c985153a2ce8a1b2a541941d2a7c398211a9c49a2f428cf7f2f2ea4692391ec469b2f664c791390a9429e3f6e8438325720dd84173ae45a70f763d189336ec41a057aefc2a559966dda523b20de9253a27d48065ce8d0be3166058aa5bbab5e9569b6f48954da215cab6dde7c6bb57e2cdcb089fef5ab365fe0ecb745f6f5ba877f60e29c1582844bc7bde0e3c27fae749c779ee255cd2baa15193a5179e5ca9fd6a60c89b37562c98d5b368cd4947d63d7b903be4dda57bfe9bf8d7b750e58f960729e7727ecbd9c33b16ecfc73bce5c2d71ad5dadcd437e2bba59717cc4c58b2386dd1e5cb1ffed8d97165e15bb7dd1fda987c6ee9655e7efef8dc64f5ebefdf87497f564102d4402a410100129f4010a000ff00c2fe0000007900f0000080ef00ff90c1840b0a1c388031a2c58c0b1a3c7801b1e53187d6264cb8813361c985153a2ce8a1b2a541941d2a7c398211a9c49a2f428cf7f2f2ea4692391ec469b2f664c791390a9429e3f6e8438325720dd84173ae45a70f763d189336ec41a057aefc2a559966dda523b20de9253a27d48065ce8d0be3166058aa5bbab5e9569b6f48954da215cab6dde7c6bb57e2cdcb089fef5ab365fe0ecb745f6f5ba877f60e29c1582844bc7bde0e3c27fae749c779ee255cd2baa15193a5179e5ca9fd6a60c89b37562c98d5b368cd4947d63d7b903be4dda57bfe9bf8d7b750e58f960729e7727ecbd9c33b16ecfc73bce5c2d71ad5dadcd437e2bba59717cc4c58b2386dd1e5cb1ffed8d97165e15bb7dd1fda987c6ee9655e7efef8dc64f5ebefdf87497f564102d4402a410100129f4010a000ff00c2000000009100f4000080ef0059d2318ac80e04385070e1458209853c184c6061b283179934b8017122468c17363456317264c1902b4e84b8525322c59c095a44285135e7c79813125c4871566d43872d3e2c886315a6c9892d121d7913516ec69a4b369c3aac846540a913a235aae379e349903f622c8940fb60df813b7e4df9433ca3d1aa6172dcb87218edc0936d7605d8a4f9aed2a86576b569c5f069568765eaedebb399a042c521031d3b50bd26c8bb6142dda987dd6f4b9167070ebb04d3b6c0db552775ccf712f66e84a1cea59a361f256bbf8b47b5aa0710b54cd97b3e461ae6732c6bbc9546661a07b7b0f4beb39396598c18ffd7b595163d6cc655b0e6b471aa7c26551afc6f53e68b324d4aabd423e695b313fcf9e7957de3da61829ccc061231f4c27faf5eef73d5785946d3555e451640e676f926ce5c6fddc400a677f97402108ab1c6eadc6af138bf5d720e1427d45c7508fed767c536eadc5b591757d57eb9d4589b7b0a1508d7585537539761c1e66a1a6bc8c652e485a146eeda71c566fc5e479508a5178416e5226d44a16773a38f2a47132d84e1758ed396713435266cb955505592621400207395f826d67d6e28655a9545a72b147469e5b128493a79fe59703e1907ea447d09f0619f4627cd504000129f4010a000ff00c2000000003400f4000080ef0059d2318ac80e04385070e1458909022c78c012a3c884179113184c60664565ca0674b88153e0ce8c11368456b194e7cb8615469c2902b56346843116dcb963372ecd9f0b3af449d2f2efcc844b46742a02786053a04b8a257a03b1a4c5831ba25dba333be45daa091e7c8af53c2141b327ca9d2b863aac49942f5abc8ab136abdd807512bc9b70fb6c50a313eee5cab530354baa5fbe95f876736a4eba2d4ea489c2b8acc5cb834ef59a8597a66d9c973794abf338e2d5aa4f37954ac8b96c49c0ad6e5caa48507ce1c0832aed4b569ce2e4bb21de2eed06f4e7da993dca442923563063c6bd1f94ab9c727957d94d4a476d97d4316ca5c61e56a9243befe6e1fbb32b8e2872ba7360f67992a66a097b217a94b5c347eb5bfef5d0f5d1aa474cb61a6da134e7dd4fb5a7d9166361557f9e4b71371edc6d0556c6956709a5095e6259161a5262c168806d77a1e466dd693d77a0ea6ed957a85661e15872ab4dedf41add5e552832567c91276e14479d67addc8d4545a65464d5f57e9571cd86409e75cd23675d474537ccd16c325560d3891208d065840ec730a8788d0790579729340c16946ee644e36b653994649871199ddb97e1d682688331a6995160b9c586e8956a84fed49766b7ff596526198b109d7ac947e39805136622707e69d26c7d85e4db587e62d59897723a893e93727dc735199d8ac9352b6c263aef95a290c107889b5aa1f529298572a81d175791994ddd5f85ba77e0af2eeaae50ab42c8789ea1a29ac99c6481dae299808a8af160999e69d926867e0a2be696b217aaed52fdb46921b262e8c71b9be1790f5f969ed8a22b8f16d72157620e9ae7de81d26bbe12530a0b902f8076489d145966ea78ada8ea295aaaa1b5ba1f10a46a4c956db3c60acb108ce67579a96207d6266fb3ae79fc55b8e94c9f9684b659452e78b2aaf9608576065e21a87a49c41ccb1e1699ebb5d1e426995b7d177fa3a13af8a423a9599c0a254cf5b8147ca5c6a5d624c63adbfd29cac29b5717c39a782f226bf2a6ab5eb27a093e1d80d69a73ecad79b66fa1a55d7a9e54841fef9ae3eb93faeb0ee3ab5b769ce8d32aede172753e8ab9e6c75b17f8efb8a2ddece06373bae1797762ad0f9e6e56f8e6f47bc92de3f4e8529cd27fc1ae1b8edf7c4d7eebd975916c8f2cd66e9ec59eba33cb77e6be6668e9aaea9e3c9a7ebf7777be2cdc037b68bbb7665c99ac5dadbb1a316747def1fc9dbae8dc9b7f5e8cf0bddf455eb524aa9df88d384b437e7d78bd9edc1eebec6eb5c35ca6826f57518bc355f314fbdfba4c3e5124aa62e22f1db816bf933ddf4937199e14f615a931dc6dcb56e919946236f725bdfb03854306d66c250c35196e8851db4159941872c8e4e905519b10658cb565a329c9648fa2a0dcf8352cb6e85c6669dbbb9f0f16f191c1a52f23664ad89cd8f74a27e9b0546b2261a90194a52e31294f44ea080000129f4010a000ff00c2000000000a0005000080ef0059d2318ac80e04385070e1458909022c78c012a3c884172a5c5871b126cd8a1b3a44e8f1d3654e8bc88904263015a2b26509569c3992702bc597216a235933d5a9c2913962dc79c3f6acc6953382e42a0455e1df9b359e056a6379aec8af47aa15298091a6dcac57ba7dea06fba8d0b467ca9d2b86fc61b1a82bd2d469d6f52b48bc3d4ec51ae6fe6c5bb437feb5cb27bf6ddfbe75fe063c9750726abb8103f56c1891b3c094974a8cc85913b5ecc0273b76dc0ab3764a87478a9ef98ad56a628aab53be7d7ad57c68dba76bdead8b567e6adaa38e5d68e055ba40ae3382ae1eb3b8bac3ea039fc43e2cb9fb6b9ccb8a2f381ddaf3f5e9d98f67ce1cb3efead2d7954b9f2f8e937affc7e5dbbfdcdb9a76d2d7457e05bfc438ed5df9f3f7d7b9bf1d7cf1e710a9617df53020803df79023477dc75c586be948fe158ced48ded5851e3790d1880146c754684d3624906a85f402e28a2a55d8df54855572206e81559850622ab86026465958c3668d326804658e3e09bc965bc9148c5373b1180b90880297c463805a2825ad6e46185bd59df15531d230d1143c5786e52734634c16994d968119a62469886af6846d49ede8939f41d9b5fb146e629805d16ad9c825998fd588d45c48727728e886318776a045251a236b929aa9f3e4a59aa9e1a298729585ad7e46d50a629f9ee50ae2893a9a4aa9adf58a5a69a8f1baef702b90367568e9676975162ea665ea3fdeaeb685cba19fbe954bd65b4944672e59ca980628761935d45876d53bac217acd3b68e4bbd16b5d6277da88b0138a11138f50b86d186cdd75612a60eaba4615cb6fab8297065293a1ab0c9ab70175e411513a563858b0f285d554b6d2651e6bb81954f12cbb5129f41741be74576c707e3c072d52fe75513d83697a822a6c518cef5db9063cb365431b84b41f7d764812b47685eba919a462dcf01268133c5bab9c27a9017982ba99cf165f1ddc1f63ab5d3833f0d823aa04396ef51dd192c1660d54acbbf51480dac85a38ba1a69e24a7bee9113a5ea98d3a539037fa7538da1b9bc5e2c6956a7f60dc05fbfd9ef9d3e6f4cea372ed88eca2d30f38233e850b3c183baf26870ea9909bad9075da827c53f9da3a6db824495f64886bd207ab7953c361286d18d6ab28f679867f451f97cefa3dc8225d4ebb71f47b570d2b589b7327cf2cd49bda18b5ce872e4cb1df575d7335b31d4cf170e6153a17ebbcb74f59f98d97f72aa9e4df9ab53967a287913decd6d919f0a99fba157484ed9739748c59449db864d6bc8d67e94f6e4219beeeae2eb8954ab9dcee94ffb8f418af54c9ba4166553232a85c635aa2c88dc446e22e053f654004fc57f8c24b90a1fc847afb0e5fd8f24032cd0d817c1cdf15dc866cad95e9ea7fb9ef0b8ed713b21dbce96572575486742f2e2159827effa2475884172d31b800906f0363d1fce506b3b5a07a32ca3d18e697fb1cf56e2a8abafb8462d6e92ce17f2c4981809770480daf12b5ef789b12efb4e5ce2139d052347311eece98904375e03e76329c9cf218d5b13e90398a2a2dd90b061ebfc57c47316372677ca797c5859b4f5c6c2d9bc63771124d96af4eb30810e429b94ad5f6ea6772722aee5736a5f9201851e94e5c1f87b72d2afcaf8b9225a8ca22cdb090e7069aea0017ea45e6bc6d4e6592830360c6d68bc75a474f508be897ec369d35f1e1947babd212c4227bcab5548465d332ade866003ca573b65454c42eea295c28c51d6939aa4811a0483dc1b5fc0a84f955190596e71e366ead7d0efb7a9705362b337e4fcc5d4470e0ccd9e113cd315f87aa216935287645014c6e7e83b9deba72b6a7d04070908c7711f2e69411e50a237353736747698c215ac0f9971152257c480dc4655faf80abac8ff486493f06c1bd5c4af4a0f25920d48e73ba3eb4e4d9f819782f31af4f8eab3dd4cc28f91926d4aa9d0c4f162fb486c186bfe88b3df9a76688adc0ed25988ff47124aca8c5bfa46445a294ad50c2084521662a8e51894698fc06b63bc5b0564691d81c435547adb2ca868dcb6a2641c2cacaa6643a58890ca9b814204c7d7077648bf0eed288b6d885c3ba897b68ed924a66d5a1cfc99321bfda4ec9ebcc45a33b9fccb9e14bb933542e055e976d2eff1d4709385e4686b38c43789dba8a42acdaafe0841dbc2a45739d49bd4ee48dfaa119d08a1854f0065bafcc6d2ae09740464e4be89e4a6eec48e8ccbf2d5516596afae9d4b48dda124d8798ba0fe34dd79a357656d59bdcd95433b80cce06c136a0e37d625ad6a3d5cd150289bc9c0b01839d982df9a1a37db62f4fe2604f2e72b6780d791a5d89155caaeea7a425a52543195cb66996b3b6fdbb99434611e9718f6e962b73213349e89b897b64971ecfa3b6657b94956092c0e140ee210a1b3f994702c015d0bef47c7c4a6637137b2dee248b2c2c3d4d35da766cc998de5c32c2de605f888b8be6d6b65d36a65273cb4eb924a41a36c266ee2a8c0eabaefa5f77a6c651a4526866eca26f4caea7b527b9cfbb296fb48a32559a9f63abb46dd296373fdb0a33978f51bf95eeda99d80fb489519dff9e79c43663bac2546c4a21b8e274bcd62681d5849c25d6ac3b8a21e571bb8d860e9d81f991e84ec21f5d99599a0ff344553b9f48c3d3537c7bd626c93f34364b369a19696660e8de9936cdc431f9675356472fbb0ebf4e56ad6de655db799432ab1ea822a7c512c1464554cd0963e199d6d05cdc51d76423dba645a9c93a6976345c0bb576210c435713e93d603af516a9639947e219dd6c0cce4cb45887c07ab95569e5aaa35b3a47da86f480b18cf7f0ec7c0db447fc0aa54546fd39a6275cc4f7569e9688f6b5fb49b2c2e91478d96d264163b79adeb1c49468462fabc74d09b4a23e43c46b713db32aab5e6d8a33e0471d5119b584ef0a36d8412c697c888787ba93bbdc2ca42c11bc0a023ea2abb4d0bea7f26199a0fcba0e2ac3b6fbd3545510cc61aade821a3315912bb6e0f0dc5ccfce995949bdd3bcad3313ac36098e27088f6922b80a883c41b07f79db46c693f2c966959e8b3ef922634c129727cbde91ec5bc483b5789aad3ce52febb5d773bca094265de83b5da9294f5115ce9796ff75ce01580bbce6e28618a2af1b6e417924b360240d6cf4dd72d2b9a3395fab1a93da0b287fe1e7f6c9666b3f1179826047cabeeea2e0ed19c310100129f4010a000ff00c200000000fe0005000080ef0059d2318ac80e04385070e1458909022c78c012a3c884172a5c5871b126cd8a1b3a44e8f1d365409325466c0982b46ac3911b890426f27021b18e2599bc560317ac4a950f66ec99ac086d4f913382f4b9f2b8a0de99457a154a8417a2d3a44d9e2d8af37724daa04fa275da34b9675aa261c2359a659c2ad1bb5bc245e8c03e6749b529e664bb07116d5db779f6e5bbe79f6069b38342ed9b18b0fe50c4851ecc7ca316ab47909b2325ac1933b464a5932f563ad9f1f7e0d2572386dc5a933aedc89943be3d69d4bbe4dda53f8e5d4b16b769d8bf5fc61d8195a164c97507363e3c19f1fdbac39f2feb5cf9ff54cdc7a75f68e718a354bf6186777c405bef7ec8af49bb8f3853d929f4fed9d387dacdf669f1f7e9961d5f90bd7ef7f3f90ac71f1e9368ede776d776fd674fd085417780ed71f9f7012f421ec7cf9c76164860aa771e48b1258d41e7c1248b0ae712698e1e3862e5832e08922685f12820e285e118b89942dda46dd1683e07a25d858de8532940d1178d13764a5480967816b5b6165b31b5b4d8595d96f458565e95b9da5f4e695567985d79f5d49152f4e513995d99351b575e76e46999a56606e45c6e58a4a047850777ef897e47246e998509c3a07e723634ed82192663a3712146c4956e4996a5a86449f407e89c8e5a0725afad766bd3aab159d95791a24ab9a6ae955a8aaa6c829a99625da9baef0b685f916637268cf1f978e19a86f8d75ea18eea2825751d57d72292422a08e0a7f55543a4ad8a485fd7513d258225b86a7a5415ad658503a39d5a6bee5791924bc2e496ae794ea99a5a180ee3bd69c99e916c2219b1d876c9778729734a442f5ebf7e356cafa31efa819293cafb3120a311eb982c5c03343966b50d2c0e585c8248cd2ebb496b3b269c319a10eaa96a7af1b7bb1339d1fab3a68c42f9cc17d6fea96ad67a56a968f9dc1d9f774d67585fb919c74ca0c4422b5460d7c2faac6fa68a2b9fee99295b3d2772894b71f5960bb9c6dd655b7b476a6af96bf5baa81b4cb568aaa98bd133a9a1aba5f77a6248ec2b766efbd47b95c22a0c90bb42efd5576071f2fdb79fca7d879fafc41d3c80dfdf091e983db8834cf7a1c387a54a97b54f9b113ac1793a22bb85f69cc378b60d8933eb81027a48728d8faddfe87a8fa9dabda3230ca1e2e3da387d934ca60b0817cfc988dd23c015d7c6706f2e49f79be1121e3530f75d164cbcabc1986971bc65a5c9a74027bc07afdc2b6e3428d9ca9c48e4e823273abc993ac929f472d6ecbc39b29fb5d7d5fa7329bb3386c34b0b6069976e0298897ae17e13371978324ab39def04546a4e54deb58eb5802f8c74bb3d1f64467322b83a0155b16e947a274ca8b92a2a6a63d396d89696b5ad3b6562710a1e58a5bfa602ab2b48c98816a61549329dd52b4c9b8c97a677eff110e83b4d3d81c4160b86f046160ca17c0be0aeb404af11b40aac5b7b6e44b268702bf50c8f303cd2a3f4b2ec100111fe7b1220e0f26449b5d1e8ce5dda22e39aa7232ea4cfe3445cad57b6479e2d1ab05c52645edae06808c61a4c8c670487950f475848cd08068eb39114e46647b771c7cc79d1746346f887c44222932333b803e2641f2532f58b537163267849783341eca123fb9469c47770a2219e895a8ccf0b926452c7f4ed42628b629fc4353a46a482508a112d5cfc382aadc18e8264522bc9b6c628b99df4c399d143e0d699903a6a442f608bb79627e5719dc8ffae7c33146948653296fde7af60bc80e733b7b7252d605e92348951c414d1efab29c5ca53028953e05659bdc9c92586b3086e6c678d2fa1fce095e4126633a821492ee6626303eb542dc20d3e399e2853222a9401c9a3aa5a2e2744c37ad78a79dfbeddf3bc97d926c849d62daff411f639e3b99cd81222396eda057035a1ddee4526c915ba47a47c3bdd0bd842c176909e7a841163922abac6e4623737ec0a5b25b71ecab9a117a48aa527579811da79907c806ce62a395903aca1ea474deae81da493525e1a60579cf322602768b3b7a4f19c66f22566c2f8ed2cedf59045f188a844d99ec90dbdceae4bcb8e43572b3f8e53faa74af4efb467beb4f9f8cd8c1c93ef2dd507475e5e0da0a11bdec897c451ae52746acb0d4ac4fa5238ef424213ab911124a8b672cd0a8fe5371c690ca8b978a55a7575b5854d8f4fe47cb8362921ae5c79e4119880b7ee1ca865ca3e8457f914217201beabecc62cfe370b591516a98cfa85d9e2644e92ee7a247bc33f288c340c499222ffa74c4e241f4b5eba5a82359d6a936a6fbac359edf4f189cbfa6b8e742f51daa42c536c6e52c01b3a503aa8a221e2c02b13456697260350a513b468f8f288bbba2750666bd3e4270bd9c6a9e6bcb22241f533399b4a7562d22cec47d5f6a93f2fe59113aaa5ce164a57a025bc3fe49363e9156b89c7da428e02bfb312ba50ba2eb2ded6bd866bf173cce4504fd2fa0e6afbbf218cc78c5b6294ae4bd30e653b04579ba1ef7f4d902e4751a01a33acaed27e663b4da1b87b1a5e23b33c53c41b9b0bf8234b66fce48ba53429793adbd81b5972abe2c1612778125cf8dd02c066466067c9e0431357f3422b3ae165f73c17f849a1d48a1535ad7bcaa6fdb66d557de2a3d2a84cc30af1f3a3dc55ac7d67afc12739fcb5364d17f42bbc22013ee47e233905312c7fc71f23ad56f3bc2a7b14e6e9e9ce25c47bcb5b5b34ebe441d8dc3a516465198a3ddeed9ccac53b24eba0b5b96303c65da404372c0dd8e14135e66f81a4241a450bab19c93b9522cb02f111f4f8be5f2032d09c15f97f76ff493a2e069a04d5e8095dcfc331e3b8a12575b11767cb4f55ace0d1fadd9d498bcfbbd676ef79cc9eea2e15ea144bbcc6d4774a077b9d1a502a66dde58703e7a6878bcf10b20fcb833693abc509b17a8f27b9948d9e2980a670d67d0071cc0d0bd059a4c754a11bb3c02a17fbb58d8bdf236717bd84c510ad1cf035e5e7f2a6c61922ae2b5c1c467816613e3bb57bf973f8076c7bc5e2ce16815b0acd6fb7fd45c689b17b38a8de074a2e48b5e635c08b732b9f9b937bc4dcebd43d7c664bba9ce9b11ed0b39d47f0626193a25ff0a79d2a57f0fefcfdcfce1b2551996f67bc6ded9f859f969dfe00a792ce79cecc2cfc2fc6521ae19538910597b96997113895d4242906c1b91599ccc8bb71dbcb043731d5bc75ebbd1dcd28e4ddf0150e1653a1d09eefe4c8b22c705fd2ee8d1238d4bd756dbbcd4819dbb93c4bda3465ee6b7fe1f69a9ac20d762a2de39fc72a92b29f17e5deb5fbf37746374864877236781695d712a6677c52c54dd37257c58550d7047c25bc0d45b47721913895eb7f73e05d07de7cc2cc4c02217de7ae2003fe3562243c812671e4821918dd21b37a25053c73d5a644d68e5765366943bb71c4227837a733a71040965574334183b6157624a774168663a3876a344f37271773f69d37634b2eb3775b760b2093172f344246616581866b4e27197e84ce4ce3da22e64843171f7007f84545406a17ed5982db4293db6146848268985911ed6ed7ab6446273d389b39f57571c52c44f3808bb7ef3b78b39b6138c08314f170465b5934d182877d25282425f65a4cc79661b54126045c6ed38d3fe4d08863187d661c6b075837d17c70e78b23553655c4e369940949123b33d7975d97447b166c4bf6306f95f869e77481f2616ec7ca6e12693516265df7723107c88a82ae43b8445058c589a5bb57012485b2ac77b8c560f4f66a67383ff5232b158458d45676e38982346b7f55a960a7376532be8711e37c321171e7ec5e58fb7812cb1d365c33781783977543b8253408237eb2ce40862e4c94dd56c70367a79969172d5ba55c8337c26a273066b2352b03676a74236712e332e81989b4029cf6bb7f25c167d56c74075043b30978f6475cd8cd54d40383ef93a66057a26527dc3fc82a8358f62d35d68da4328498287f96256a432c1d580e80a6783f122b84885f41d7956a94b75083836de4109019386cc13b58f3176b35c98381bc8ea7796e03dc89f8f94b45d49933d596386b38c65c30c89d4316819b39aa29360b8757cd51a8907168449967be4a490545345a57f46641359193683442d81980b80e30934d36f47640762a3a482a5c83d12286489717599b162493257570237888464b7343d576e8e59f64627a583a9cf85479e5cf5123459736418e499c6d847e1883808429c23604822d11fe32373148199f8ab88755148c7a428a4c66ac4a13871d278f79d67b5388077515306ec2557e61b659550e7847bdef44e8d83028829a05fd8b57b84934a898f68523731b99b2478e08511679e67248315b586a4206e039d6cf51a8b866a66945f75798a6ff24a4cf6295b63c29d799493e2238dd16848d8bb7ee36949a6fb8586043f253a9e045b32d86b4b29d780779598b50526e4f89265627887ea80c6127458b488b7a73d658c7779058a47877c69499925b49a94867a464663761691176651b4ba19e8ca8db2c834a3c0a3845659627d50b409890af1acb7859ba91472c5a79f93d73bb4de9975494a555732d3f595a3394b252528079776a80456c59d75b44d9fb6535c63ad87e8276d53984719f79638ea51a9c589f3b375a9f74ad8259253a96e757f3b8612884a574605e5683ed110100129f4010a000ff00c2000000000910f4000080ef0059d2318ac80e04385070e1458909022c78c012a3c884172a5c5871b126cd8a1b3a44e8f1d365409325466c0982b46ac39a2b52bc794216a9c894376adc595317adc564c4021b18f35951b283497af40a3078a05f974595055a54b72f44ab479a1d9ae4392156a85f9e6dba14dba559a165be8d6a263a2a53ba6bb2b5ea56ba6bd8b051e25dab06fee752ba7fcab59b673b20ecb281f2fd2cb77de0e3c96307362cf891fb58c395277468891166edca9b337efce93438e1d2ab439e3d6a353ae5daab53be7dea363ce9d2bb63d60d5c4befcddb478ee63a34d7f4de91c3b2fe2efb98f2d4edbd830f5e3cb93374e1d9af178e7d587677eac5bf37fedd9befb4fae8dfbb87be6e7a79f0fae1cf8fdedefcfaf7f9e9cbb74fcedebcfbf3f1f3dfcf25514a3d08e25e450ed4702182392860e2890e38e0648d0e4880a4851258c0e58a166841975a5d78655885498840d88626988228872aa892298c2eb8e26c8b2ac8d2ec8636d8832c873ae8932d8c3ef8e3609b3a09d3e09646198420933265f7954126057555585d39a0508a4d49322496562414159c5949d5669552a8d497915e5916214a529985aa936a95d62557627970989f52a957ab9772d9f59063769967ef917af9b520aa7a0a96ac958e0ab62c99821ac6e3ad8289976e9805e6e1e6801268b9a6a616680a67a1ae7a2a69a4ae9ac92aae96aa93d8855e14efa9978e5545a51da361655c1ea7beda3b6359bacaabadafbe78fb5371cafa745fa7caea3c5da8ca0b9ca3bbc20bac65b4ce4b2d25b9de6bcb27b3c67b6ca5b0ee7b4e64b1ea7b6e69bea6371ba49aae8acaeaa2f2cb3fa9a1f2db8fadb5febbaf6ebf2d5947679c01f76ed954d1475e126cc5474e5e51e1bb707d5ed9372e9b57dd3750ba511b2cf79b7c0f5cc7d3c5cd8708d4c5ce2c5618c60f2642b0790b7582b3ce7d670132c2135c72f7c849aca179cd09da926087f6fb443fb64f0d74feb84f2da473def23d0fa0c6057935fba8c2ab7deea5e66d0d24bc5f3b75b6d0633b2636be220b7ee9df5b7d56b8bb22adb57bd85bcd96fbdb678de5bbd14fefdd467edcda26b0d23c86784390de920cc9a4d81e8891249baa1ea022ea9a2eb123ed9a3ec024e01a4e4025e30a5e6126ef0a3ef66f4735b5e3359cb57c83f8932fc581f6993bfc2653c29dae96abc685dcb3356f2bbec2bde82ece737dea2b5c485bc98dbee62eea7dce91bd5acdc94cf65ab70c337fe7892f9db3432366c3dde0571d3e72df4b3d4e3af6e7af7e7bfce73ba1d2c5ad6d5cadadc627fa2ad7f3cf0fbdf8f71bdfb6acef0085f310eff89450440e003f795b50a69895f0c306abc08b0c90a2052810cb0eefc2811cd0660b388f3e0230348f1c11660f76b51fc4fe2443b12d5ca643e24cc4c0ba62a991a5de3363410a76278c4ad12c0f78ef534022e0588e3c02a1178874c22221798a4c62e66878619571344c22110cc57ca881943954256f5203d61776d5443d71d83164e2d81177ed3336611c8152f2ea19c8d6413eb11d869a632558e8924b3a060f8e6c680713e8a64f32b1304d74d31f15e8284832121196840b4a11e26c2e35ea2e76b28227680881994221fc66a970606a42a0c0b586c3946bcc0e82c6b9c7b572f68781052923353a465288c49c224561193924c649b0f5841c015c2578f241d1a0917d998b061779234b3295eb44bc679321321a9ba1121a9c118d5519a97810d53312915a66ac09b9d0986240d944dc0a9e0bc9319c6664a22cd43c182bd94ecec8433e9911b6e84e720aef892da13f90b458cdc29980935082241c72ddc311736db5b4e0965471f566681a7d2776a1b488c44696b243ffc491241e7dba57a75af035892c20a00500e3473f1201507dd3d0aa2dec464992254e3084f50d703792be233ea465c2db21a0e3c412b0508504d4f340a00920558a9e43b044c879493a2259d4a72755e72c9d29ffd53d328e95943f036835e8c57489c110e9bcc1465567685138ac80583538ab0850c4d8462ec7be1ca622651cca3f58c78710b538ad70fc5442bae29daaf9a121a871c84f0b508a9605a0bd6d0a2f570b275066548f0e8d504a0e4abb49cd3496702aa767b6b74bc9e5805b93ccda4205e9a33c32768977db27ea0b83871aefaa91d0b35056892af042d924f0ba9b74e8655d16fc4f822fc893092c656d4ab550de25f3bd9d59a0807bd851a2431abe8d1aed4fb886be3447b0082a311b0506dac4d013e4140d62196cbb25ceaaadeea99cdb5c5da6bb24d405a6a6fb2dca7d8bf206ac92e500a87b63015b93ac12f2b49011354979d5ad57c2143db303235a713a1da5d905e020dd196f7b7890e192143e9bc8afab614168d0aeb0cca79241ef531339156c4109bcbc44d2ac1c682a45cf095436d3eee25c25b0ed06c7232ee8813df7ce4dbe2047be090582a8d95715c83457c0430d506492358e34859f078d7a6c9e5c591b417e833601ace165aca72f27b51cc0d2f1b3bad202e500eff7944fdb28226ee982535c2061cbb2a1a440570d4603a879a16da17413425fd217987918b5fb80a19cd4905436b6b35298c96f685c483df9f420bd0982abfb67ac072639a621c37835a817174ada43dc707862838a5ae666e602bd7eb4ea4d179953719d4fa8cd73eab25ade5ef924b22d3b58864b3292ddb903b7d6865608264a7053cd57912e4dade15695ec4cc11bd7db24ba96239a171db299dd47ce3c2f1ead8b631362dd52963b67b9fa97a1a47b74aa853fc640d619992eb9cfb0350075354af4d70f941bd13108503d59a29633f2d1dafc09cba6fb32d48e0ad3bad11960598c0b2ed29bddcffef5694ef8a91c77aabf44dd9337a9fce752766aefcf6ac8a0710e2c801cda28ded317bf25bd08ccc5c6f12419f44ccac49174d4cacb329fc9eb2fa7fc0e1edaeaabb559054f168a3332a300502fd6962b1d8d24e204b75576e548447f50db2f4f5ba6e214e476ac8247661a0a1ac5dddd69c7fa8c5c312c6ae594da48286e1319847c5ac171dea7b10aa491e95c21664fa9374e8ed49e3816bda78d92c181421a078b5879c36209636f5024e82f1e5dbd78c24dc79202d204e773230da9214e4135012f1635095035079733e3d3c24ef1ed7049b762dcc651b3d579cac8aca3bdb9c79bde418da24e71449f3d055c883e54c58f6dbc94330a0c770515e579c03255120a8c244d5dcb2e95e34ede09f6be41a6ef012d19afe9f9af92932673ec01397bb7a9241b4a04a8a1aff2f1529fa879a7144bbf2099af47af358354203fa1d55376124a477451287325697b014564084760b57f77772016a02a7c864c0335b86e310459506f71f7985ec3577197797bc07085009505e5171a87325500cd7b26476cf34c58f4747ec7435747c70405f57501bb7366311cf7028e774a39c13089856a07529c7ed7228081d38aa71258500663017c65d5501585f20b16bc01d7595847ad1527387500850977fc5aa7847b917e62d58030a0358e257643475c5126c08401868145241287454a96f206a7485126b75595907801a87d58cb1978611a65595500b06266f85a488f7201350850ef7d7b65950607538fc7922978243838556f78c86396d06a01f78885556397db15165b5b47bc0e07435984601b48c68c916770288c7b68df7e85b51a964052874e7401c85425cf5991a86226a38283a419b83255983b22888275e78853480a3334676276867394b68ac0975058801026e85b97936428e97924341a87ec6c93868350893ac07588459a8ed7e72b48ad70e8ed80f33f7885108261a872505922020e8587463a988d4682d344535011d55988d8e01ac7df8064837e85017806487f20af7081401f187b80931f7e97991ec7da7e17c25501868f48d72ed76a7fd8416c65b00770277ce8a713e85b6103f277362019d8b989644287a05002781b5eef181d5e372041f7625ba6c01a87b97ee55c05565b55413413770e8a97de7d582016b7ad5e95a268856a0711a398f8eb1e390c7b75e65096131e83ba6341b759504c1705f496d7a51dd8d914d5f291344619371787346d8533a962876d5f24e08aa7c294199053523d72381116273b8c47b756d5f37ce5ee2937b00625e83289f352153223d70c7309ee7824d175374a5c898a61172889977d8965ce27577b84340d7cf89f3f18479dc4f09d34f78e52d53676c016b7de5752850885af75922431181d50295473689f3d91b758570d4f09911f58097093be2f09e83287d72005377b24eb8fc75c2eb8b96ee51167c7035cb9b33ca8a47972ac7245b381e890ef8501e29f87236c38885cd5839456c65da95b6ad44c03984d83728988853116a04254e8fc1b47ec7cd5811a980898255a5301b59ee25a8df9f11484f787a06011e8317cf3b694b21e8099271627b00bb8964341a86556c51305ef5ee4f585985e7e850884552b9c651671852f68934285293017d9f204a5939885950296639234950c2a562ce4556845b851e9d2ad525b35b7556847e42a414590a05c113ac657b7776bf8358e51bd5eb52238a9281885d36fd244ace6363d41b65f396c68850171a6924d172f7ff83e7c914e9d85726e46f78967824d26301a986722668d902236a5259562942b7601e20d85d1a2031f7b88422e831f764a0563394552a7ef028d70235d2878a68a337a9634652236a778a01b95bc01e9c0a5a4678d58920cf8038b9ac9a647459a1ac3a785c27fd41f8de91452501f49e9595d27e82d17f0a72a556b17801e240f9ce8122b69992d17f98ec50ba587c995c6552df75c97a6e88b01249834006571141d88e88a41b65458336341e45d8a1c9d79dc16e8f07f35788125350250cdaf20edabd7cda019767587a61c5aac053ab56924bd58478dab00250ff7adaddacda950e20bdaf202fa8c51415a96815a3096946e195983a6595be96378915baf56cf91d50e7b476b21e89f55512d9a6491a4340033f5398dd48e72d2c3ae85b37be627a781f58439558a5633a9175285ca241250556eef77d22701478d8a59242839762711b721e012f85623e8c7aea6f31678fc9222a980e763b0b2f01e116267491d56172b5a95d1b4dad917d90aa8779014982e7baaf799941f7b00891b682283036e770a0b6c8aa38522647ba739896bcd5792d17397c31f89da66f6504b49d85e371021f7db51f3dba226d34b49e85bfa0bacb7ab6b915417988dad70fb22679ea409702398c26428ab9507283863462398905b38ec26e4b0b226d8429923b51396adf75b5078422553d527d9b6b18ac65c26c83f8a529e23d341a045962a527e20849c26b6ab75ae817a489152a7937a4642078113d7e2b301868c5b367601d88aa8f52b68649b6864ab3671bfd5ec72ba29efa1aa0282b3f6179aa6823a11ae41016eb66f87113d379149339ae85b886a45c07d9de6f760035c065bec70c87b9b113d72f7a01c2b528649f31486368bea5515f9eeb5f96976e404bb11219e1190caa68446b2289e97322ac7cd50a8924689e9452a451428018b95f2b675e187c5347a67aa9054dea14175a0699722160225a94a4b717c799bb75bba5c2a26b597267db2ab95a5950652864282f7bcae19d474c48da96ae1617ae88bcb8cb5211e9347cc994865178b2a5d86382e55deb379c6556a9e41e80aa6885c88788f93f6f2b89b2e7785e6b21155611bf61571678bfa428b001b97823ba7253eb29b2b5f47601aa98350dba34f82a4b9eb48653aef53633cb7bd65e5cb27553f7ce1b57aeb2f8ab965c028931cad3de948715417a896a11e56145706f21ab4c03e7b325dbb40187be4635209ba09debba3c8c385394253f31529d4cef8bb232c607f4b27ac7992b7468f8401e798dbe6cfdb015e246b276cd9b35ad8ad326613985358daf5a0f51f8538f075c2b69d64ec86daa710a32bbea995a339c5604a5282e91225165ca81bee7014d02801ecb6117cb2c6891b7ad913d7649cc94199367984016f9d3116b7a1df9fa5d41df770631a46c7553326f955b556dc527be86cf8a8b5c08da446c938830fca68b757e4df4dea1e47ecfa23015dbbd4ea2da911d1a8f786a0b3aa019c95591e44ca4f5f332885ef29154427e0c04cec2289a93462f7a99b7ac6611e88bb49ba514c9a01f8a72d6d1551a5a7a7d0176a989d791b3a7489760b1e9468b67adb12287c5f59ec1957b90a985a289d188e7a6176c65355cc8321ac2aac13279515889ea91bc96a410a9257e1202b5b61027dcf85d573bc954e0799c4551f75d6683a5c2b51f7d18d6850ba8c99bbc0918abcc1ad7d1a1595e20ca34b2a98019f1a2f9544c83b96b01e195fc70a7e4468edb9765ea57d0a6311e1dd855a880d25532189c389dd4eccfaad72b9da6624d4b8cfcd7c2aadf4e7dee9f75a27a1601117a56c17cae11948f6ce6723b65c966928ad9f57223dabbc619595706817d5655925126848786a29ef614125942670145988be017cb1a0bc4d7ba3de6532392b8fb436672b620037571e63f8f07b374c284a408003f59675fd287b462fca386288faad0532217ad3647bea89c4d527cbb6b352d3dbb242963c2c49a18ad649bc077a1b7483e7a48750030b90113b4ea5418dab39705b412bb649d69c998592ad1e2bfcb75cc796505a2f4a942684eac3121eecd7025aadb12591d6cc902dced6014d586c05286843942631a57d2347ec2930fcaeb0162a7b6681d8dde1c1ad7cb88388cf9cf776dab47e31fa40e4c8da721f7596c9604554ae366fd2933e8ab515cfe95f7653abaef90f550b17b4fcd3a0d4e6a85ab46f31e08bbccf952e9b671507c5babeddddef80136a15a764aa7fa91e40b7479722aab6ad803efdac9661916eb7918f13abc229cb1b68a1e9d69972aaa61a8edbbcb1f0cd06e05f82f0527606d8016785cbf9ea5ccc25ad42dd61298a2d4c2e69d544cca3e6e54ab774cc276a60e1576493a63a8f277cbb882cbe95b375f9307c3deba2b6c5ca6662e3226c5aceeb692702a1a1eaa4ebac7b882d7d49f4493edf58015b8fbdc11125ec88dcd5b595029b1199af7b69d2832212f3e0ab99149a98a3eb07998d7dbc0ac85281095a8dd8f5b9016a01a7cdd6aba98d1aba59cd3b9c27deec91179ad728e601dfe81928c75bbfba7b7c3d1c7fb8cd5966cbf07e2517931e1a50b244a809b3875be0f152141aefcc85a3f5acde4104572d7517083467a0b376b581cf41dfe54ecf8dd18fd819d2fae92784e1e2c86e2415ad3d8b16e0af07706365f3e757cf4db17d9a6692824348e15698a097d3b986da8638b361a8bd5366504a41c8af07716781dce31e78a23545f6eb941e0849d9501cede59b3d4ff859cad488f6da7c1e975a97d49c37462a65a7550894da975a63069cef8740a81d7579fe435df576bed7bde26c158c5ea66a8aeb7b1981fd85aeb6a0f8ced7345258b5f920c0ecc483554160668ad35d354afac07a01386f76476f7f91aafda7a8a68a03f93bd35008138f173017b5250728748ffed952050bf5452cf6c7f845af235545baf57c1188cf6af545e4efca456a0e35cbfdda8798eac3d025a8a30641cc017cf4af6f7337a33b45c70ff7728ff7967a9d5ab501ce72eaf357bf4aa462965e356180776c66cf6c7e837b5ff7afa19a2b6893d356ef001d74911b56ac49513565031624280aaf834e3f0bf444057a49582e3817268a98f0f4114388051224280294e84385055e2c2822712bc18827911389b2916dc79f2d523c6993d02c448b0d5ea42a70d8adc2a44d46a4c9a0362d458bc68efc4a03b4eccc9b2796140982f824d6af317a1d3a039a66ddaa358ad41bb211e050bd35567d0bb0796b53a06f564d8b1656aedaa37baa9d99157c65d0a68b03355a2891f36e973fd236ab27b62147b0499ed519027fe5ef52b857173e89497951d4c96db60d9ad3b85160c097ae168a43f53845d67d5fd48d84d86be09c371fc679725733dfacbb272cecc2783fcac52327f6dc3adaadc6e283a3f59b5bb13e6de97513472f393079de9475af2efd92bfec6fdd9d03b4ab297fa0d2b5a183df9e7990f95ae4e3cf2044feeb8fa04fbe8b4c4da207e3eaa7a0ba8bcf20bade13cac043dafa3e0f340d835f29a8d2abbf6c20e6c3da2db3fc7bf091ccca8affe4c3e04b9caa30f283be0abb1da3ee2934d8cb9beb27c6031d02b9f4041d6dbdc67302b4bccafbee07cafe746d093815e34255a709eaceee24a04bf1d7b60f838052c1d09c6f66c91f8c8caba5e8fb5c6b20d2f33f8742efbca452d5a5ec44fc2543d24b42bca396fc7cc83c07142daec7aebb707943c2f4dfe5c0ecd4947ac3ccd3bc0446fc5c1f62b823ccfc673ce8eb7eefabc63522f4da458cd0745d01c47c223847cb85b9283973f1d6b8c805c474c3072b6d83b10b6c405c3c013511574449ab02985fd4a404d0ca0335c1315fc67a61bad0ec7d26d64629ac907a5cfc05fe69485dc30deaacdc051556c53b5c67b6c5a0d45e2bc54dfaeb43d259adfbc23b6feba11f5957b4b7bcb7acfc12f0508bb538bdb15fe3c35ade2be5c7f16b5d4c8059b033e5dcaf5ae44dab8f5c012594fd488dbd66bb5e3d2e39d36471dba17a453555d43e2e2bd4a7395c511b4471e48dab693befcc59b5f21659571d29773d6b742051b51504a478cb83c4ca4dd8399e053058afa5cf8d4a33bee31dd9ad74503bd6f6940b79cdf24d95dfb4d6cc74d866a82e93314763de06704445c4b0765713dc5a8d580946457f5e57c6cbffbf47ade4fbcb7395b45ceaaf3eb77b3a5515e935d3c1fd16b8efc6ab365a3d67ec0c7fe1c44fa47acf9bd489ff5cb3f4ac3ceddecd32f46dc556a39c4f67579c1540b71fbee7ebe876d29e6f35856c56a7cb6e3f4044b9c682d869df151f047729947475e56396c5184147d3feea79d6f6a5d65f877a93be3bb14cb53cd9616ec7bc267f54ae93ed676fd9f463dfeef2325241e23654e291bd2831521416ea95ebb3f02eefcd7d828d0ed614b0af812e6958f20650dee4fe2c903f0975ca5c1c90e6bba80e2aea4124ee909c386b2b99a5ac4c0c4b0ede25e1ba813c2e6dc3dec374a66320b859a97e8b1b50ac28c821069c253c124a9b78b7234b6dcf8e6504ad9582278cb0254f2c6014d398034513b1a5f8e56fcbff06bc55fc2a71be646d9aef4c03d5cf1a220036859a9719e4c76bbcf520588263b818fc23a2c9590a4d56896e89e6b4cb31c19a0e21a96558ca88ab22c020b37184cc9a52d238ced031765c9281d6c6d5a49e2eefea5bfac953d6766a305d8bce456bcec8d6156c1da938417e33291af072ff214db0bd6e7a44ed09f40ebd3278ef823455642b18544bfd9cefef6fb4635fca179837f960dc221a1a1d2f794c2e89427474b1932bc0b7583cc1101f75a90e92359644ac9df03a8aca076fb4b55db6f87fc498342a12aa442f370a405d8829edd53738e89b2d9d095fa2ee4e0328502afdcc207cead35da2352c2fbd23f972ac4e86fc13d63e21bf656202d3a83755ce4ec14aa58cfc179dbca612b8325b8161b4f2ebda486f105259e19564a4660db50fb0bd52df3e6bee83ba6afd3e3d6e838f1d5654e6b5a3de5ac3f0646b69a9a4d5262a9d1d06953549dc0dd580342592759dd4532bf4d8dfa81a5c07744c4c5fd0565c473e43919c4b64a5c4d2492375b1de79c4fc557ac7773971857a4bb4b317da98714dc8a68666ef9c1aa7d4b877417d70369e4c5e19e29a61520945d845e2bf8d5f677f3be9757744d1d850d8fa5156454f63a60458adea07e51819bb6985f397acfa16fda2a8d1d58a0b3e9537b7295ea20d6c956326abc054da3035a1ba8e03f89cc84b1a5db8239e724d7bee43391657da9d6a876d28d2d4fae2341e045696f99ed2dc4a98cd158ec192b5c3e929448c57a9e6cf950a51995dba58adb9e3f8863405911b5b41d05ae2d5af75c820e4a8d72cad005740e94d11faca42c11117887964b5a121d9bbc67aa2fd97b582238cf7fa5236ac034e94a1e0fa49d7cfe6059ba3daf0a9cc0938d7a59645bf542be339f632bfcac7767e523e17d47894b061d3dbb991e36e917c84c055175ecaa77c729f595c95d403361673e2f0661d152fc08a7876961c726481b554625a09b170c9ac6879eaa36901a5da7e9b8d5fcef4e6908000129f4010a000ff00c2000000000910f4000080ef0059d2318ac80e04385070e1458909022c78c012a3c884172a5c5871b126cd8a1b3a44e8f1d365409325466c0982b46ac39a2b52bc794216a9c894376adc595317adc564c4021b18f35951b283497af40a3078a05f974595055a54b72f44ab479a1d9ae4392156a85f9e6dba14dba559a165be8d6a263a2a53ba6bb2b5ea56ba6bd8b051e25dab06fee752ba7fcab59b673b20ecb281f2fd2cb77de0e3c96307362cf891fb58c395277468891166edca9b337efce93438e1d2ab439e3d6a353ae5daab53be7dea363ce9d2bb63d60d5c4befcddb478ee63a34d7f4de91c3b2fe2efb98f2d4edbd830f5e3cb93374e1d9af178e7d587677eac5bf37fedd9befb4fae8dfbb87be6e7a79f0fae1cf8fdedefcfaf7f9e9cbb74fcedebcfbf3f1f3dfcf25514a3d08e25e450ed4702182392860e2890e38e0648d0e4880a4851258c0e58a166841975a5d78655885498840d88626988228872aa892298c2eb8e26c8b2ac8d2ec8636d8832c873ae8932d8c3ef8e3609b3a09d3e09646198420933265f7954126057555585d39a0508a4d49322496562414159c5949d5669552a8d497915e5916214a529985aa936a95d62557627970989f52a957ab9772d9f59063769967ef917af9b520aa7a0a96ac958e0ab62c99821ac6e3ad8289976e9805e6e1e6801268b9a6a616680a67a1ae7a2a69a4ae9ac92aae96aa93d8855e14efa9978e5545a51da361655c1ea7beda3b6359bacaabadafbe78fb5371cafa745fa7caea3c5da8ca0b9ca3bbc20bac65b4ce4b2d25b9de6bcb27b3c67b6ca5b0ee7b4e64b1ea7b6e69bea6371ba49aae8acaeaa2f2cb3fa9a1f2db8fadb5febbaf6ebf2d5947679c01f76ed954d1475e126cc5474e5e51e1bb707d5ed9372e9b57dd3750ba511b2cf79b7c0f5cc7d3c5cd8708d4c5ce2c5618c60f2642b0790b7582b3ce7d670132c2135c72f7c849aca179cd09da926087f6fb443fb64f0d74feb84f2da473def23d0fa0c6057935fba8c2ab7deea5e66d0d24bc5f3b75b6d0633b2636be220b7ee9df5b7d56b8bb22adb57bd85bcd96fbdb678de5bbd14fefdd467edcda26b0d23c86784390de920cc9a4d81e8891249baa1ea022ea9a2eb123ed9a3ec024e01a4e4025e30a5e6126ef0a3ef66f4735b5e3359cb57c83f8932fc581f6993bfc2653c29dae96abc685dcb3356f2bbec2bde82ece737dea2b5c485bc98dbee62eea7dce91bd5acdc94cf65ab70c337fe7892f9db3432366c3dde0571d3e72df4b3d4e3af6e7af7e7bfce73ba1d2c5ad6d5cadadc627fa2ad7f3cf0fbdf8f71bdfb6acef0085f310eff89450440e003f795b50a69895f0c306abc08b0c90a2052810cb0eefc2811cd0660b388f3e0230348f1c11660f76b51fc4fe2443b12d5ca643e24cc4c0ba62a991a5de3363410a76278c4ad12c0f78ef534022e0588e3c02a1178874c22221798a4c62e66878619571344c22110cc57ca881943954256f5203d61776d5443d71d83164e2d81177ed3336611c8152f2ea19c8d6413eb11d869a632558e8924b3a060f8e6c680713e8a64f32b1304d74d31f15e8284832121196840b4a11e26c2e35ea2e76b28227680881994221fc66a970606a42a0c0b586c3946bcc0e82c6b9c7b572f68781052923353a465288c49c224561193924c649b0f5841c015c2578f241d1a0917d998b061779234b3295eb44bc679321321a9ba1121a9c118d5519a97810d53312915a66ac09b9d0986240d944dc0a9e0bc9319c6664a22cd43c182bd94ecec8433e9911b6e84e720aef892da13f90b458cdc29980935082241c72ddc311736db5b4e0965471f566681a7d2776a1b488c44696b243ffc491241e7dba57a75af035892c20a00500e3473f1201507dd3d0aa2dec464992254e3084f50d703792be233ea465c2db21a0e3c412b0508504d4f340a00920558a9e43b044c879493a2259d4a72755e72c9d29ffd53d328e95943f036835e8c57489c110e9bcc1465567685138ac80583538ab0850c4d8462ec7be1ca622651cca3f58c78710b538ad70fc5442bae29daaf9a121a871c84f0b508a9605a0bd6d0a2f570b275066548f0e8d504a0e4abb49cd3496702aa767b6b74bc9e5805b93ccda4205e9a33c32768977db27ea0b83871aefaa91d0b35056892af042d924f0ba9b74e8655d16fc4f822fc893092c656d4ab550de25f3bd9d59a0807bd851a2431abe8d1aed4fb886be3447b0082a311b0506dac4d013e4140d62196cbb25ceaaadeea99cdb5c5da6bb24d405a6a6fb2dca7d8bf206ac92e500a87b63015b93ac12f2b49011354979d5ad57c2143db303235a713a1da5d905e020dd196f7b7890e192143e9bc8afab614168d0aeb0cca79241ef531339156c4109bcbc44d2ac1c682a45cf095436d3eee25c25b0ed06c7232ee8813df7ce4dbe2047be090582a8d95715c83457c0430d506492358e34859f078d7a6c9e5c591b417e833601ace165aca72f27b51cc0d2f1b3bad202e500eff7944fdb28226ee982535c2061cbb2a1a440570d4603a879a16da17413425fd217987918b5fb80a19cd4905436b6b35298c96f685c483df9f420bd0982abfb67ac072639a621c37835a817174ada43dc707862838a5ae666e602bd7eb4ea4d179953719d4fa8cd73eab25ade5ef924b22d3b58864b3292ddb903b7d6865608264a7053cd57912e4dade15695ec4cc11bd7db24ba96239a171db299dd47ce3c2f1ead8b631362dd52963b67b9fa97a1a47b74aa853fc640d619992eb9cfb0350075354af4d70f941bd13108503d59a29633f2d1dafc09cba6fb32d48e0ad3bad11960598c0b2ed29bddcffef5694ef8a91c77aabf44dd9337a9fce752766aefcf6ac8a0710e2c801cda28ded317bf25bd08ccc5c6f12419f44ccac49174d4cacb329fc9eb2fa7fc0e1edaeaabb559054f168a3332a300502fd6962b1d8d24e204b75576e548447f50db2f4f5ba6e214e476ac8247661a0a1ac5dddd69c7fa8c5c312c6ae594da48286e1319847c5ac171dea7b10aa491e95c21664fa9374e8ed49e3816bda78d92c181421a078b5879c36209636f5024e82f1e5dbd78c24dc79202d204e773230da9214e4135012f1635095035079733e3d3c24ef1ed7049b762dcc651b3d579cac8aca3bdb9c79bde418da24e71449f3d055c883e54c58f6dbc94330a0c770515e579c03255120a8c244d5dcb2e95e34ede09f6be41a6ef012d19afe9f9af92932673ec01397bb7a9241b4a04a8a1aff2f1529fa879a7144bbf2099af47af358354203fa1d55376124a477451287325697b014564084760b57f77772016a02a7c864c0335b86e310459506f71f7985ec3577197797bc07085009505e5171a87325500cd7b26476cf34c58f4747ec7435747c70405f57501bb7366311cf7028e774a39c13089856a07529c7ed7228081d38aa71258500663017c65d5501585f20b16bc01d7595847ad1527387500850977fc5aa7847b917e62d58030a0358e257643475c5126c08401868145241287454a96f206a7485126b75595907801a87d58cb1978611a65595500b06266f85a488f7201350850ef7d7b65950607538fc7922978243838556f78c86396d06a01f78885556397db15165b5b47bc0e07435984601b48c68c916770288c7b68df7e85b51a964052874e7401c85425cf5991a86226a38283a419b83255983b22888275e78853480a3334676276867394b68ac0975058801026e85b97936428e97924341a87ec6c93868350893ac07588459a8ed7e72b48ad70e8ed80f33f7885108261a872505922020e8587463a988d4682d344535011d55988d8e01ac7df8064837e85017806487f20af7081401f187b80931f7e97991ec7da7e17c25501868f48d72ed76a7fd8416c65b00770277ce8a713e85b6103f277362019d8b989644287a05002781b5eef181d5e372041f7625ba6c01a87b97ee55c05565b55413413770e8a97de7d582016b7ad5e95a268856a0711a398f8eb1e390c7b75e65096131e83ba6341b759504c1705f496d7a51dd8d914d5f291344619371787346d8533a962876d5f24e08aa7c294199053523d72381116273b8c47b756d5f37ce5ee2937b00625e83289f352153223d70c7309ee7824d175374a5c898a61172889977d8965ce27577b84340d7cf89f3f18479dc4f09d34f78e52d53676c016b7de5752850885af75922431181d50295473689f3d91b758570d4f09911f58097093be2f09e83287d72005377b24eb8fc75c2eb8b96ee51167c7035cb9b33ca8a47972ac7245b381e890ef8501e29f87236c38885cd5839456c65da95b6ad44c03984d83728988853116a04254e8fc1b47ec7cd5811a980898255a5301b59ee25a8df9f11484f787a06011e8317cf3b694b21e8099271627b00bb8964341a86556c51305ef5ee4f585985e7e850884552b9c651671852f68934285293017d9f204a5939885950296639234950c2a562ce4556845b851e9d2ad525b35b7556847e42a414590a05c113ac657b7776bf8358e51bd5eb52238a9281885d36fd244ace6363d41b65f396c68850171a6924d172f7ff83e7c914e9d85726e46f78967824d26301a986722668d902236a5259562942b7601e20d85d1a2031f7b88422e831f764a0563394552a7ef028d70235d2878a68a337a9634652236a778a01b95bc01e9c0a5a4678d58920cf8038b9ac9a647459a1ac3a785c27fd41f8de91452501f49e9595d27e82d17f0a72a556b17801e240f9ce8122b69992d17f98ec50ba587c995c6552df75c97a6e88b01249834006571141d88e88a41b65458336341e45d8a1c9d79dc16e8f07f35788125350250cdaf20edabd7cda019767587a61c5aac053ab56924bd58478dab00250ff7adaddacda950e20bdaf202fa8c51415a96815a3096946e195983a6595be96378915baf56cf91d50e7b476b21e89f55512d9a6491a4340033f5398dd48e72d2c3ae85b37be627a781f58439558a5633a9175285ca241250556eef77d22701478d8a59242839762711b721e012f85623e8c7aea6f31678fc9222a980e763b0b2f01e116267491d56172b5a95d1b4dad917d90aa8779014982e7baaf799941f7b00891b682283036e770a0b6c8aa38522647ba739896bcd5792d17397c31f89da66f6504b49d85e371021f7db51f3dba226d34b49e85bfa0bacb7ab6b915417988dad70fb22679ea409702398c26428ab9507283863462398905b38ec26e4b0b226d8429923b51396adf75b5078422553d527d9b6b18ac65c26c83f8a529e23d341a045962a527e20849c26b6ab75ae817a489152a7937a4642078113d7e2b301868c5b367601d88aa8f52b68649b6864ab3671bfd5ec72ba29efa1aa0282b3f6179aa6823a11ae41016eb66f87113d379149339ae85b886a45c07d9de6f760035c065bec70c87b9b113d72f7a01c2b528649f31486368bea5515f9eeb5f96976e404bb11219e1190caa68446b2289e97322ac7cd50a8924689e9452a451428018b95f2b675e187c5347a67aa9054dea14175a0699722160225a94a4b717c799bb75bba5c2a26b597267db2ab95a5950652864282f7bcae19d474c48da96ae1617ae88bcb8cb5211e9347cc994865178b2a5d86382e55deb379c6556a9e41e80aa6885c88788f93f6f2b89b2e7785e6b21155611bf61571678bfa428b001b97823ba7253eb29b2b5f47601aa98350dba34f82a4b9eb48653aef53633cb7bd65e5cb27553f7ce1b57aeb2f8ab965c028931cad3de948715417a896a11e56145706f21ab4c03e7b325dbb40187be4635209ba09debba3c8c385394253f31529d4cef8bb232c607f4b27ac7992b7468f8401e798dbe6cfdb015e246b276cd9b35ad8ad326613985358daf5a0f51f8538f075c2b69d64ec86daa710a32bbea995a339c5604a5282e91225165ca81bee7014d02801ecb6117cb2c6891b7ad913d7649cc94199367984016f9d3116b7a1df9fa5d41df770631a46c7553326f955b556dc527be86cf8a8b5c08da446c938830fca68b757e4df4dea1e47ecfa23015dbbd4ea2da911d1a8f786a0b3aa019c95591e44ca4f5f332885ef29154427e0c04cec2289a93462f7a99b7ac6611e88bb49ba514c9a01f8a72d6d1551a5a7a7d0176a989d791b3a7489760b1e9468b67adb12287c5f59ec1957b90a985a289d188e7a6176c65355cc8321ac2aac13279515889ea91bc96a410a9257e1202b5b61027dcf85d573bc954e0799c4551f75d6683a5c2b51f7d18d6850ba8c99bbc0918abcc1ad7d1a1595e20ca34b2a98019f1a2f9544c83b96b01e195fc70a7e4468edb9765ea57d0a6311e1dd855a880d25532189c389dd4eccfaad72b9da6624d4b8cfcd7c2aadf4e7dee9f75a27a1601117a56c17cae11948f6ce6723b65c966928ad9f57223dabbc619595706817d5655925126848786a29ef614125942670145988be017cb1a0bc4d7ba3de6532392b8fb436672b620037571e63f8f07b374c284a408003f59675fd287b462fca386288faad0532217ad3647bea89c4d527cbb6b352d3dbb242963c2c49a18ad649bc077a1b7483e7a48750030b90113b4ea5418dab39705b412bb649d69c998592ad1e2bfcb75cc796505a2f4a942684eac3121eecd7025aadb12591d6cc902dced6014d586c05286843942631a57d2347ec2930fcaeb0162a7b6681d8dde1c1ad7cb88388cf9cf776dab47e31fa40e4c8da721f7596c9604554ae366fd2933e8ab515cfe95f7653abaef90f550b17b4fcd3a0d4e6a85ab46f31e08bbccf952e9b671507c5babeddddef80136a15a764aa7fa91e40b7479722aab6ad803efdac9661916eb7918f13abc229cb1b68a1e9d69972aaa61a8edbbcb1f0cd06e05f82f0527606d8016785cbf9ea5ccc25ad42dd61298a2d4c2e69d544cca3e6e54ab774cc276a60e1576493a63a8f277cbb882cbe95b375f9307c3deba2b6c5ca6662e3226c5aceeb692702a1a1eaa4ebac7b882d7d49f4493edf58015b8fbdc11125ec88dcd5b595029b1199af7b69d2832212f3e0ab99149a98a3eb07998d7dbc0ac85281095a8dd8f5b9016a01a7cdd6aba98d1aba59cd3b9c27deec91179ad728e601dfe81928c75bbfba7b7c3d1c7fb8cd5966cbf07e2517931e1a50b244a809b3875be0f152141aefcc85a3f5acde4104572d7517083467a0b376b581cf41dfe54ecf8dd18fd819d2fae92784e1e2c86e2415ad3d8b16e0af07706365f3e757cf4db17d9a6692824348e15698a097d3b986da8638b361a8bd5366504a41c8af07716781dce31e78a23545f6eb941e0849d9501cede59b3d4ff859cad488f6da7c1e975a97d49c37462a65a7550894da975a63069cef8740a81d7579fe435df576bed7bde26c158c5ea66a8aeb7b1981fd85aeb6a0f8ced7345258b5f920c0ecc483554160668ad35d354afac07a01386f76476f7f91aafda7a8a68a03f93bd35008138f173017b5250728748ffed952050bf5452cf6c7f845af235545baf57c1188cf6af545e4efca456a0e35cbfdda8798eac3d025a8a30641cc017cf4af6f7337a33b45c70ff7728ff7967a9d5ab501ce72eaf357bf4aa462965e356180776c66cf6c7e837b5ff7afa19a2b6893d356ef001d74911b56ac49513565031624280aaf834e3f0bf444057a49582e3817268a98f0f4114388051224280294e84385055e2c2822712bc18827911389b2916dc79f2d523c6993d02c448b0d5ea42a70d8adc2a44d46a4c9a0362d458bc68efc4a03b4eccc9b2796140982f824d6af317a1d3a039a66ddaa358ad41bb211e050bd35567d0bb0796b53a06f564d8b1656aedaa37baa9d99157c65d0a68b03355a2891f36e973fd236ab27b62147b0499ed519027fe5ef52b857173e89497951d4c96db60d9ad3b85160c097ae168a43f53845d67d5fd48d84d86be09c371fc679725733dfacbb272cecc2783fcac52327f6dc3adaadc6e283a3f59b5bb13e6de97513472f393079de9475af2efd92bfec6fdd9d03b4ab297fa0d2b5a183df9e7990f95ae4e3cf2044feeb8fa04fbe8b4c4da207e3eaa7a0ba8bcf20bade13cac043dafa3e0f340d835f29a8d2abbf6c20e6c3da2db3fc7bf091ccca8affe4c3e04b9caa30f283be0abb1da3ee2934d8cb9beb27c6031d02b9f4041d6dbdc67302b4bccafbee07cafe746d093815e34255a709eaceee24a04bf1d7b60f838052c1d09c6f66c91f8c8caba5e8fb5c6b20d2f33f8742efbca452d5a5ec44fc2543d24b42bca396fc7cc83c07142daec7aebb707943c2f4dfe5c0ecd4947ac3ccd3bc0446fc5c1f62b823ccfc673ce8eb7eefabc63522f4da458cd0745d01c47c223847cb85b9283973f1d6b8c805c474c3072b6d83b10b6c405c3c013511574449ab02985fd4a404d0ca0335c1315fc67a61bad0ec7d26d64629ac907a5cfc05fe69485dc30deaacdc051556c53b5c67b6c5a0d45e2bc54dfaeb43d259adfbc23b6feba11f5957b4b7bcb7acfc12f0508bb538bdb15fe3c35ade2be5c7f16b5d4c8059b033e5dcaf5ae44dab8f5c012594fd488dbd66bb5e3d2e39d36471dba17a453555d43e2e2bd4a7395c511b4471e48dab693befcc59b5f21659571d29773d6b742051b51504a478cb83c4ca4dd8399e053058afa5cf8d4a33bee31dd9ad74503bd6f6940b79cdf24d95dfb4d6cc74d866a82e93314763de06704445c4b0765713dc5a8d580946457f5e57c6cbffbf47ade4fbcb7395b45ceaaf3eb77b3a5515e935d3c1fd16b8efc6ab365a3d67ec0c7fe1c44fa47acf9bd489ff5cb3f4ac3ceddecd32f46dc556a39c4f67579c1540b71fbee7ebe876d29e6f35856c56a7cb6e3f4044b9c682d869df151f047729947475e56396c5184147d3feea79d6f6a5d65f877a93be3bb14cb53cd9616ec7bc267f54ae93ed676fd9f463dfeef2325241e23654e291bd2831521416ea95ebb3f02eefcd7d828d0ed614b0af812e6958f20650dee4fe2c903f0975ca5c1c90e6bba80e2aea4124ee909c386b2b99a5ac4c0c4b0ede25e1ba813c2e6dc3dec374a66320b859a97e8b1b50ac28c821069c253c124a9b78b7234b6dcf8e6504ad9582278cb0254f2c6014d398034513b1a5f8e56fcbff06bc55fc2a71be646d9aef4c03d5cf1a220036859a9719e4c76bbcf520588263b818fc23a2c9590a4d56896e89e6b4cb31c19a0e21a96558ca88ab22c020b37184cc9a52d238ced031765c9281d6c6d5a49e2eefea5bfac953d6766a305d8bce456bcec8d6156c1da938417e33291af072ff214db0bd6e7a44ed09f40ebd3278ef823455642b18544bfd9cefef6fb4635fca179837f960dc221a1a1d2f794c2e89427474b1932bc0b7583cc1101f75a90e92359644ac9df03a8aca076fb4b55db6f87fc498342a12aa442f370a405d8829edd53738e89b2d9d095fa2ee4e0328502afdcc207cead35da2352c2fbd23f972ac4e86fc13d63e21bf656202d3a83755ce4ec14aa58cfc179dbca612b8325b8161b4f2ebda486f105259e19564a4660db50fb0bd52df3e6bee83ba6afd3e3d6e838f1d5654e6b5a3de5ac3f0646b69a9a4d5262a9d1d06953549dc0dd580342592759dd4532bf4d8dfa81a5c07744c4c5fd0565c473e43919c4b64a5c4d2492375b1de79c4fc557ac7773971857a4bb4b317da98714dc8a68666ef9c1aa7d4b877417d70369e4c5e19e29a61520945d845e2bf8d5f677f3be9757744d1d850d8fa5156454f63a60458adea07e51819bb6985f397acfa16fda2a8d1d58a0b3e9537b7295ea20d6c956326abc054da3035a1ba8e03f89cc84b1a5db8239e724d7bee43391657da9d6a876d28d2d4fae2341e045696f99ed2dc4a98cd158ec192b5c3e929448c57a9e6cf950a51995dba58adb9e3f8863405911b5b41d05ae2d5af75c820e4a8d72cad005740e94d11faca42c11117887964b5a121d9bbc67aa2fd97b582238cf7fa5236ac034e94a1e0fa49d7cfe6059ba3daf0a9cc0938d7a59645bf542be339f632bfcac7767e523e17d47894b061d3dbb991e36e917c84c055175ecaa77c729f595c95d403361673e2f0661d152fc08a7876961c726481b554625a09b170c9ac6879eaa36901a5da7e9b8d5fcef4e6908000129f4010a000ff00c2000000000910f4000080ef0059d2318ac80e04385070e1458909022c78c012a3c884172a5c5871b126cd8a1b3a44e8f1d365409325466c0982b46ac39a2b52bc794216a9c894376adc595317adc564c4021b18f35951b283497af40a3078a05f974595055a54b72f44ab479a1d9ae4392156a85f9e6dba14dba559a165be8d6a263a2a53ba6bb2b5ea56ba6bd8b051e25dab06fee752ba7fcab59b673b20ecb281f2fd2cb77de0e3c96307362cf891fb58c395277468891166edca9b337efce93438e1d2ab439e3d6a353ae5daab53be7dea363ce9d2bb63d60d5c4befcddb478ee63a34d7f4de91c3b2fe2efb98f2d4edbd830f5e3cb93374e1d9af178e7d587677eac5bf37fedd9befb4fae8dfbb87be6e7a79f0fae1cf8fdedefcfaf7f9e9cbb74fcedebcfbf3f1f3dfcf25514a3d08e25e450ed4702182392860e2890e38e0648d0e4880a4851258c0e58a166841975a5d78655885498840d88626988228872aa892298c2eb8e26c8b2ac8d2ec8636d8832c873ae8932d8c3ef8e3609b3a09d3e09646198420933265f7954126057555585d39a0508a4d49322496562414159c5949d5669552a8d497915e5916214a529985aa936a95d62557627970989f52a957ab9772d9f59063769967ef917af9b520aa7a0a96ac958e0ab62c99821ac6e3ad8289976e9805e6e1e6801268b9a6a616680a67a1ae7a2a69a4ae9ac92aae96aa93d8855e14efa9978e5545a51da361655c1ea7beda3b6359bacaabadafbe78fb5371cafa745fa7caea3c5da8ca0b9ca3bbc20bac65b4ce4b2d25b9de6bcb27b3c67b6ca5b0ee7b4e64b1ea7b6e69bea6371ba49aae8acaeaa2f2cb3fa9a1f2db8fadb5febbaf6ebf2d5947679c01f76ed954d1475e126cc5474e5e51e1bb707d5ed9372e9b57dd3750ba511b2cf79b7c0f5cc7d3c5cd8708d4c5ce2c5618c60f2642b0790b7582b3ce7d670132c2135c72f7c849aca179cd09da926087f6fb443fb64f0d74feb84f2da473def23d0fa0c6057935fba8c2ab7deea5e66d0d24bc5f3b75b6d0633b2636be220b7ee9df5b7d56b8bb22adb57bd85bcd96fbdb678de5bbd14fefdd467edcda26b0d23c86784390de920cc9a4d81e8891249baa1ea022ea9a2eb123ed9a3ec024e01a4e4025e30a5e6126ef0a3ef66f4735b5e3359cb57c83f8932fc581f6993bfc2653c29dae96abc685dcb3356f2bbec2bde82ece737dea2b5c485bc98dbee62eea7dce91bd5acdc94cf65ab70c337fe7892f9db3432366c3dde0571d3e72df4b3d4e3af6e7af7e7bfce73ba1d2c5ad6d5cadadc627fa2ad7f3cf0fbdf8f71bdfb6acef0085f310eff89450440e003f795b50a69895f0c306abc08b0c90a2052810cb0eefc2811cd0660b388f3e0230348f1c11660f76b51fc4fe2443b12d5ca643e24cc4c0ba62a991a5de3363410a76278c4ad12c0f78ef534022e0588e3c02a1178874c22221798a4c62e66878619571344c22110cc57ca881943954256f5203d61776d5443d71d83164e2d81177ed3336611c8152f2ea19c8d6413eb11d869a632558e8924b3a060f8e6c680713e8a64f32b1304d74d31f15e8284832121196840b4a11e26c2e35ea2e76b28227680881994221fc66a970606a42a0c0b586c3946bcc0e82c6b9c7b572f68781052923353a465288c49c224561193924c649b0f5841c015c2578f241d1a0917d998b061779234b3295eb44bc679321321a9ba1121a9c118d5519a97810d53312915a66ac09b9d0986240d944dc0a9e0bc9319c6664a22cd43c182bd94ecec8433e9911b6e84e720aef892da13f90b458cdc29980935082241c72ddc311736db5b4e0965471f566681a7d2776a1b488c44696b243ffc491241e7dba57a75af035892c20a00500e3473f1201507dd3d0aa2dec464992254e3084f50d703792be233ea465c2db21a0e3c412b0508504d4f340a00920558a9e43b044c879493a2259d4a72755e72c9d29ffd53d328e95943f036835e8c57489c110e9bcc1465567685138ac80583538ab0850c4d8462ec7be1ca622651cca3f58c78710b538ad70fc5442bae29daaf9a121a871c84f0b508a9605a0bd6d0a2f570b275066548f0e8d504a0e4abb49cd3496702aa767b6b74bc9e5805b93ccda4205e9a33c32768977db27ea0b83871aefaa91d0b35056892af042d924f0ba9b74e8655d16fc4f822fc893092c656d4ab550de25f3bd9d59a0807bd851a2431abe8d1aed4fb886be3447b0082a311b0506dac4d013e4140d62196cbb25ceaaadeea99cdb5c5da6bb24d405a6a6fb2dca7d8bf206ac92e500a87b63015b93ac12f2b49011354979d5ad57c2143db303235a713a1da5d905e020dd196f7b7890e192143e9bc8afab614168d0aeb0cca79241ef531339156c4109bcbc44d2ac1c682a45cf095436d3eee25c25b0ed06c7232ee8813df7ce4dbe2047be090582a8d95715c83457c0430d506492358e34859f078d7a6c9e5c591b417e833601ace165aca72f27b51cc0d2f1b3bad202e500eff7944fdb28226ee982535c2061cbb2a1a440570d4603a879a16da17413425fd217987918b5fb80a19cd4905436b6b35298c96f685c483df9f420bd0982abfb67ac072639a621c37835a817174ada43dc707862838a5ae666e602bd7eb4ea4d179953719d4fa8cd73eab25ade5ef924b22d3b58864b3292ddb903b7d6865608264a7053cd57912e4dade15695ec4cc11bd7db24ba96239a171db299dd47ce3c2f1ead8b631362dd52963b67b9fa97a1a47b74aa853fc640d619992eb9cfb0350075354af4d70f941bd13108503d59a29633f2d1dafc09cba6fb32d48e0ad3bad11960598c0b2ed29bddcffef5694ef8a91c77aabf44dd9337a9fce752766aefcf6ac8a0710e2c801cda28ded317bf25bd08ccc5c6f12419f44ccac49174d4cacb329fc9eb2fa7fc0e1edaeaabb559054f168a3332a300502fd6962b1d8d24e204b75576e548447f50db2f4f5ba6e214e476ac8247661a0a1ac5dddd69c7fa8c5c312c6ae594da48286e1319847c5ac171dea7b10aa491e95c21664fa9374e8ed49e3816bda78d92c181421a078b5879c36209636f5024e82f1e5dbd78c24dc79202d204e773230da9214e4135012f1635095035079733e3d3c24ef1ed7049b762dcc651b3d579cac8aca3bdb9c79bde418da24e71449f3d055c883e54c58f6dbc94330a0c770515e579c03255120a8c244d5dcb2e95e34ede09f6be41a6ef012d19afe9f9af92932673ec01397bb7a9241b4a04a8a1aff2f1529fa879a7144bbf2099af47af358354203fa1d55376124a477451287325697b014564084760b57f77772016a02a7c864c0335b86e310459506f71f7985ec3577197797bc07085009505e5171a87325500cd7b26476cf34c58f4747ec7435747c70405f57501bb7366311cf7028e774a39c13089856a07529c7ed7228081d38aa71258500663017c65d5501585f20b16bc01d7595847ad1527387500850977fc5aa7847b917e62d58030a0358e257643475c5126c08401868145241287454a96f206a7485126b75595907801a87d58cb1978611a65595500b06266f85a488f7201350850ef7d7b65950607538fc7922978243838556f78c86396d06a01f78885556397db15165b5b47bc0e07435984601b48c68c916770288c7b68df7e85b51a964052874e7401c85425cf5991a86226a38283a419b83255983b22888275e78853480a3334676276867394b68ac0975058801026e85b97936428e97924341a87ec6c93868350893ac07588459a8ed7e72b48ad70e8ed80f33f7885108261a872505922020e8587463a988d4682d344535011d55988d8e01ac7df8064837e85017806487f20af7081401f187b80931f7e97991ec7da7e17c25501868f48d72ed76a7fd8416c65b00770277ce8a713e85b6103f277362019d8b989644287a05002781b5eef181d5e372041f7625ba6c01a87b97ee55c05565b55413413770e8a97de7d582016b7ad5e95a268856a0711a398f8eb1e390c7b75e65096131e83ba6341b759504c1705f496d7a51dd8d914d5f291344619371787346d8533a962876d5f24e08aa7c294199053523d72381116273b8c47b756d5f37ce5ee2937b00625e83289f352153223d70c7309ee7824d175374a5c898a61172889977d8965ce27577b84340d7cf89f3f18479dc4f09d34f78e52d53676c016b7de5752850885af75922431181d50295473689f3d91b758570d4f09911f58097093be2f09e83287d72005377b24eb8fc75c2eb8b96ee51167c7035cb9b33ca8a47972ac7245b381e890ef8501e29f87236c38885cd5839456c65da95b6ad44c03984d83728988853116a04254e8fc1b47ec7cd5811a980898255a5301b59ee25a8df9f11484f787a06011e8317cf3b694b21e8099271627b00bb8964341a86556c51305ef5ee4f585985e7e850884552b9c651671852f68934285293017d9f204a5939885950296639234950c2a562ce4556845b851e9d2ad525b35b7556847e42a414590a05c113ac657b7776bf8358e51bd5eb52238a9281885d36fd244ace6363d41b65f396c68850171a6924d172f7ff83e7c914e9d85726e46f78967824d26301a986722668d902236a5259562942b7601e20d85d1a2031f7b88422e831f764a0563394552a7ef028d70235d2878a68a337a9634652236a778a01b95bc01e9c0a5a4678d58920cf8038b9ac9a647459a1ac3a785c27fd41f8de91452501f49e9595d27e82d17f0a72a556b17801e240f9ce8122b69992d17f98ec50ba587c995c6552df75c97a6e88b01249834006571141d88e88a41b65458336341e45d8a1c9d79dc16e8f07f35788125350250cdaf20edabd7cda019767587a61c5aac053ab56924bd58478dab00250ff7adaddacda950e20bdaf202fa8c51415a96815a3096946e195983a6595be96378915baf56cf91d50e7b476b21e89f55512d9a6491a4340033f5398dd48e72d2c3ae85b37be627a781f58439558a5633a9175285ca241250556eef77d22701478d8a59242839762711b721e012f85623e8c7aea6f31678fc9222a980e763b0b2f01e116267491d56172b5a95d1b4dad917d90aa8779014982e7baaf799941f7b00891b682283036e770a0b6c8aa38522647ba739896bcd5792d17397c31f89da66f6504b49d85e371021f7db51f3dba226d34b49e85bfa0bacb7ab6b915417988dad70fb22679ea409702398c26428ab9507283863462398905b38ec26e4b0b226d8429923b51396adf75b5078422553d527d9b6b18ac65c26c83f8a529e23d341a045962a527e20849c26b6ab75ae817a489152a7937a4642078113d7e2b301868c5b367601d88aa8f52b68649b6864ab3671bfd5ec72ba29efa1aa0282b3f6179aa6823a11ae41016eb66f87113d379149339ae85b886a45c07d9de6f760035c065bec70c87b9b113d72f7a01c2b528649f31486368bea5515f9eeb5f96976e404bb11219e1190caa68446b2289e97322ac7cd50a8924689e9452a451428018b95f2b675e187c5347a67aa9054dea14175a0699722160225a94a4b717c799bb75bba5c2a26b597267db2ab95a5950652864282f7bcae19d474c48da96ae1617ae88bcb8cb5211e9347cc994865178b2a5d86382e55deb379c6556a9e41e80aa6885c88788f93f6f2b89b2e7785e6b21155611bf61571678bfa428b001b97823ba7253eb29b2b5f47601aa98350dba34f82a4b9eb48653aef53633cb7bd65e5cb27553f7ce1b57aeb2f8ab965c028931cad3de948715417a896a11e56145706f21ab4c03e7b325dbb40187be4635209ba09debba3c8c385394253f31529d4cef8bb232c607f4b27ac7992b7468f8401e798dbe6cfdb015e246b276cd9b35ad8ad326613985358daf5a0f51f8538f075c2b69d64ec86daa710a32bbea995a339c5604a5282e91225165ca81bee7014d02801ecb6117cb2c6891b7ad913d7649cc94199367984016f9d3116b7a1df9fa5d41df770631a46c7553326f955b556dc527be86cf8a8b5c08da446c938830fca68b757e4df4dea1e47ecfa23015dbbd4ea2da911d1a8f786a0b3aa019c95591e44ca4f5f332885ef29154427e0c04cec2289a93462f7a99b7ac6611e88bb49ba514c9a01f8a72d6d1551a5a7a7d0176a989d791b3a7489760b1e9468b67adb12287c5f59ec1957b90a985a289d188e7a6176c65355cc8321ac2aac13279515889ea91bc96a410a9257e1202b5b61027dcf85d573bc954e0799c4551f75d6683a5c2b51f7d18d6850ba8c99bbc0918abcc1ad7d1a1595e20ca34b2a98019f1a2f9544c83b96b01e195fc70a7e4468edb9765ea57d0a6311e1dd855a880d25532189c389dd4eccfaad72b9da6624d4b8cfcd7c2aadf4e7dee9f75a27a1601117a56c17cae11948f6ce6723b65c966928ad9f57223dabbc619595706817d5655925126848786a29ef614125942670145988be017cb1a0bc4d7ba3de6532392b8fb436672b620037571e63f8f07b374c284a408003f59675fd287b462fca386288faad0532217ad3647bea89c4d527cbb6b352d3dbb242963c2c49a18ad649bc077a1b7483e7a48750030b90113b4ea5418dab39705b412bb649d69c998592ad1e2bfcb75cc796505a2f4a942684eac3121eecd7025aadb12591d6cc902dced6014d586c05286843942631a57d2347ec2930fcaeb0162a7b6681d8dde1c1ad7cb88388cf9cf776dab47e31fa40e4c8da721f7596c9604554ae366fd2933e8ab515cfe95f7653abaef90f550b17b4fcd3a0d4e6a85ab46f31e08bbccf952e9b671507c5babeddddef80136a15a764aa7fa91e40b7479722aab6ad803efdac9661916eb7918f13abc229cb1b68a1e9d69972aaa61a8edbbcb1f0cd06e05f82f0527606d8016785cbf9ea5ccc25ad42dd61298a2d4c2e69d544cca3e6e54ab774cc276a60e1576493a63a8f277cbb882cbe95b375f9307c3deba2b6c5ca6662e3226c5aceeb692702a1a1eaa4ebac7b882d7d49f4493edf58015b8fbdc11125ec88dcd5b595029b1199af7b69d2832212f3e0ab99149a98a3eb07998d7dbc0ac85281095a8dd8f5b9016a01a7cdd6aba98d1aba59cd3b9c27deec91179ad728e601dfe81928c75bbfba7b7c3d1c7fb8cd5966cbf07e2517931e1a50b244a809b3875be0f152141aefcc85a3f5acde4104572d7517083467a0b376b581cf41dfe54ecf8dd18fd819d2fae92784e1e2c86e2415ad3d8b16e0af07706365f3e757cf4db17d9a6692824348e15698a097d3b986da8638b361a8bd5366504a41c8af07716781dce31e78a23545f6eb941e0849d9501cede59b3d4ff859cad488f6da7c1e975a97d49c37462a65a7550894da975a63069cef8740a81d7579fe435df576bed7bde26c158c5ea66a8aeb7b1981fd85aeb6a0f8ced7345258b5f920c0ecc483554160668ad35d354afac07a01386f76476f7f91aafda7a8a68a03f93bd35008138f173017b5250728748ffed952050bf5452cf6c7f845af235545baf57c1188cf6af545e4efca456a0e35cbfdda8798eac3d025a8a30641cc017cf4af6f7337a33b45c70ff7728ff7967a9d5ab501ce72eaf357bf4aa462965e356180776c66cf6c7e837b5ff7afa19a2b6893d356ef001d74911b56ac49513565031624280aaf834e3f0bf444057a49582e3817268a98f0f4114388051224280294e84385055e2c2822712bc18827911389b2916dc79f2d523c6993d02c448b0d5ea42a70d8adc2a44d46a4c9a0362d458bc68efc4a03b4eccc9b2796140982f824d6af317a1d3a039a66ddaa358ad41bb211e050bd35567d0bb0796b53a06f564d8b1656aedaa37baa9d99157c65d0a68b03355a2891f36e973fd236ab27b62147b0499ed519027fe5ef52b857173e89497951d4c96db60d9ad3b85160c097ae168a43f53845d67d5fd48d84d86be09c371fc679725733dfacbb272cecc2783fcac52327f6dc3adaadc6e283a3f59b5bb13e6de97513472f393079de9475af2efd92bfec6fdd9d03b4ab297fa0d2b5a183df9e7990f95ae4e3cf2044feeb8fa04fbe8b4c4da207e3eaa7a0ba8bcf20bade13cac043dafa3e0f340d835f29a8d2abbf6c20e6c3da2db3fc7bf091ccca8affe4c3e04b9caa30f283be0abb1da3ee2934d8cb9beb27c6031d02b9f4041d6dbdc67302b4bccafbee07cafe746d093815e34255a709eaceee24a04bf1d7b60f838052c1d09c6f66c91f8c8caba5e8fb5c6b20d2f33f8742efbca452d5a5ec44fc2543d24b42bca396fc7cc83c07142daec7aebb707943c2f4dfe5c0ecd4947ac3ccd3bc0446fc5c1f62b823ccfc673ce8eb7eefabc63522f4da458cd0745d01c47c223847cb85b9283973f1d6b8c805c474c3072b6d83b10b6c405c3c013511574449ab02985fd4a404d0ca0335c1315fc67a61bad0ec7d26d64629ac907a5cfc05fe69485dc30deaacdc051556c53b5c67b6c5a0d45e2bc54dfaeb43d259adfbc23b6feba11f5957b4b7bcb7acfc12f0508bb538bdb15fe3c35ade2be5c7f16b5d4c8059b033e5dcaf5ae44dab8f5c012594fd488dbd66bb5e3d2e39d36471dba17a453555d43e2e2bd4a7395c511b4471e48dab693befcc59b5f21659571d29773d6b742051b51504a478cb83c4ca4dd8399e053058afa5cf8d4a33bee31dd9ad74503bd6f6940b79cdf24d95dfb4d6cc74d866a82e93314763de06704445c4b0765713dc5a8d580946457f5e57c6cbffbf47ade4fbcb7395b45ceaaf3eb77b3a5515e935d3c1fd16b8efc6ab365a3d67ec0c7fe1c44fa47acf9bd489ff5cb3f4ac3ceddecd32f46dc556a39c4f67579c1540b71fbee7ebe876d29e6f35856c56a7cb6e3f4044b9c682d869df151f047729947475e56396c5184147d3feea79d6f6a5d65f877a93be3bb14cb53cd9616ec7bc267f54ae93ed676fd9f463dfeef2325241e23654e291bd2831521416ea95ebb3f02eefcd7d828d0ed614b0af812e6958f20650dee4fe2c903f0975ca5c1c90e6bba80e2aea4124ee909c386b2b99a5ac4c0c4b0ede25e1ba813c2e6dc3dec374a66320b859a97e8b1b50ac28c821069c253c124a9b78b7234b6dcf8e6504ad9582278cb0254f2c6014d398034513b1a5f8e56fcbff06bc55fc2a71be646d9aef4c03d5cf1a220036859a9719e4c76bbcf520588263b818fc23a2c9590a4d56896e89e6b4cb31c19a0e21a96558ca88ab22c020b37184cc9a52d238ced031765c9281d6c6d5a49e2eefea5bfac953d6766a305d8bce456bcec8d6156c1da938417e33291af072ff214db0bd6e7a44ed09f40ebd3278ef823455642b18544bfd9cefef6fb4635fca179837f960dc221a1a1d2f794c2e89427474b1932bc0b7583cc1101f75a90e92359644ac9df03a8aca076fb4b55db6f87fc498342a12aa442f370a405d8829edd53738e89b2d9d095fa2ee4e0328502afdcc207cead35da2352c2fbd23f972ac4e86fc13d63e21bf656202d3a83755ce4ec14aa58cfc179dbca612b8325b8161b4f2ebda486f105259e19564a4660db50fb0bd52df3e6bee83ba6afd3e3d6e838f1d5654e6b5a3de5ac3f0646b69a9a4d5262a9d1d06953549dc0dd580342592759dd4532bf4d8dfa81a5c07744c4c5fd0565c473e43919c4b64a5c4d2492375b1de79c4fc557ac7773971857a4bb4b317da98714dc8a68666ef9c1aa7d4b877417d70369e4c5e19e29a61520945d845e2bf8d5f677f3be9757744d1d850d8fa5156454f63a60458adea07e51819bb6985f397acfa16fda2a8d1d58a0b3e9537b7295ea20d6c956326abc054da3035a1ba8e03f89cc84b1a5db8239e724d7bee43391657da9d6a876d28d2d4fae2341e045696f99ed2dc4a98cd158ec192b5c3e929448c57a9e6cf950a51995dba58adb9e3f8863405911b5b41d05ae2d5af75c820e4a8d72cad005740e94d11faca42c11117887964b5a121d9bbc67aa2fd97b582238cf7fa5236ac034e94a1e0fa49d7cfe6059ba3daf0a9cc0938d7a59645bf542be339f632bfcac7767e523e17d47894b061d3dbb991e36e917c84c055175ecaa77c729f595c95d403361673e2f0661d152fc08a7876961c726481b554625a09b170c9ac6879eaa36901a5da7e9b8d5fcef4e6908000129f4010a000ff00c2000000000910f4000080ef0059d2318ac80e04385070e1458909022c78c012a3c884172a5c5871b126cd8a1b3a44e8f1d365409325466c0982b46ac39a2b52bc794216a9c894376adc595317adc564c4021b18f35951b283497af40a3078a05f974595055a54b72f44ab479a1d9ae4392156a85f9e6dba14dba559a165be8d6a263a2a53ba6bb2b5ea56ba6bd8b051e25dab06fee752ba7fcab59b673b20ecb281f2fd2cb77de0e3c96307362cf891fb58c395277468891166edca9b337efce93438e1d2ab439e3d6a353ae5daab53be7dea363ce9d2bb63d60d5c4befcddb478ee63a34d7f4de91c3b2fe2efb98f2d4edbd830f5e3cb93374e1d9af178e7d587677eac5bf37fedd9befb4fae8dfbb87be6e7a79f0fae1cf8fdedefcfaf7f9e9cbb74fcedebcfbf3f1f3dfcf25514a3d08e25e450ed4702182392860e2890e38e0648d0e4880a4851258c0e58a166841975a5d78655885498840d88626988228872aa892298c2eb8e26c8b2ac8d2ec8636d8832c873ae8932d8c3ef8e3609b3a09d3e09646198420933265f7954126057555585d39a0508a4d49322496562414159c5949d5669552a8d497915e5916214a529985aa936a95d62557627970989f52a957ab9772d9f59063769967ef917af9b520aa7a0a96ac958e0ab62c99821ac6e3ad8289976e9805e6e1e6801268b9a6a616680a67a1ae7a2a69a4ae9ac92aae96aa93d8855e14efa9978e5545a51da361655c1ea7beda3b6359bacaabadafbe78fb5371cafa745fa7caea3c5da8ca0b9ca3bbc20bac65b4ce4b2d25b9de6bcb27b3c67b6ca5b0ee7b4e64b1ea7b6e69bea6371ba49aae8acaeaa2f2cb3fa9a1f2db8fadb5febbaf6ebf2d5947679c01f76ed954d1475e126cc5474e5e51e1bb707d5ed9372e9b57dd3750ba511b2cf79b7c0f5cc7d3c5cd8708d4c5ce2c5618c60f2642b0790b7582b3ce7d670132c2135c72f7c849aca179cd09da926087f6fb443fb64f0d74feb84f2da473def23d0fa0c6057935fba8c2ab7deea5e66d0d24bc5f3b75b6d0633b2636be220b7ee9df5b7d56b8bb22adb57bd85bcd96fbdb678de5bbd14fefdd467edcda26b0d23c86784390de920cc9a4d81e8891249baa1ea022ea9a2eb123ed9a3ec024e01a4e4025e30a5e6126ef0a3ef66f4735b5e3359cb57c83f8932fc581f6993bfc2653c29dae96abc685dcb3356f2bbec2bde82ece737dea2b5c485bc98dbee62eea7dce91bd5acdc94cf65ab70c337fe7892f9db3432366c3dde0571d3e72df4b3d4e3af6e7af7e7bfce73ba1d2c5ad6d5cadadc627fa2ad7f3cf0fbdf8f71bdfb6acef0085f310eff89450440e003f795b50a69895f0c306abc08b0c90a2052810cb0eefc2811cd0660b388f3e0230348f1c11660f76b51fc4fe2443b12d5ca643e24cc4c0ba62a991a5de3363410a76278c4ad12c0f78ef534022e0588e3c02a1178874c22221798a4c62e66878619571344c22110cc57ca881943954256f5203d61776d5443d71d83164e2d81177ed3336611c8152f2ea19c8d6413eb11d869a632558e8924b3a060f8e6c680713e8a64f32b1304d74d31f15e8284832121196840b4a11e26c2e35ea2e76b28227680881994221fc66a970606a42a0c0b586c3946bcc0e82c6b9c7b572f68781052923353a465288c49c224561193924c649b0f5841c015c2578f241d1a0917d998b061779234b3295eb44bc679321321a9ba1121a9c118d5519a97810d53312915a66ac09b9d0986240d944dc0a9e0bc9319c6664a22cd43c182bd94ecec8433e9911b6e84e720aef892da13f90b458cdc29980935082241c72ddc311736db5b4e0965471f566681a7d2776a1b488c44696b243ffc491241e7dba57a75af035892c20a00500e3473f1201507dd3d0aa2dec464992254e3084f50d703792be233ea465c2db21a0e3c412b0508504d4f340a00920558a9e43b044c879493a2259d4a72755e72c9d29ffd53d328e95943f036835e8c57489c110e9bcc1465567685138ac80583538ab0850c4d8462ec7be1ca622651cca3f58c78710b538ad70fc5442bae29daaf9a121a871c84f0b508a9605a0bd6d0a2f570b275066548f0e8d504a0e4abb49cd3496702aa767b6b74bc9e5805b93ccda4205e9a33c32768977db27ea0b83871aefaa91d0b35056892af042d924f0ba9b74e8655d16fc4f822fc893092c656d4ab550de25f3bd9d59a0807bd851a2431abe8d1aed4fb886be3447b0082a311b0506dac4d013e4140d62196cbb25ceaaadeea99cdb5c5da6bb24d405a6a6fb2dca7d8bf206ac92e500a87b63015b93ac12f2b49011354979d5ad57c2143db303235a713a1da5d905e020dd196f7b7890e192143e9bc8afab614168d0aeb0cca79241ef531339156c4109bcbc44d2ac1c682a45cf095436d3eee25c25b0ed06c7232ee8813df7ce4dbe2047be090582a8d95715c83457c0430d506492358e34859f078d7a6c9e5c591b417e833601ace165aca72f27b51cc0d2f1b3bad202e500eff7944fdb28226ee982535c2061cbb2a1a440570d4603a879a16da17413425fd217987918b5fb80a19cd4905436b6b35298c96f685c483df9f420bd0982abfb67ac072639a621c37835a817174ada43dc707862838a5ae666e602bd7eb4ea4d179953719d4fa8cd73eab25ade5ef924b22d3b58864b3292ddb903b7d6865608264a7053cd57912e4dade15695ec4cc11bd7db24ba96239a171db299dd47ce3c2f1ead8b631362dd52963b67b9fa97a1a47b74aa853fc640d619992eb9cfb0350075354af4d70f941bd13108503d59a29633f2d1dafc09cba6fb32d48e0ad3bad11960598c0b2ed29bddcffef5694ef8a91c77aabf44dd9337a9fce752766aefcf6ac8a0710e2c801cda28ded317bf25bd08ccc5c6f12419f44ccac49174d4cacb329fc9eb2fa7fc0e1edaeaabb559054f168a3332a300502fd6962b1d8d24e204b75576e548447f50db2f4f5ba6e214e476ac8247661a0a1ac5dddd69c7fa8c5c312c6ae594da48286e1319847c5ac171dea7b10aa491e95c21664fa9374e8ed49e3816bda78d92c181421a078b5879c36209636f5024e82f1e5dbd78c24dc79202d204e773230da9214e4135012f1635095035079733e3d3c24ef1ed7049b762dcc651b3d579cac8aca3bdb9c79bde418da24e71449f3d055c883e54c58f6dbc94330a0c770515e579c03255120a8c244d5dcb2e95e34ede09f6be41a6ef012d19afe9f9af92932673ec01397bb7a9241b4a04a8a1aff2f1529fa879a7144bbf2099af47af358354203fa1d55376124a477451287325697b014564084760b57f77772016a02a7c864c0335b86e310459506f71f7985ec3577197797bc07085009505e5171a87325500cd7b26476cf34c58f4747ec7435747c70405f57501bb7366311cf7028e774a39c13089856a07529c7ed7228081d38aa71258500663017c65d5501585f20b16bc01d7595847ad1527387500850977fc5aa7847b917e62d58030a0358e257643475c5126c08401868145241287454a96f206a7485126b75595907801a87d58cb1978611a65595500b06266f85a488f7201350850ef7d7b65950607538fc7922978243838556f78c86396d06a01f78885556397db15165b5b47bc0e07435984601b48c68c916770288c7b68df7e85b51a964052874e7401c85425cf5991a86226a38283a419b83255983b22888275e78853480a3334676276867394b68ac0975058801026e85b97936428e97924341a87ec6c93868350893ac07588459a8ed7e72b48ad70e8ed80f33f7885108261a872505922020e8587463a988d4682d344535011d55988d8e01ac7df8064837e85017806487f20af7081401f187b80931f7e97991ec7da7e17c25501868f48d72ed76a7fd8416c65b00770277ce8a713e85b6103f277362019d8b989644287a05002781b5eef181d5e372041f7625ba6c01a87b97ee55c05565b55413413770e8a97de7d582016b7ad5e95a268856a0711a398f8eb1e390c7b75e65096131e83ba6341b759504c1705f496d7a51dd8d914d5f291344619371787346d8533a962876d5f24e08aa7c294199053523d72381116273b8c47b756d5f37ce5ee2937b00625e83289f352153223d70c7309ee7824d175374a5c898a61172889977d8965ce27577b84340d7cf89f3f18479dc4f09d34f78e52d53676c016b7de5752850885af75922431181d50295473689f3d91b758570d4f09911f58097093be2f09e83287d72005377b24eb8fc75c2eb8b96ee51167c7035cb9b33ca8a47972ac7245b381e890ef8501e29f87236c38885cd5839456c65da95b6ad44c03984d83728988853116a04254e8fc1b47ec7cd5811a980898255a5301b59ee25a8df9f11484f787a06011e8317cf3b694b21e8099271627b00bb8964341a86556c51305ef5ee4f585985e7e850884552b9c651671852f68934285293017d9f204a5939885950296639234950c2a562ce4556845b851e9d2ad525b35b7556847e42a414590a05c113ac657b7776bf8358e51bd5eb52238a9281885d36fd244ace6363d41b65f396c68850171a6924d172f7ff83e7c914e9d85726e46f78967824d26301a986722668d902236a5259562942b7601e20d85d1a2031f7b88422e831f764a0563394552a7ef028d70235d2878a68a337a9634652236a778a01b95bc01e9c0a5a4678d58920cf8038b9ac9a647459a1ac3a785c27fd41f8de91452501f49e9595d27e82d17f0a72a556b17801e240f9ce8122b69992d17f98ec50ba587c995c6552df75c97a6e88b01249834006571141d88e88a41b65458336341e45d8a1c9d79dc16e8f07f35788125350250cdaf20edabd7cda019767587a61c5aac053ab56924bd58478dab00250ff7adaddacda950e20bdaf202fa8c51415a96815a3096946e195983a6595be96378915baf56cf91d50e7b476b21e89f55512d9a6491a4340033f5398dd48e72d2c3ae85b37be627a781f58439558a5633a9175285ca241250556eef77d22701478d8a59242839762711b721e012f85623e8c7aea6f31678fc9222a980e763b0b2f01e116267491d56172b5a95d1b4dad917d90aa8779014982e7baaf799941f7b00891b682283036e770a0b6c8aa38522647ba739896bcd5792d17397c31f89da66f6504b49d85e371021f7db51f3dba226d34b49e85bfa0bacb7ab6b915417988dad70fb22679ea409702398c26428ab9507283863462398905b38ec26e4b0b226d8429923b51396adf75b5078422553d527d9b6b18ac65c26c83f8a529e23d341a045962a527e20849c26b6ab75ae817a489152a7937a4642078113d7e2b301868c5b367601d88aa8f52b68649b6864ab3671bfd5ec72ba29efa1aa0282b3f6179aa6823a11ae41016eb66f87113d379149339ae85b886a45c07d9de6f760035c065bec70c87b9b113d72f7a01c2b528649f31486368bea5515f9eeb5f96976e404bb11219e1190caa68446b2289e97322ac7cd50a8924689e9452a451428018b95f2b675e187c5347a67aa9054dea14175a0699722160225a94a4b717c799bb75bba5c2a26b597267db2ab95a5950652864282f7bcae19d474c48da96ae1617ae88bcb8cb5211e9347cc994865178b2a5d86382e55deb379c6556a9e41e80aa6885c88788f93f6f2b89b2e7785e6b21155611bf61571678bfa428b001b97823ba7253eb29b2b5f47601aa98350dba34f82a4b9eb48653aef53633cb7bd65e5cb27553f7ce1b57aeb2f8ab965c028931cad3de948715417a896a11e56145706f21ab4c03e7b325dbb40187be4635209ba09debba3c8c385394253f31529d4cef8bb232c607f4b27ac7992b7468f8401e798dbe6cfdb015e246b276cd9b35ad8ad326613985358daf5a0f51f8538f075c2b69d64ec86daa710a32bbea995a339c5604a5282e91225165ca81bee7014d02801ecb6117cb2c6891b7ad913d7649cc94199367984016f9d3116b7a1df9fa5d41df770631a46c7553326f955b556dc527be86cf8a8b5c08da446c938830fca68b757e4df4dea1e47ecfa23015dbbd4ea2da911d1a8f786a0b3aa019c95591e44ca4f5f332885ef29154427e0c04cec2289a93462f7a99b7ac6611e88bb49ba514c9a01f8a72d6d1551a5a7a7d0176a989d791b3a7489760b1e9468b67adb12287c5f59ec1957b90a985a289d188e7a6176c65355cc8321ac2aac13279515889ea91bc96a410a9257e1202b5b61027dcf85d573bc954e0799c4551f75d6683a5c2b51f7d18d6850ba8c99bbc0918abcc1ad7d1a1595e20ca34b2a98019f1a2f9544c83b96b01e195fc70a7e4468edb9765ea57d0a6311e1dd855a880d25532189c389dd4eccfaad72b9da6624d4b8cfcd7c2aadf4e7dee9f75a27a1601117a56c17cae11948f6ce6723b65c966928ad9f57223dabbc619595706817d5655925126848786a29ef614125942670145988be017cb1a0bc4d7ba3de6532392b8fb436672b620037571e63f8f07b374c284a408003f59675fd287b462fca386288faad0532217ad3647bea89c4d527cbb6b352d3dbb242963c2c49a18ad649bc077a1b7483e7a48750030b90113b4ea5418dab39705b412bb649d69c998592ad1e2bfcb75cc796505a2f4a942684eac3121eecd7025aadb12591d6cc902dced6014d586c05286843942631a57d2347ec2930fcaeb0162a7b6681d8dde1c1ad7cb88388cf9cf776dab47e31fa40e4c8da721f7596c9604554ae366fd2933e8ab515cfe95f7653abaef90f550b17b4fcd3a0d4e6a85ab46f31e08bbccf952e9b671507c5babeddddef80136a15a764aa7fa91e40b7479722aab6ad803efdac9661916eb7918f13abc229cb1b68a1e9d69972aaa61a8edbbcb1f0cd06e05f82f0527606d8016785cbf9ea5ccc25ad42dd61298a2d4c2e69d544cca3e6e54ab774cc276a60e1576493a63a8f277cbb882cbe95b375f9307c3deba2b6c5ca6662e3226c5aceeb692702a1a1eaa4ebac7b882d7d49f4493edf58015b8fbdc11125ec88dcd5b595029b1199af7b69d2832212f3e0ab99149a98a3eb07998d7dbc0ac85281095a8dd8f5b9016a01a7cdd6aba98d1aba59cd3b9c27deec91179ad728e601dfe81928c75bbfba7b7c3d1c7fb8cd5966cbf07e2517931e1a50b244a809b3875be0f152141aefcc85a3f5acde4104572d7517083467a0b376b581cf41dfe54ecf8dd18fd819d2fae92784e1e2c86e2415ad3d8b16e0af07706365f3e757cf4db17d9a6692824348e15698a097d3b986da8638b361a8bd5366504a41c8af07716781dce31e78a23545f6eb941e0849d9501cede59b3d4ff859cad488f6da7c1e975a97d49c37462a65a7550894da975a63069cef8740a81d7579fe435df576bed7bde26c158c5ea66a8aeb7b1981fd85aeb6a0f8ced7345258b5f920c0ecc483554160668ad35d354afac07a01386f76476f7f91aafda7a8a68a03f93bd35008138f173017b5250728748ffed952050bf5452cf6c7f845af235545baf57c1188cf6af545e4efca456a0e35cbfdda8798eac3d025a8a30641cc017cf4af6f7337a33b45c70ff7728ff7967a9d5ab501ce72eaf357bf4aa462965e356180776c66cf6c7e837b5ff7afa19a2b6893d356ef001d74911b56ac49513565031624280aaf834e3f0bf444057a49582e3817268a98f0f4114388051224280294e84385055e2c2822712bc18827911389b2916dc79f2d523c6993d02c448b0d5ea42a70d8adc2a44d46a4c9a0362d458bc68efc4a03b4eccc9b2796140982f824d6af317a1d3a039a66ddaa358ad41bb211e050bd35567d0bb0796b53a06f564d8b1656aedaa37baa9d99157c65d0a68b03355a2891f36e973fd236ab27b62147b0499ed519027fe5ef52b857173e89497951d4c96db60d9ad3b85160c097ae168a43f53845d67d5fd48d84d86be09c371fc679725733dfacbb272cecc2783fcac52327f6dc3adaadc6e283a3f59b5bb13e6de97513472f393079de9475af2efd92bfec6fdd9d03b4ab297fa0d2b5a183df9e7990f95ae4e3cf2044feeb8fa04fbe8b4c4da207e3eaa7a0ba8bcf20bade13cac043dafa3e0f340d835f29a8d2abbf6c20e6c3da2db3fc7bf091ccca8affe4c3e04b9caa30f283be0abb1da3ee2934d8cb9beb27c6031d02b9f4041d6dbdc67302b4bccafbee07cafe746d093815e34255a709eaceee24a04bf1d7b60f838052c1d09c6f66c91f8c8caba5e8fb5c6b20d2f33f8742efbca452d5a5ec44fc2543d24b42bca396fc7cc83c07142daec7aebb707943c2f4dfe5c0ecd4947ac3ccd3bc0446fc5c1f62b823ccfc673ce8eb7eefabc63522f4da458cd0745d01c47c223847cb85b9283973f1d6b8c805c474c3072b6d83b10b6c405c3c013511574449ab02985fd4a404d0ca0335c1315fc67a61bad0ec7d26d64629ac907a5cfc05fe69485dc30deaacdc051556c53b5c67b6c5a0d45e2bc54dfaeb43d259adfbc23b6feba11f5957b4b7bcb7acfc12f0508bb538bdb15fe3c35ade2be5c7f16b5d4c8059b033e5dcaf5ae44dab8f5c012594fd488dbd66bb5e3d2e39d36471dba17a453555d43e2e2bd4a7395c511b4471e48dab693befcc59b5f21659571d29773d6b742051b51504a478cb83c4ca4dd8399e053058afa5cf8d4a33bee31dd9ad74503bd6f6940b79cdf24d95dfb4d6cc74d866a82e93314763de06704445c4b0765713dc5a8d580946457f5e57c6cbffbf47ade4fbcb7395b45ceaaf3eb77b3a5515e935d3c1fd16b8efc6ab365a3d67ec0c7fe1c44fa47acf9bd489ff5cb3f4ac3ceddecd32f46dc556a39c4f67579c1540b71fbee7ebe876d29e6f35856c56a7cb6e3f4044b9c682d869df151f047729947475e56396c5184147d3feea79d6f6a5d65f877a93be3bb14cb53cd9616ec7bc267f54ae93ed676fd9f463dfeef2325241e23654e291bd2831521416ea95ebb3f02eefcd7d828d0ed614b0af812e6958f20650dee4fe2c903f0975ca5c1c90e6bba80e2aea4124ee909c386b2b99a5ac4c0c4b0ede25e1ba813c2e6dc3dec374a66320b859a97e8b1b50ac28c821069c253c124a9b78b7234b6dcf8e6504ad9582278cb0254f2c6014d398034513b1a5f8e56fcbff06bc55fc2a71be646d9aef4c03d5cf1a220036859a9719e4c76bbcf520588263b818fc23a2c9590a4d56896e89e6b4cb31c19a0e21a96558ca88ab22c020b37184cc9a52d238ced031765c9281d6c6d5a49e2eefea5bfac953d6766a305d8bce456bcec8d6156c1da938417e33291af072ff214db0bd6e7a44ed09f40ebd3278ef823455642b18544bfd9cefef6fb4635fca179837f960dc221a1a1d2f794c2e89427474b1932bc0b7583cc1101f75a90e92359644ac9df03a8aca076fb4b55db6f87fc498342a12aa442f370a405d8829edd53738e89b2d9d095fa2ee4e0328502afdcc207cead35da2352c2fbd23f972ac4e86fc13d63e21bf656202d3a83755ce4ec14aa58cfc179dbca612b8325b8161b4f2ebda486f105259e19564a4660db50fb0bd52df3e6bee83ba6afd3e3d6e838f1d5654e6b5a3de5ac3f0646b69a9a4d5262a9d1d06953549dc0dd580342592759dd4532bf4d8dfa81a5c07744c4c5fd0565c473e43919c4b64a5c4d2492375b1de79c4fc557ac7773971857a4bb4b317da98714dc8a68666ef9c1aa7d4b877417d70369e4c5e19e29a61520945d845e2bf8d5f677f3be9757744d1d850d8fa5156454f63a60458adea07e51819bb6985f397acfa16fda2a8d1d58a0b3e9537b7295ea20d6c956326abc054da3035a1ba8e03f89cc84b1a5db8239e724d7bee43391657da9d6a876d28d2d4fae2341e045696f99ed2dc4a98cd158ec192b5c3e929448c57a9e6cf950a51995dba58adb9e3f8863405911b5b41d05ae2d5af75c820e4a8d72cad005740e94d11faca42c11117887964b5a121d9bbc67aa2fd97b582238cf7fa5236ac034e94a1e0fa49d7cfe6059ba3daf0a9cc0938d7a59645bf542be339f632bfcac7767e523e17d47894b061d3dbb991e36e917c84c055175ecaa77c729f595c95d403361673e2f0661d152fc08a7876961c726481b554625a09b170c9ac6879eaa36901a5da7e9b8d5fcef4e6908000129f4010a000ff00c2000000000910f4000080ef0059d2318ac80e04385070e1458909022c78c012a3c884172a5c5871b126cd8a1b3a44e8f1d365409325466c0982b46ac39a2b52bc794216a9c894376adc595317adc564c4021b18f35951b283497af40a3078a05f974595055a54b72f44ab479a1d9ae4392156a85f9e6dba14dba559a165be8d6a263a2a53ba6bb2b5ea56ba6bd8b051e25dab06fee752ba7fcab59b673b20ecb281f2fd2cb77de0e3c96307362cf891fb58c395277468891166edca9b337efce93438e1d2ab439e3d6a353ae5daab53be7dea363ce9d2bb63d60d5c4befcddb478ee63a34d7f4de91c3b2fe2efb98f2d4edbd830f5e3cb93374e1d9af178e7d587677eac5bf37fedd9befb4fae8dfbb87be6e7a79f0fae1cf8fdedefcfaf7f9e9cbb74fcedebcfbf3f1f3dfcf25514a3d08e25e450ed4702182392860e2890e38e0648d0e4880a4851258c0e58a166841975a5d78655885498840d88626988228872aa892298c2eb8e26c8b2ac8d2ec8636d8832c873ae8932d8c3ef8e3609b3a09d3e09646198420933265f7954126057555585d39a0508a4d49322496562414159c5949d5669552a8d497915e5916214a529985aa936a95d62557627970989f52a957ab9772d9f59063769967ef917af9b520aa7a0a96ac958e0ab62c99821ac6e3ad8289976e9805e6e1e6801268b9a6a616680a67a1ae7a2a69a4ae9ac92aae96aa93d8855e14efa9978e5545a51da361655c1ea7beda3b6359bacaabadafbe78fb5371cafa745fa7caea3c5da8ca0b9ca3bbc20bac65b4ce4b2d25b9de6bcb27b3c67b6ca5b0ee7b4e64b1ea7b6e69bea6371ba49aae8acaeaa2f2cb3fa9a1f2db8fadb5febbaf6ebf2d5947679c01f76ed954d1475e126cc5474e5e51e1bb707d5ed9372e9b57dd3750ba511b2cf79b7c0f5cc7d3c5cd8708d4c5ce2c5618c60f2642b0790b7582b3ce7d670132c2135c72f7c849aca179cd09da926087f6fb443fb64f0d74feb84f2da473def23d0fa0c6057935fba8c2ab7deea5e66d0d24bc5f3b75b6d0633b2636be220b7ee9df5b7d56b8bb22adb57bd85bcd96fbdb678de5bbd14fefdd467edcda26b0d23c86784390de920cc9a4d81e8891249baa1ea022ea9a2eb123ed9a3ec024e01a4e4025e30a5e6126ef0a3ef66f4735b5e3359cb57c83f8932fc581f6993bfc2653c29dae96abc685dcb3356f2bbec2bde82ece737dea2b5c485bc98dbee62eea7dce91bd5acdc94cf65ab70c337fe7892f9db3432366c3dde0571d3e72df4b3d4e3af6e7af7e7bfce73ba1d2c5ad6d5cadadc627fa2ad7f3cf0fbdf8f71bdfb6acef0085f310eff89450440e003f795b50a69895f0c306abc08b0c90a2052810cb0eefc2811cd0660b388f3e0230348f1c11660f76b51fc4fe2443b12d5ca643e24cc4c0ba62a991a5de3363410a76278c4ad12c0f78ef534022e0588e3c02a1178874c22221798a4c62e66878619571344c22110cc57ca881943954256f5203d61776d5443d71d83164e2d81177ed3336611c8152f2ea19c8d6413eb11d869a632558e8924b3a060f8e6c680713e8a64f32b1304d74d31f15e8284832121196840b4a11e26c2e35ea2e76b28227680881994221fc66a970606a42a0c0b586c3946bcc0e82c6b9c7b572f68781052923353a465288c49c224561193924c649b0f5841c015c2578f241d1a0917d998b061779234b3295eb44bc679321321a9ba1121a9c118d5519a97810d53312915a66ac09b9d0986240d944dc0a9e0bc9319c6664a22cd43c182bd94ecec8433e9911b6e84e720aef892da13f90b458cdc29980935082241c72ddc311736db5b4e0965471f566681a7d2776a1b488c44696b243ffc491241e7dba57a75af035892c20a00500e3473f1201507dd3d0aa2dec464992254e3084f50d703792be233ea465c2db21a0e3c412b0508504d4f340a00920558a9e43b044c879493a2259d4a72755e72c9d29ffd53d328e95943f036835e8c57489c110e9bcc1465567685138ac80583538ab0850c4d8462ec7be1ca622651cca3f58c78710b538ad70fc5442bae29daaf9a121a871c84f0b508a9605a0bd6d0a2f570b275066548f0e8d504a0e4abb49cd3496702aa767b6b74bc9e5805b93ccda4205e9a33c32768977db27ea0b83871aefaa91d0b35056892af042d924f0ba9b74e8655d16fc4f822fc893092c656d4ab550de25f3bd9d59a0807bd851a2431abe8d1aed4fb886be3447b0082a311b0506dac4d013e4140d62196cbb25ceaaadeea99cdb5c5da6bb24d405a6a6fb2dca7d8bf206ac92e500a87b63015b93ac12f2b49011354979d5ad57c2143db303235a713a1da5d905e020dd196f7b7890e192143e9bc8afab614168d0aeb0cca79241ef531339156c4109bcbc44d2ac1c682a45cf095436d3eee25c25b0ed06c7232ee8813df7ce4dbe2047be090582a8d95715c83457c0430d506492358e34859f078d7a6c9e5c591b417e833601ace165aca72f27b51cc0d2f1b3bad202e500eff7944fdb28226ee982535c2061cbb2a1a440570d4603a879a16da17413425fd217987918b5fb80a19cd4905436b6b35298c96f685c483df9f420bd0982abfb67ac072639a621c37835a817174ada43dc707862838a5ae666e602bd7eb4ea4d179953719d4fa8cd73eab25ade5ef924b22d3b58864b3292ddb903b7d6865608264a7053cd57912e4dade15695ec4cc11bd7db24ba96239a171db299dd47ce3c2f1ead8b631362dd52963b67b9fa97a1a47b74aa853fc640d619992eb9cfb0350075354af4d70f941bd13108503d59a29633f2d1dafc09cba6fb32d48e0ad3bad11960598c0b2ed29bddcffef5694ef8a91c77aabf44dd9337a9fce752766aefcf6ac8a0710e2c801cda28ded317bf25bd08ccc5c6f12419f44ccac49174d4cacb329fc9eb2fa7fc0e1edaeaabb559054f168a3332a300502fd6962b1d8d24e204b75576e548447f50db2f4f5ba6e214e476ac8247661a0a1ac5dddd69c7fa8c5c312c6ae594da48286e1319847c5ac171dea7b10aa491e95c21664fa9374e8ed49e3816bda78d92c181421a078b5879c36209636f5024e82f1e5dbd78c24dc79202d204e773230da9214e4135012f1635095035079733e3d3c24ef1ed7049b762dcc651b3d579cac8aca3bdb9c79bde418da24e71449f3d055c883e54c58f6dbc94330a0c770515e579c03255120a8c244d5dcb2e95e34ede09f6be41a6ef012d19afe9f9af92932673ec01397bb7a9241b4a04a8a1aff2f1529fa879a7144bbf2099af47af358354203fa1d55376124a477451287325697b014564084760b57f77772016a02a7c864c0335b86e310459506f71f7985ec3577197797bc07085009505e5171a87325500cd7b26476cf34c58f4747ec7435747c70405f57501bb7366311cf7028e774a39c13089856a07529c7ed7228081d38aa71258500663017c65d5501585f20b16bc01d7595847ad1527387500850977fc5aa7847b917e62d58030a0358e257643475c5126c08401868145241287454a96f206a7485126b75595907801a87d58cb1978611a65595500b06266f85a488f7201350850ef7d7b65950607538fc7922978243838556f78c86396d06a01f78885556397db15165b5b47bc0e07435984601b48c68c916770288c7b68df7e85b51a964052874e7401c85425cf5991a86226a38283a419b83255983b22888275e78853480a3334676276867394b68ac0975058801026e85b97936428e97924341a87ec6c93868350893ac07588459a8ed7e72b48ad70e8ed80f33f7885108261a872505922020e8587463a988d4682d344535011d55988d8e01ac7df8064837e85017806487f20af7081401f187b80931f7e97991ec7da7e17c25501868f48d72ed76a7fd8416c65b00770277ce8a713e85b6103f277362019d8b989644287a05002781b5eef181d5e372041f7625ba6c01a87b97ee55c05565b55413413770e8a97de7d582016b7ad5e95a268856a0711a398f8eb1e390c7b75e65096131e83ba6341b759504c1705f496d7a51dd8d914d5f291344619371787346d8533a962876d5f24e08aa7c294199053523d72381116273b8c47b756d5f37ce5ee2937b00625e83289f352153223d70c7309ee7824d175374a5c898a61172889977d8965ce27577b84340d7cf89f3f18479dc4f09d34f78e52d53676c016b7de5752850885af75922431181d50295473689f3d91b758570d4f09911f58097093be2f09e83287d72005377b24eb8fc75c2eb8b96ee51167c7035cb9b33ca8a47972ac7245b381e890ef8501e29f87236c38885cd5839456c65da95b6ad44c03984d83728988853116a04254e8fc1b47ec7cd5811a980898255a5301b59ee25a8df9f11484f787a06011e8317cf3b694b21e8099271627b00bb8964341a86556c51305ef5ee4f585985e7e850884552b9c651671852f68934285293017d9f204a5939885950296639234950c2a562ce4556845b851e9d2ad525b35b7556847e42a414590a05c113ac657b7776bf8358e51bd5eb52238a9281885d36fd244ace6363d41b65f396c68850171a6924d172f7ff83e7c914e9d85726e46f78967824d26301a986722668d902236a5259562942b7601e20d85d1a2031f7b88422e831f764a0563394552a7ef028d70235d2878a68a337a9634652236a778a01b95bc01e9c0a5a4678d58920cf8038b9ac9a647459a1ac3a785c27fd41f8de91452501f49e9595d27e82d17f0a72a556b17801e240f9ce8122b69992d17f98ec50ba587c995c6552df75c97a6e88b01249834006571141d88e88a41b65458336341e45d8a1c9d79dc16e8f07f35788125350250cdaf20edabd7cda019767587a61c5aac053ab56924bd58478dab00250ff7adaddacda950e20bdaf202fa8c51415a96815a3096946e195983a6595be96378915baf56cf91d50e7b476b21e89f55512d9a6491a4340033f5398dd48e72d2c3ae85b37be627a781f58439558a5633a9175285ca241250556eef77d22701478d8a59242839762711b721e012f85623e8c7aea6f31678fc9222a980e763b0b2f01e116267491d56172b5a95d1b4dad917d90aa8779014982e7baaf799941f7b00891b682283036e770a0b6c8aa38522647ba739896bcd5792d17397c31f89da66f6504b49d85e371021f7db51f3dba226d34b49e85bfa0bacb7ab6b915417988dad70fb22679ea409702398c26428ab9507283863462398905b38ec26e4b0b226d8429923b51396adf75b5078422553d527d9b6b18ac65c26c83f8a529e23d341a045962a527e20849c26b6ab75ae817a489152a7937a4642078113d7e2b301868c5b367601d88aa8f52b68649b6864ab3671bfd5ec72ba29efa1aa0282b3f6179aa6823a11ae41016eb66f87113d379149339ae85b886a45c07d9de6f760035c065bec70c87b9b113d72f7a01c2b528649f31486368bea5515f9eeb5f96976e404bb11219e1190caa68446b2289e97322ac7cd50a8924689e9452a451428018b95f2b675e187c5347a67aa9054dea14175a0699722160225a94a4b717c799bb75bba5c2a26b597267db2ab95a5950652864282f7bcae19d474c48da96ae1617ae88bcb8cb5211e9347cc994865178b2a5d86382e55deb379c6556a9e41e80aa6885c88788f93f6f2b89b2e7785e6b21155611bf61571678bfa428b001b97823ba7253eb29b2b5f47601aa98350dba34f82a4b9eb48653aef53633cb7bd65e5cb27553f7ce1b57aeb2f8ab965c028931cad3de948715417a896a11e56145706f21ab4c03e7b325dbb40187be4635209ba09debba3c8c385394253f31529d4cef8bb232c607f4b27ac7992b7468f8401e798dbe6cfdb015e246b276cd9b35ad8ad326613985358daf5a0f51f8538f075c2b69d64ec86daa710a32bbea995a339c5604a5282e91225165ca81bee7014d02801ecb6117cb2c6891b7ad913d7649cc94199367984016f9d3116b7a1df9fa5d41df770631a46c7553326f955b556dc527be86cf8a8b5c08da446c938830fca68b757e4df4dea1e47ecfa23015dbbd4ea2da911d1a8f786a0b3aa019c95591e44ca4f5f332885ef29154427e0c04cec2289a93462f7a99b7ac6611e88bb49ba514c9a01f8a72d6d1551a5a7a7d0176a989d791b3a7489760b1e9468b67adb12287c5f59ec1957b90a985a289d188e7a6176c65355cc8321ac2aac13279515889ea91bc96a410a9257e1202b5b61027dcf85d573bc954e0799c4551f75d6683a5c2b51f7d18d6850ba8c99bbc0918abcc1ad7d1a1595e20ca34b2a98019f1a2f9544c83b96b01e195fc70a7e4468edb9765ea57d0a6311e1dd855a880d25532189c389dd4eccfaad72b9da6624d4b8cfcd7c2aadf4e7dee9f75a27a1601117a56c17cae11948f6ce6723b65c966928ad9f57223dabbc619595706817d5655925126848786a29ef614125942670145988be017cb1a0bc4d7ba3de6532392b8fb436672b620037571e63f8f07b374c284a408003f59675fd287b462fca386288faad0532217ad3647bea89c4d527cbb6b352d3dbb242963c2c49a18ad649bc077a1b7483e7a48750030b90113b4ea5418dab39705b412bb649d69c998592ad1e2bfcb75cc796505a2f4a942684eac3121eecd7025aadb12591d6cc902dced6014d586c05286843942631a57d2347ec2930fcaeb0162a7b6681d8dde1c1ad7cb88388cf9cf776dab47e31fa40e4c8da721f7596c9604554ae366fd2933e8ab515cfe95f7653abaef90f550b17b4fcd3a0d4e6a85ab46f31e08bbccf952e9b671507c5babeddddef80136a15a764aa7fa91e40b7479722aab6ad803efdac9661916eb7918f13abc229cb1b68a1e9d69972aaa61a8edbbcb1f0cd06e05f82f0527606d8016785cbf9ea5ccc25ad42dd61298a2d4c2e69d544cca3e6e54ab774cc276a60e1576493a63a8f277cbb882cbe95b375f9307c3deba2b6c5ca6662e3226c5aceeb692702a1a1eaa4ebac7b882d7d49f4493edf58015b8fbdc11125ec88dcd5b595029b1199af7b69d2832212f3e0ab99149a98a3eb07998d7dbc0ac85281095a8dd8f5b9016a01a7cdd6aba98d1aba59cd3b9c27deec91179ad728e601dfe81928c75bbfba7b7c3d1c7fb8cd5966cbf07e2517931e1a50b244a809b3875be0f152141aefcc85a3f5acde4104572d7517083467a0b376b581cf41dfe54ecf8dd18fd819d2fae92784e1e2c86e2415ad3d8b16e0af07706365f3e757cf4db17d9a6692824348e15698a097d3b986da8638b361a8bd5366504a41c8af07716781dce31e78a23545f6eb941e0849d9501cede59b3d4ff859cad488f6da7c1e975a97d49c37462a65a7550894da975a63069cef8740a81d7579fe435df576bed7bde26c158c5ea66a8aeb7b1981fd85aeb6a0f8ced7345258b5f920c0ecc483554160668ad35d354afac07a01386f76476f7f91aafda7a8a68a03f93bd35008138f173017b5250728748ffed952050bf5452cf6c7f845af235545baf57c1188cf6af545e4efca456a0e35cbfdda8798eac3d025a8a30641cc017cf4af6f7337a33b45c70ff7728ff7967a9d5ab501ce72eaf357bf4aa462965e356180776c66cf6c7e837b5ff7afa19a2b6893d356ef001d74911b56ac49513565031624280aaf834e3f0bf444057a49582e3817268a98f0f4114388051224280294e84385055e2c2822712bc18827911389b2916dc79f2d523c6993d02c448b0d5ea42a70d8adc2a44d46a4c9a0362d458bc68efc4a03b4eccc9b2796140982f824d6af317a1d3a039a66ddaa358ad41bb211e050bd35567d0bb0796b53a06f564d8b1656aedaa37baa9d99157c65d0a68b03355a2891f36e973fd236ab27b62147b0499ed519027fe5ef52b857173e89497951d4c96db60d9ad3b85160c097ae168a43f53845d67d5fd48d84d86be09c371fc679725733dfacbb272cecc2783fcac52327f6dc3adaadc6e283a3f59b5bb13e6de97513472f393079de9475af2efd92bfec6fdd9d03b4ab297fa0d2b5a183df9e7990f95ae4e3cf2044feeb8fa04fbe8b4c4da207e3eaa7a0ba8bcf20bade13cac043dafa3e0f340d835f29a8d2abbf6c20e6c3da2db3fc7bf091ccca8affe4c3e04b9caa30f283be0abb1da3ee2934d8cb9beb27c6031d02b9f4041d6dbdc67302b4bccafbee07cafe746d093815e34255a709eaceee24a04bf1d7b60f838052c1d09c6f66c91f8c8caba5e8fb5c6b20d2f33f8742efbca452d5a5ec44fc2543d24b42bca396fc7cc83c07142daec7aebb707943c2f4dfe5c0ecd4947ac3ccd3bc0446fc5c1f62b823ccfc673ce8eb7eefabc63522f4da458cd0745d01c47c223847cb85b9283973f1d6b8c805c474c3072b6d83b10b6c405c3c013511574449ab02985fd4a404d0ca0335c1315fc67a61bad0ec7d26d64629ac907a5cfc05fe69485dc30deaacdc051556c53b5c67b6c5a0d45e2bc54dfaeb43d259adfbc23b6feba11f5957b4b7bcb7acfc12f0508bb538bdb15fe3c35ade2be5c7f16b5d4c8059b033e5dcaf5ae44dab8f5c012594fd488dbd66bb5e3d2e39d36471dba17a453555d43e2e2bd4a7395c511b4471e48dab693befcc59b5f21659571d29773d6b742051b51504a478cb83c4ca4dd8399e053058afa5cf8d4a33bee31dd9ad74503bd6f6940b79cdf24d95dfb4d6cc74d866a82e93314763de06704445c4b0765713dc5a8d580946457f5e57c6cbffbf47ade4fbcb7395b45ceaaf3eb77b3a5515e935d3c1fd16b8efc6ab365a3d67ec0c7fe1c44fa47acf9bd489ff5cb3f4ac3ceddecd32f46dc556a39c4f67579c1540b71fbee7ebe876d29e6f35856c56a7cb6e3f4044b9c682d869df151f047729947475e56396c5184147d3feea79d6f6a5d65f877a93be3bb14cb53cd9616ec7bc267f54ae93ed676fd9f463dfeef2325241e23654e291bd2831521416ea95ebb3f02eefcd7d828d0ed614b0af812e6958f20650dee4fe2c903f0975ca5c1c90e6bba80e2aea4124ee909c386b2b99a5ac4c0c4b0ede25e1ba813c2e6dc3dec374a66320b859a97e8b1b50ac28c821069c253c124a9b78b7234b6dcf8e6504ad9582278cb0254f2c6014d398034513b1a5f8e56fcbff06bc55fc2a71be646d9aef4c03d5cf1a220036859a9719e4c76bbcf520588263b818fc23a2c9590a4d56896e89e6b4cb31c19a0e21a96558ca88ab22c020b37184cc9a52d238ced031765c9281d6c6d5a49e2eefea5bfac953d6766a305d8bce456bcec8d6156c1da938417e33291af072ff214db0bd6e7a44ed09f40ebd3278ef823455642b18544bfd9cefef6fb4635fca179837f960dc221a1a1d2f794c2e89427474b1932bc0b7583cc1101f75a90e92359644ac9df03a8aca076fb4b55db6f87fc498342a12aa442f370a405d8829edd53738e89b2d9d095fa2ee4e0328502afdcc207cead35da2352c2fbd23f972ac4e86fc13d63e21bf656202d3a83755ce4ec14aa58cfc179dbca612b8325b8161b4f2ebda486f105259e19564a4660db50fb0bd52df3e6bee83ba6afd3e3d6e838f1d5654e6b5a3de5ac3f0646b69a9a4d5262a9d1d06953549dc0dd580342592759dd4532bf4d8dfa81a5c07744c4c5fd0565c473e43919c4b64a5c4d2492375b1de79c4fc557ac7773971857a4bb4b317da98714dc8a68666ef9c1aa7d4b877417d70369e4c5e19e29a61520945d845e2bf8d5f677f3be9757744d1d850d8fa5156454f63a60458adea07e51819bb6985f397acfa16fda2a8d1d58a0b3e9537b7295ea20d6c956326abc054da3035a1ba8e03f89cc84b1a5db8239e724d7bee43391657da9d6a876d28d2d4fae2341e045696f99ed2dc4a98cd158ec192b5c3e929448c57a9e6cf950a51995dba58adb9e3f8863405911b5b41d05ae2d5af75c820e4a8d72cad005740e94d11faca42c11117887964b5a121d9bbc67aa2fd97b582238cf7fa5236ac034e94a1e0fa49d7cfe6059ba3daf0a9cc0938d7a59645bf542be339f632bfcac7767e523e17d47894b061d3dbb991e36e917c84c055175ecaa77c729f595c95d403361673e2f0661d152fc08a7876961c726481b554625a09b170c9ac6879eaa36901a5da7e9b8d5fcef4e6908000129f4010a000ff00c2000000000910f4000080ef0059d2318ac80e04385070e1458909022c78c012a3c884172a5c5871b126cd8a1b3a44e8f1d365409325466c0982b46ac39a2b52bc794216a9c894376adc595317adc564c4021b18f35951b283497af40a3078a05f974595055a54b72f44ab479a1d9ae4392156a85f9e6dba14dba559a165be8d6a263a2a53ba6bb2b5ea56ba6bd8b051e25dab06fee752ba7fcab59b673b20ecb281f2fd2cb77de0e3c96307362cf891fb58c395277468891166edca9b337efce93438e1d2ab439e3d6a353ae5daab53be7dea363ce9d2bb63d60d5c4befcddb478ee63a34d7f4de91c3b2fe2efb98f2d4edbd830f5e3cb93374e1d9af178e7d587677eac5bf37fedd9befb4fae8dfbb87be6e7a79f0fae1cf8fdedefcfaf7f9e9cbb74fcedebcfbf3f1f3dfcf25514a3d08e25e450ed4702182392860e2890e38e0648d0e4880a4851258c0e58a166841975a5d78655885498840d88626988228872aa892298c2eb8e26c8b2ac8d2ec8636d8832c873ae8932d8c3ef8e3609b3a09d3e09646198420933265f7954126057555585d39a0508a4d49322496562414159c5949d5669552a8d497915e5916214a529985aa936a95d62557627970989f52a957ab9772d9f59063769967ef917af9b520aa7a0a96ac958e0ab62c99821ac6e3ad8289976e9805e6e1e6801268b9a6a616680a67a1ae7a2a69a4ae9ac92aae96aa93d8855e14efa9978e5545a51da361655c1ea7beda3b6359bacaabadafbe78fb5371cafa745fa7caea3c5da8ca0b9ca3bbc20bac65b4ce4b2d25b9de6bcb27b3c67b6ca5b0ee7b4e64b1ea7b6e69bea6371ba49aae8acaeaa2f2cb3fa9a1f2db8fadb5febbaf6ebf2d5947679c01f76ed954d1475e126cc5474e5e51e1bb707d5ed9372e9b57dd3750ba511b2cf79b7c0f5cc7d3c5cd8708d4c5ce2c5618c60f2642b0790b7582b3ce7d670132c2135c72f7c849aca179cd09da926087f6fb443fb64f0d74feb84f2da473def23d0fa0c6057935fba8c2ab7deea5e66d0d24bc5f3b75b6d0633b2636be220b7ee9df5b7d56b8bb22adb57bd85bcd96fbdb678de5bbd14fefdd467edcda26b0d23c86784390de920cc9a4d81e8891249baa1ea022ea9a2eb123ed9a3ec024e01a4e4025e30a5e6126ef0a3ef66f4735b5e3359cb57c83f8932fc581f6993bfc2653c29dae96abc685dcb3356f2bbec2bde82ece737dea2b5c485bc98dbee62eea7dce91bd5acdc94cf65ab70c337fe7892f9db3432366c3dde0571d3e72df4b3d4e3af6e7af7e7bfce73ba1d2c5ad6d5cadadc627fa2ad7f3cf0fbdf8f71bdfb6acef0085f310eff89450440e003f795b50a69895f0c306abc08b0c90a2052810cb0eefc2811cd0660b388f3e0230348f1c11660f76b51fc4fe2443b12d5ca643e24cc4c0ba62a991a5de3363410a76278c4ad12c0f78ef534022e0588e3c02a1178874c22221798a4c62e66878619571344c22110cc57ca881943954256f5203d61776d5443d71d83164e2d81177ed3336611c8152f2ea19c8d6413eb11d869a632558e8924b3a060f8e6c680713e8a64f32b1304d74d31f15e8284832121196840b4a11e26c2e35ea2e76b28227680881994221fc66a970606a42a0c0b586c3946bcc0e82c6b9c7b572f68781052923353a465288c49c224561193924c649b0f5841c015c2578f241d1a0917d998b061779234b3295eb44bc679321321a9ba1121a9c118d5519a97810d53312915a66ac09b9d0986240d944dc0a9e0bc9319c6664a22cd43c182bd94ecec8433e9911b6e84e720aef892da13f90b458cdc29980935082241c72ddc311736db5b4e0965471f566681a7d2776a1b488c44696b243ffc491241e7dba57a75af035892c20a00500e3473f1201507dd3d0aa2dec464992254e3084f50d703792be233ea465c2db21a0e3c412b0508504d4f340a00920558a9e43b044c879493a2259d4a72755e72c9d29ffd53d328e95943f036835e8c57489c110e9bcc1465567685138ac80583538ab0850c4d8462ec7be1ca622651cca3f58c78710b538ad70fc5442bae29daaf9a121a871c84f0b508a9605a0bd6d0a2f570b275066548f0e8d504a0e4abb49cd3496702aa767b6b74bc9e5805b93ccda4205e9a33c32768977db27ea0b83871aefaa91d0b35056892af042d924f0ba9b74e8655d16fc4f822fc893092c656d4ab550de25f3bd9d59a0807bd851a2431abe8d1aed4fb886be3447b0082a311b0506dac4d013e4140d62196cbb25ceaaadeea99cdb5c5da6bb24d405a6a6fb2dca7d8bf206ac92e500a87b63015b93ac12f2b49011354979d5ad57c2143db303235a713a1da5d905e020dd196f7b7890e192143e9bc8afab614168d0aeb0cca79241ef531339156c4109bcbc44d2ac1c682a45cf095436d3eee25c25b0ed06c7232ee8813df7ce4dbe2047be090582a8d95715c83457c0430d506492358e34859f078d7a6c9e5c591b417e833601ace165aca72f27b51cc0d2f1b3bad202e500eff7944fdb28226ee982535c2061cbb2a1a440570d4603a879a16da17413425fd217987918b5fb80a19cd4905436b6b35298c96f685c483df9f420bd0982abfb67ac072639a621c37835a817174ada43dc707862838a5ae666e602bd7eb4ea4d179953719d4fa8cd73eab25ade5ef924b22d3b58864b3292ddb903b7d6865608264a7053cd57912e4dade15695ec4cc11bd7db24ba96239a171db299dd47ce3c2f1ead8b631362dd52963b67b9fa97a1a47b74aa853fc640d619992eb9cfb0350075354af4d70f941bd13108503d59a29633f2d1dafc09cba6fb32d48e0ad3bad11960598c0b2ed29bddcffef5694ef8a91c77aabf44dd9337a9fce752766aefcf6ac8a0710e2c801cda28ded317bf25bd08ccc5c6f12419f44ccac49174d4cacb329fc9eb2fa7fc0e1edaeaabb559054f168a3332a300502fd6962b1d8d24e204b75576e548447f50db2f4f5ba6e214e476ac8247661a0a1ac5dddd69c7fa8c5c312c6ae594da48286e1319847c5ac171dea7b10aa491e95c21664fa9374e8ed49e3816bda78d92c181421a078b5879c36209636f5024e82f1e5dbd78c24dc79202d204e773230da9214e4135012f1635095035079733e3d3c24ef1ed7049b762dcc651b3d579cac8aca3bdb9c79bde418da24e71449f3d055c883e54c58f6dbc94330a0c770515e579c03255120a8c244d5dcb2e95e34ede09f6be41a6ef012d19afe9f9af92932673ec01397bb7a9241b4a04a8a1aff2f1529fa879a7144bbf2099af47af358354203fa1d55376124a477451287325697b014564084760b57f77772016a02a7c864c0335b86e310459506f71f7985ec3577197797bc07085009505e5171a87325500cd7b26476cf34c58f4747ec7435747c70405f57501bb7366311cf7028e774a39c13089856a07529c7ed7228081d38aa71258500663017c65d5501585f20b16bc01d7595847ad1527387500850977fc5aa7847b917e62d58030a0358e257643475c5126c08401868145241287454a96f206a7485126b75595907801a87d58cb1978611a65595500b06266f85a488f7201350850ef7d7b65950607538fc7922978243838556f78c86396d06a01f78885556397db15165b5b47bc0e07435984601b48c68c916770288c7b68df7e85b51a964052874e7401c85425cf5991a86226a38283a419b83255983b22888275e78853480a3334676276867394b68ac0975058801026e85b97936428e97924341a87ec6c93868350893ac07588459a8ed7e72b48ad70e8ed80f33f7885108261a872505922020e8587463a988d4682d344535011d55988d8e01ac7df8064837e85017806487f20af7081401f187b80931f7e97991ec7da7e17c25501868f48d72ed76a7fd8416c65b00770277ce8a713e85b6103f277362019d8b989644287a05002781b5eef181d5e372041f7625ba6c01a87b97ee55c05565b55413413770e8a97de7d582016b7ad5e95a268856a0711a398f8eb1e390c7b75e65096131e83ba6341b759504c1705f496d7a51dd8d914d5f291344619371787346d8533a962876d5f24e08aa7c294199053523d72381116273b8c47b756d5f37ce5ee2937b00625e83289f352153223d70c7309ee7824d175374a5c898a61172889977d8965ce27577b84340d7cf89f3f18479dc4f09d34f78e52d53676c016b7de5752850885af75922431181d50295473689f3d91b758570d4f09911f58097093be2f09e83287d72005377b24eb8fc75c2eb8b96ee51167c7035cb9b33ca8a47972ac7245b381e890ef8501e29f87236c38885cd5839456c65da95b6ad44c03984d83728988853116a04254e8fc1b47ec7cd5811a980898255a5301b59ee25a8df9f11484f787a06011e8317cf3b694b21e8099271627b00bb8964341a86556c51305ef5ee4f585985e7e850884552b9c651671852f68934285293017d9f204a5939885950296639234950c2a562ce4556845b851e9d2ad525b35b7556847e42a414590a05c113ac657b7776bf8358e51bd5eb52238a9281885d36fd244ace6363d41b65f396c68850171a6924d172f7ff83e7c914e9d85726e46f78967824d26301a986722668d902236a5259562942b7601e20d85d1a2031f7b88422e831f764a0563394552a7ef028d70235d2878a68a337a9634652236a778a01b95bc01e9c0a5a4678d58920cf8038b9ac9a647459a1ac3a785c27fd41f8de91452501f49e9595d27e82d17f0a72a556b17801e240f9ce8122b69992d17f98ec50ba587c995c6552df75c97a6e88b01249834006571141d88e88a41b65458336341e45d8a1c9d79dc16e8f07f35788125350250cdaf20edabd7cda019767587a61c5aac053ab56924bd58478dab00250ff7adaddacda950e20bdaf202fa8c51415a96815a3096946e195983a6595be96378915baf56cf91d50e7b476b21e89f55512d9a6491a4340033f5398dd48e72d2c3ae85b37be627a781f58439558a5633a9175285ca241250556eef77d22701478d8a59242839762711b721e012f85623e8c7aea6f31678fc9222a980e763b0b2f01e116267491d56172b5a95d1b4dad917d90aa8779014982e7baaf799941f7b00891b682283036e770a0b6c8aa38522647ba739896bcd5792d17397c31f89da66f6504b49d85e371021f7db51f3dba226d34b49e85bfa0bacb7ab6b915417988dad70fb22679ea409702398c26428ab9507283863462398905b38ec26e4b0b226d8429923b51396adf75b5078422553d527d9b6b18ac65c26c83f8a529e23d341a045962a527e20849c26b6ab75ae817a489152a7937a4642078113d7e2b301868c5b367601d88aa8f52b68649b6864ab3671bfd5ec72ba29efa1aa0282b3f6179aa6823a11ae41016eb66f87113d379149339ae85b886a45c07d9de6f760035c065bec70c87b9b113d72f7a01c2b528649f31486368bea5515f9eeb5f96976e404bb11219e1190caa68446b2289e97322ac7cd50a8924689e9452a451428018b95f2b675e187c5347a67aa9054dea14175a0699722160225a94a4b717c799bb75bba5c2a26b597267db2ab95a5950652864282f7bcae19d474c48da96ae1617ae88bcb8cb5211e9347cc994865178b2a5d86382e55deb379c6556a9e41e80aa6885c88788f93f6f2b89b2e7785e6b21155611bf61571678bfa428b001b97823ba7253eb29b2b5f47601aa98350dba34f82a4b9eb48653aef53633cb7bd65e5cb27553f7ce1b57aeb2f8ab965c028931cad3de948715417a896a11e56145706f21ab4c03e7b325dbb40187be4635209ba09debba3c8c385394253f31529d4cef8bb232c607f4b27ac7992b7468f8401e798dbe6cfdb015e246b276cd9b35ad8ad326613985358daf5a0f51f8538f075c2b69d64ec86daa710a32bbea995a339c5604a5282e91225165ca81bee7014d02801ecb6117cb2c6891b7ad913d7649cc94199367984016f9d3116b7a1df9fa5d41df770631a46c7553326f955b556dc527be86cf8a8b5c08da446c938830fca68b757e4df4dea1e47ecfa23015dbbd4ea2da911d1a8f786a0b3aa019c95591e44ca4f5f332885ef29154427e0c04cec2289a93462f7a99b7ac6611e88bb49ba514c9a01f8a72d6d1551a5a7a7d0176a989d791b3a7489760b1e9468b67adb12287c5f59ec1957b90a985a289d188e7a6176c65355cc8321ac2aac13279515889ea91bc96a410a9257e1202b5b61027dcf85d573bc954e0799c4551f75d6683a5c2b51f7d18d6850ba8c99bbc0918abcc1ad7d1a1595e20ca34b2a98019f1a2f9544c83b96b01e195fc70a7e4468edb9765ea57d0a6311e1dd855a880d25532189c389dd4eccfaad72b9da6624d4b8cfcd7c2aadf4e7dee9f75a27a1601117a56c17cae11948f6ce6723b65c966928ad9f57223dabbc619595706817d5655925126848786a29ef614125942670145988be017cb1a0bc4d7ba3de6532392b8fb436672b620037571e63f8f07b374c284a408003f59675fd287b462fca386288faad0532217ad3647bea89c4d527cbb6b352d3dbb242963c2c49a18ad649bc077a1b7483e7a48750030b90113b4ea5418dab39705b412bb649d69c998592ad1e2bfcb75cc796505a2f4a942684eac3121eecd7025aadb12591d6cc902dced6014d586c05286843942631a57d2347ec2930fcaeb0162a7b6681d8dde1c1ad7cb88388cf9cf776dab47e31fa40e4c8da721f7596c9604554ae366fd2933e8ab515cfe95f7653abaef90f550b17b4fcd3a0d4e6a85ab46f31e08bbccf952e9b671507c5babeddddef80136a15a764aa7fa91e40b7479722aab6ad803efdac9661916eb7918f13abc229cb1b68a1e9d69972aaa61a8edbbcb1f0cd06e05f82f0527606d8016785cbf9ea5ccc25ad42dd61298a2d4c2e69d544cca3e6e54ab774cc276a60e1576493a63a8f277cbb882cbe95b375f9307c3deba2b6c5ca6662e3226c5aceeb692702a1a1eaa4ebac7b882d7d49f4493edf58015b8fbdc11125ec88dcd5b595029b1199af7b69d2832212f3e0ab99149a98a3eb07998d7dbc0ac85281095a8dd8f5b9016a01a7cdd6aba98d1aba59cd3b9c27deec91179ad728e601dfe81928c75bbfba7b7c3d1c7fb8cd5966cbf07e2517931e1a50b244a809b3875be0f152141aefcc85a3f5acde4104572d7517083467a0b376b581cf41dfe54ecf8dd18fd819d2fae92784e1e2c86e2415ad3d8b16e0af07706365f3e757cf4db17d9a6692824348e15698a097d3b986da8638b361a8bd5366504a41c8af07716781dce31e78a23545f6eb941e0849d9501cede59b3d4ff859cad488f6da7c1e975a97d49c37462a65a7550894da975a63069cef8740a81d7579fe435df576bed7bde26c158c5ea66a8aeb7b1981fd85aeb6a0f8ced7345258b5f920c0ecc483554160668ad35d354afac07a01386f76476f7f91aafda7a8a68a03f93bd35008138f173017b5250728748ffed952050bf5452cf6c7f845af235545baf57c1188cf6af545e4efca456a0e35cbfdda8798eac3d025a8a30641cc017cf4af6f7337a33b45c70ff7728ff7967a9d5ab501ce72eaf357bf4aa462965e356180776c66cf6c7e837b5ff7afa19a2b6893d356ef001d74911b56ac49513565031624280aaf834e3f0bf444057a49582e3817268a98f0f4114388051224280294e84385055e2c2822712bc18827911389b2916dc79f2d523c6993d02c448b0d5ea42a70d8adc2a44d46a4c9a0362d458bc68efc4a03b4eccc9b2796140982f824d6af317a1d3a039a66ddaa358ad41bb211e050bd35567d0bb0796b53a06f564d8b1656aedaa37baa9d99157c65d0a68b03355a2891f36e973fd236ab27b62147b0499ed519027fe5ef52b857173e89497951d4c96db60d9ad3b85160c097ae168a43f53845d67d5fd48d84d86be09c371fc679725733dfacbb272cecc2783fcac52327f6dc3adaadc6e283a3f59b5bb13e6de97513472f393079de9475af2efd92bfec6fdd9d03b4ab297fa0d2b5a183df9e7990f95ae4e3cf2044feeb8fa04fbe8b4c4da207e3eaa7a0ba8bcf20bade13cac043dafa3e0f340d835f29a8d2abbf6c20e6c3da2db3fc7bf091ccca8affe4c3e04b9caa30f283be0abb1da3ee2934d8cb9beb27c6031d02b9f4041d6dbdc67302b4bccafbee07cafe746d093815e34255a709eaceee24a04bf1d7b60f838052c1d09c6f66c91f8c8caba5e8fb5c6b20d2f33f8742efbca452d5a5ec44fc2543d24b42bca396fc7cc83c07142daec7aebb707943c2f4dfe5c0ecd4947ac3ccd3bc0446fc5c1f62b823ccfc673ce8eb7eefabc63522f4da458cd0745d01c47c223847cb85b9283973f1d6b8c805c474c3072b6d83b10b6c405c3c013511574449ab02985fd4a404d0ca0335c1315fc67a61bad0ec7d26d64629ac907a5cfc05fe69485dc30deaacdc051556c53b5c67b6c5a0d45e2bc54dfaeb43d259adfbc23b6feba11f5957b4b7bcb7acfc12f0508bb538bdb15fe3c35ade2be5c7f16b5d4c8059b033e5dcaf5ae44dab8f5c012594fd488dbd66bb5e3d2e39d36471dba17a453555d43e2e2bd4a7395c511b4471e48dab693befcc59b5f21659571d29773d6b742051b51504a478cb83c4ca4dd8399e053058afa5cf8d4a33bee31dd9ad74503bd6f6940b79cdf24d95dfb4d6cc74d866a82e93314763de06704445c4b0765713dc5a8d580946457f5e57c6cbffbf47ade4fbcb7395b45ceaaf3eb77b3a5515e935d3c1fd16b8efc6ab365a3d67ec0c7fe1c44fa47acf9bd489ff5cb3f4ac3ceddecd32f46dc556a39c4f67579c1540b71fbee7ebe876d29e6f35856c56a7cb6e3f4044b9c682d869df151f047729947475e56396c5184147d3feea79d6f6a5d65f877a93be3bb14cb53cd9616ec7bc267f54ae93ed676fd9f463dfeef2325241e23654e291bd2831521416ea95ebb3f02eefcd7d828d0ed614b0af812e6958f20650dee4fe2c903f0975ca5c1c90e6bba80e2aea4124ee909c386b2b99a5ac4c0c4b0ede25e1ba813c2e6dc3dec374a66320b859a97e8b1b50ac28c821069c253c124a9b78b7234b6dcf8e6504ad9582278cb0254f2c6014d398034513b1a5f8e56fcbff06bc55fc2a71be646d9aef4c03d5cf1a220036859a9719e4c76bbcf520588263b818fc23a2c9590a4d56896e89e6b4cb31c19a0e21a96558ca88ab22c020b37184cc9a52d238ced031765c9281d6c6d5a49e2eefea5bfac953d6766a305d8bce456bcec8d6156c1da938417e33291af072ff214db0bd6e7a44ed09f40ebd3278ef823455642b18544bfd9cefef6fb4635fca179837f960dc221a1a1d2f794c2e89427474b1932bc0b7583cc1101f75a90e92359644ac9df03a8aca076fb4b55db6f87fc498342a12aa442f370a405d8829edd53738e89b2d9d095fa2ee4e0328502afdcc207cead35da2352c2fbd23f972ac4e86fc13d63e21bf656202d3a83755ce4ec14aa58cfc179dbca612b8325b8161b4f2ebda486f105259e19564a4660db50fb0bd52df3e6bee83ba6afd3e3d6e838f1d5654e6b5a3de5ac3f0646b69a9a4d5262a9d1d06953549dc0dd580342592759dd4532bf4d8dfa81a5c07744c4c5fd0565c473e43919c4b64a5c4d2492375b1de79c4fc557ac7773971857a4bb4b317da98714dc8a68666ef9c1aa7d4b877417d70369e4c5e19e29a61520945d845e2bf8d5f677f3be9757744d1d850d8fa5156454f63a60458adea07e51819bb6985f397acfa16fda2a8d1d58a0b3e9537b7295ea20d6c956326abc054da3035a1ba8e03f89cc84b1a5db8239e724d7bee43391657da9d6a876d28d2d4fae2341e045696f99ed2dc4a98cd158ec192b5c3e929448c57a9e6cf950a51995dba58adb9e3f8863405911b5b41d05ae2d5af75c820e4a8d72cad005740e94d11faca42c11117887964b5a121d9bbc67aa2fd97b582238cf7fa5236ac034e94a1e0fa49d7cfe6059ba3daf0a9cc0938d7a59645bf542be339f632bfcac7767e523e17d47894b061d3dbb991e36e917c84c055175ecaa77c729f595c95d403361673e2f0661d152fc08a7876961c726481b554625a09b170c9ac6879eaa36901a5da7e9b8d5fcef4e6908000b3 | ||
197 | EOL | ||
198 | |||
199 | |||
200 | |||
201 | use 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 | ||
218 | if($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 | }; | ||
238 | if($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 | ## | ||
250 | if($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 | }; | ||
275 | cookie("teste1",$POST{username},"+5m"); | ||
276 | cookie("teste4","conas","+10m"); | ||
277 | if($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 | ## | ||
315 | if($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 | ## | ||
329 | sub 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 | ## | ||
355 | sub 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; | ||
389 | sub 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 | ## | ||
418 | sub 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:\ \ </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>\ \ ".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 "\ \ 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'>"."\ " 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 | ## | ||
1077 | cookie("username",$POST{username},"+1M") if( $POST{username} ); | ||
1078 | print "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; | ||
1085 | if($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 | |||
1108 | if($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 | |||
1122 | if($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 | ## | ||
1127 | if($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 | |||
5 | echo -ne "Content-type: text/html\r\n\r\n" | ||
6 | |||
7 | echo -e "<HTML>\n" | ||
8 | echo -e "<BODY>\n" | ||
9 | |||
10 | echo -e "THis is a simple cgi file\n" | ||
11 | echo -e "$QUERY_STRING" | ||
12 | echo -e "</body>" | ||
13 | echo -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; | ||
9 | my %POST; | ||
10 | my %QUERY_STRING; | ||
11 | my %COOKIE; | ||
12 | my $stdindata; | ||
13 | |||
14 | while(<STDIN>) { | ||
15 | $stdindata.=$_; | ||
16 | }; | ||
17 | if($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 | }; | ||
27 | if($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 | }; | ||
37 | if($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 | |||
46 | sub 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 | |||
85 | sub 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"; | ||
106 | cookie("teste1","maria","+5m"); | ||
107 | cookie("login","manel","+5m"); | ||
108 | print "Content-type: text/html\r\n\r\n"; | ||
109 | |||
110 | |||
111 | |||
112 | print "<HTML>\n"; | ||
113 | print "<BODY bgcolor='EFEFEF'>\n"; | ||
114 | print "Simple cgi demo<BR>\n"; | ||
115 | print "<form action='$ENV{SCRIPT_NAME}?teste=new' method='POST'>\n"; | ||
116 | print "post value: <input type='text' name='login'>\n"; | ||
117 | print "<input type=submit name='go' value='send'>\n"; | ||
118 | print "</form><BR>\n"; | ||
119 | |||
120 | print "results:<table border=1><TR><TD>cookie 'maria'</TD><TD> $COOKIE{teste1}</TD></TR>\n"; | ||
121 | print "<TR><TD>post 'login':</TD><TD> $POST{login}</TD></TR>\n"; | ||
122 | print "<TR><TD>querystring 'teste':</TD><TD> $QUERY_STRING{teste}</TD></TR>\n"; | ||
123 | print "</TABLE>\n"; | ||
124 | |||
125 | print "</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 | |||
16 | extern struct web_client *current_web_client; | ||
17 | int PORT=80; | ||
18 | |||
19 | extern char **environ; | ||
20 | void 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 | }; | ||
51 | void 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 | }; | ||
69 | void 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 | }; | ||
87 | main() { | ||
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 | |||
9 | int PORT=80; | ||
10 | |||
11 | void 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 int outfd<BR>\n char *inetname<BR>\n char *request<BR>\n char *method<BR>\n char *user<BR>\n char *pass<BR>\n char *QueryData;<BR>\n struct memrequest *mem;<BR>\n char *(*Header)(char*);<BR>\n char *(*QueryString)(char*);<BR>\n char *(*Post)(char*);<BR>\n 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 | |||
44 | void 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 | |||
51 | int 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 @@ | |||
1 | Private-Key: (512 bit) | ||
2 | modulus: | ||
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 | ||
8 | publicExponent: 65537 (0x10001) | ||
9 | privateExponent: | ||
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 | ||
15 | prime1: | ||
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 | ||
19 | prime2: | ||
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 | ||
23 | exponent1: | ||
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 | ||
27 | exponent2: | ||
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 | ||
31 | coefficient: | ||
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 | ||
35 | Certificate: | ||
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----- | ||
68 | MIIBOwIBAAJBALT8ZLDAJ2NcpkNmrGhYSDfT9aT6r6cRof2BpHqe/5Cj7t/q7xFU | ||
69 | uMALJLNv/6iDuAwIzwNRQRTwcCDOXyWoZX8CAwEAAQJAeKrau1myKTZJiCC5jGxn | ||
70 | 4gkI+3FEkcBY37uDHVpLDHSPhjOVEFd9MsDTbLjFgrTO1ii5M/erg2MtE3SVSTcv | ||
71 | KQIhAO/cxhhhRo2+09FLb1zjHWqdedWzJIzOTNuZ1Q5wyHD9AiEAwSmSNANMuZs7 | ||
72 | YQlVvsL44uVQHl2yjSgL0q9yzIKIhysCIQDbPCI/1GGFWz8FlHpUHy4a7ZaXUab9 | ||
73 | n+415dQL3+AFDQIgfpfHGM180Du7K7pZdr8DLHjLDEuuBDLVpMuVehCmd6cCIQC4 | ||
74 | 8NaZ3IVt2ATFkn7bQS5QQtDwN688sqZ0kqDJmUcYQQ== | ||
75 | -----END RSA PRIVATE KEY----- | ||
76 | -----BEGIN CERTIFICATE----- | ||
77 | MIIBmjCCAUSgAwIBAwIBADANBgkqhkiG9w0BAQQFADAlMQswCQYDVQQGEwJVSzEW | ||
78 | MBQGA1UEAxMNT3BlblNTTCBHcm91cDAeFw0wMjA0MjMwNjU1MjFaFw0wMzA0MjMw | ||
79 | NjU1MjFaMCUxCzAJBgNVBAYTAlVLMRYwFAYDVQQDEw1PcGVuU1NMIEdyb3VwMFww | ||
80 | DQYJKoZIhvcNAQEBBQADSwAwSAJBALT8ZLDAJ2NcpkNmrGhYSDfT9aT6r6cRof2B | ||
81 | pHqe/5Cj7t/q7xFUuMALJLNv/6iDuAwIzwNRQRTwcCDOXyWoZX8CAwEAAaNfMF0w | ||
82 | EQYJYIZIAYb4QgEBBAQDAgZAMCgGCWCGSAGG+EIBDQQbFhlleGFtcGxlIGNvbW1l | ||
83 | bnQgZXh0ZW5zaW9uMB4GCWCGSAGG+EIBDAQRFg93d3cub3BlbnNzbC5vcmcwDQYJ | ||
84 | KoZIhvcNAQEEBQADQQA+ajxK7Isf66iZM9bg+fGncDx6sXOuNFIG0L4LMu3sASel | ||
85 | 1jzONDj5KUnBCw2adGC4TbngKa39WzIyPzzoky1q | ||
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 | |||
8 | typedef 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 | |||
25 | int PORTSSL=443; | ||
26 | |||
27 | unsigned 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 | } | ||
46 | void 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 | |||
221 | int 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> | ||
12 | WS_USESSL for openssl connections (https support)<BR> | ||
13 | WS_USEEXTCONF for using a external config file<BR> | ||
14 | WS_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> | ||
31 | WS_LOCAL - only local connections are handled<BR> | ||
32 | WS_DYNVAR - treat dynamic variables on output (Atention: this disables "Content-range" and "Content-length" header, responding "501 not implemented")<BR> | ||
33 | WS_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> | ||
47 | WS_LOCAL - only local connections are handled<BR> | ||
48 | WS_DYNVAR - treat dynamic variables on output (Atention: this disables "Content-range" and "Content-length" header, responding "501 not implemented")<BR> | ||
49 | WS_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> | ||
130 | The allocated memory <U>data</U> points to mustn't be smaller than <U>w</U>*<U>h</U>.<BR> | ||
131 | The 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> | ||
157 | timeoffset 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("<BODY bgcolor='$bgc;'>"); - 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> | ||
279 | extern 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-><U>outfd</U></B> <UL>is the filedescriptor of the current output stream (useful for cgi handlers and friends).</UL><BR> | ||
300 | <B>ClientInfo-><U>inetname</U></B> <UL>a string to inetname (i.e. "127.0.0.1")</UL> <BR> | ||
301 | <B>ClientInfo-><U>request</U></B> <UL>is the requested 'file' (i.e. for "GET /index.html HTTP/1.0\r\n" the ClientInfo->request is "/index.html")</UL><BR> | ||
302 | <B>ClientInfo-><U>method</U></B> <UL>is the request method ("GET" or "POST" etc..)</UL><BR> | ||
303 | <B>ClientInfo-><U>user</U></B> <UL>AuthRealm username</UL><BR> | ||
304 | <B>ClientInfo-><U>pass</U></B> <UL>AuthRealm password</UL><BR> | ||
305 | <B>ClientInfo-><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->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-><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->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-><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 <input> 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-><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-><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-><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 <input> tag.<BR><BR> | ||
311 | the structure is<BR> | ||
312 | struct _MultiPart { | ||
313 | <UL> | ||
314 | char *<U>id</u>;<BR> | ||
315 | char *<U>data</U>;<BR> | ||
316 | unsigned int <U>size</U>;<BR> | ||
317 | char *<U>filename</U>;<BR> | ||
318 | void *<U>pad</U>;<BR> | ||
319 | </UL> | ||
320 | };<BR> | ||
321 | to be used as ClientInfo-><U>MultiPart</U>("file1").<U>data</U>; ClientInfo-><U>MultiPart</U>("file1").<U>size</U>; ClientInfo-><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] | ||
330 | KEY=VALUE | ||
331 | |||
332 | libwebserver configurations must be in topic LIBWEBSERVER as: | ||
333 | [LIBWEBSERVER] | ||
334 | LOG=help.log | ||
335 | PORT=80 | ||
336 | USESSL=1 | ||
337 | CERTFILE=foocert.pm | ||
338 | MIMEFILE=/etc/mime.types | ||
339 | LOCAL=1 | ||
340 | |||
341 | LOG -> the log file | ||
342 | PORT -> the listen port that will be used for tcp connections | ||
343 | |||
344 | USESSL -> the ssl flag if you want to use openssl for secure server (https) | ||
345 | CERTFILE -> the file that contains certificate for ssl connections | ||
346 | MIMEFILE -> the file that contains mime.types similer to apache mimefile | ||
347 | LOCAL -> 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 | |||