Unnamed Fossil Project

Check-in [cc61bb1107]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:'httpd/httpx/sar'
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:cc61bb1107edcaf2f314ff4c7bf3a392e0274f1f
User & Date: alexey@sudachen.name 2012-04-28 19:50:13
Context
2012-05-24
03:28
updated check-in: 5dc3de1a25 user: alexey@sudachen.name tags: trunk
2012-04-28
19:50
'httpd/httpx/sar' check-in: cc61bb1107 user: alexey@sudachen.name tags: trunk
2012-04-04
10:37
'updated' check-in: 922d82ae97 user: alexey@sudachen.name tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to buffer.hc.

158
159
160
161
162
163
164








165
166
167
168
169
170
171
      {
        Buffer_Grow_Reserve(bf,bf->count+count);
        memset(bf->at+bf->count,c,count);
        bf->count += count;
        bf->at[bf->count] = 0;
      }
  }








#endif
  ;

void Buffer_Puts(YOYO_BUFFER *bf, char *S)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    Buffer_Append(bf,S,-1);







>
>
>
>
>
>
>
>







158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
      {
        Buffer_Grow_Reserve(bf,bf->count+count);
        memset(bf->at+bf->count,c,count);
        bf->count += count;
        bf->at[bf->count] = 0;
      }
  }
#endif
  ;

void Buffer_Print(YOYO_BUFFER *bf, char *S)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    Buffer_Append(bf,S,-1);
  }
#endif
  ;

void Buffer_Puts(YOYO_BUFFER *bf, char *S)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    Buffer_Append(bf,S,-1);

Added debugit.hc.











































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85


/*

Copyright © 2010-2011, Alexéy Sudachén, alexey@sudachen.name, Chile

In USA, UK, Japan and other countries allowing software patents:

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    http://www.gnu.org/licenses/

Otherwise:

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

Except as contained in this notice, the name of a copyright holder shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization of the copyright holder.

*/

#ifndef C_once_1ABAFC81_AD6E_4869_8891_EEE28BC64BF4
#define C_once_1ABAFC81_AD6E_4869_8891_EEE28BC64BF4

#ifdef _LIBYOYO
#define _YOYO_DEBUGIT_BUILTIN
#endif

#include "yoyo.hc"
#include "winreg.hc"

#ifdef _MSC_VER
# define Debug_Break() __debugbreak()    
#elif defined __GNUC__
# define Debug_Break() __builtin_trap()    
#else
# define Debug_Break() raise(SIGTRAP)
#endif

void Debug_It()
#ifdef _YOYO_DEBUGIT_BUILTIN
  {
#ifdef __windoze
    char ae[128] = {0};
    __Auto_Release
      {
        YOYO_WINREG *h = Open_Local_Machine_Subkey("Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug");
        char *S = WinReg_Query_String(h,"Debugger");
        snprintf(ae,127,S,GetCurrentProcessId(),0);
      }
    WinExec(ae,0);
    Sleep(3000);
#endif
    Debug_Break();    
  }
#endif
  ;
  
#endif /*C_once_1ABAFC81_AD6E_4869_8891_EEE28BC64BF4*/

Changes to dicto.hc.

382
383
384
385
386
387
388
389
390
391


















































392
393
          while ( nrec )
            {
              filter(nrec->key,nrec->ptr,state);
              nrec = nrec->next;
            }  
        }
  }
#endif
  ;



















































#endif /* C_once_38B1FFE7_1462_42EB_BABE_AA8E0BE62203 */











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
          while ( nrec )
            {
              filter(nrec->key,nrec->ptr,state);
              nrec = nrec->next;
            }  
        }
  }
#endif
  ;

typedef void (*dicto_format_printer_t)(YOYO_BUFFER *bf,void *S);

char *Dicto_Format(YOYO_DICTO *o, dicto_format_printer_t print, YOYO_BUFFER *_bf, int pretty)
#ifdef _YOYO_DICTO_BUILTIN  
  {
    int start = 0, i, j=0;
    YOYO_BUFFER *bf = _bf;
    YOYO_DICTO_REC *nrec;

    if ( !bf ) bf = Buffer_Init(0);
    start = bf->count;
    
    Buffer_Fill_Append(bf,'{',1);
    if ( pretty )
      Buffer_Fill_Append(bf,'\n',1); 

    if ( o && o->table ) 
      for ( i = 0; i < o->width; ++i )
        {      
          nrec = o->table[i];
          while ( nrec )
            {
              if ( j ) 
                if ( pretty )
                  Buffer_Fill_Append(bf,'\n',1); 
                else 
                  Buffer_Append(bf,", ",2); 
              else 
                j = 1; 
              if ( pretty )
                Buffer_Fill_Append(bf,' ',2); 
              Buffer_Append(bf,nrec->key,-1);
              Buffer_Append(bf,": ",2);
              print(bf,nrec->ptr);
              nrec = nrec->next;
            }  
        }
    
    if ( j && pretty )
      Buffer_Fill_Append(bf,'\n',1); 
    Buffer_Fill_Append(bf,'}',1);

    if ( !_bf )
      return Buffer_Take_Data(bf);
    else
      return bf->at+start;
  }
#endif
  ;

#endif /* C_once_38B1FFE7_1462_42EB_BABE_AA8E0BE62203 */

Changes to file.hc.

387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
#endif        

YOYO_FILE_STATS *File_Translate_Filestats(_YOYO_stat *fst,YOYO_FILE_STATS *st,int exists)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( !st ) st = __Malloc(sizeof(YOYO_FILE_STATS));
    memset(st,0,sizeof(*st));

    st->f.exists       = exists;
    st->f.is_regular   = (fst->st_mode&S_IFMT) == S_IFREG;
    st->f.is_directory = (fst->st_mode&S_IFMT) == S_IFDIR;
  #ifndef __windoze  
    st->f.is_symlink   = (fst->st_mode&S_IFMT) == S_IFLNK;    
    st->f.is_unisok    = (fst->st_mode&S_IFMT) == S_IFSOCK;
  #endif  
    st->f.is_writable  = (fst->st_mode&S_IWUSR) != 0;
    st->f.is_readable  = (fst->st_mode&S_IRUSR) != 0;
    st->f.is_executable = (fst->st_mode&S_IXUSR) != 0;
    st->length = fst->st_size;
    st->ctime  = fst->st_ctime;
    st->mtime  = fst->st_mtime;







<

|
|

|
|







387
388
389
390
391
392
393

394
395
396
397
398
399
400
401
402
403
404
405
406
#endif        

YOYO_FILE_STATS *File_Translate_Filestats(_YOYO_stat *fst,YOYO_FILE_STATS *st,int exists)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( !st ) st = __Malloc(sizeof(YOYO_FILE_STATS));
    memset(st,0,sizeof(*st));

    st->f.exists       = exists;
    st->f.is_regular   = !!((fst->st_mode&S_IFMT) & S_IFREG);
    st->f.is_directory = !!((fst->st_mode&S_IFMT) & S_IFDIR);
  #ifndef __windoze  
    st->f.is_symlink   = !!((fst->st_mode&S_IFMT) & S_IFLNK);    
    st->f.is_unisok    = !!((fst->st_mode&S_IFMT) & S_IFSOCK);
  #endif  
    st->f.is_writable  = (fst->st_mode&S_IWUSR) != 0;
    st->f.is_readable  = (fst->st_mode&S_IRUSR) != 0;
    st->f.is_executable = (fst->st_mode&S_IXUSR) != 0;
    st->length = fst->st_size;
    st->ctime  = fst->st_ctime;
    st->mtime  = fst->st_mtime;

Added httpd.hc.









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644

/*

Copyright © 2010-2012, Alexéy Sudachén, alexey@sudachen.name, Chile

In USA, UK, Japan and other countries allowing software patents:

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    http://www.gnu.org/licenses/

Otherwise:

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

Except as contained in this notice, the name of a copyright holder shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization of the copyright holder.

*/

#ifndef C_once_BE85262D_CDA8_4AF5_B684_8A30EB6D7370
#define C_once_BE85262D_CDA8_4AF5_B684_8A30EB6D7370

#include "yoyo.hc"
#include "string.hc"
#include "buffer.hc"
#include "dicto.hc"
#include "file.hc"
#include "tcpip.hc"
#include "url.hc"
#include "asio.hc"

#ifdef _LIBYOYO
#define _YOYO_HTTPD_BUILTIN
#endif

struct _YOYO_HTTPD_REQUEST;
typedef int (*httpd_callback_t)(void *obj, struct _YOYO_HTTPD_REQUEST *rqst, int status);
typedef struct _YOYO_HTTPD
  {
    YOYO_TCPSOK *sok;
    char *host;
    int port;

    struct _YOYO_HTTPD_REQUEST *rqst;
    httpd_callback_t callback;
    void *obj;
  } YOYO_HTTPD;

typedef struct _YOYO_HTTPD_REQUEST
  {
    YOYO_BUFFER *bf; /* associated with instrm when post data is small */
    
    /* request */    
    void *instrm;
    char *instrm_type; /*handle by qhdr*/
    int   instrm_length;
    YOYO_DICTO  *qhdr;
    
    char *uri;
    char *remote_addr;
    int   remote_port;
    int   method;
    int   httpver;
        
    /* response */
    void *outstrm;
    char *outstrm_type;
    char *outstrm_charset;
    int   outstrm_length;
    
    YOYO_ARRAY *cookie;
    char *location;
    char *cache_control;

    /* internal */    
    YOYO_TCPSOK *sok;
    YOYO_HTTPD  *httpd;
    int nline;
    int left;
    struct _YOYO_HTTPD_REQUEST *next;
  } YOYO_HTTPD_REQUEST;

void Httpd_Detach_Request(YOYO_HTTPD_REQUEST *rqst)
  {
    YOYO_HTTPD *httpd = rqst->httpd;
    YOYO_HTTPD_REQUEST **q = &httpd->rqst;
    while ( *q )
      {
        if ( *q == rqst )
          {
            *q = rqst->next;
            rqst->next = 0;
            break;
          }
        q = &(*q)->next;
      }
  }

void YOYO_HTTPD_REQUEST_Destruct(YOYO_HTTPD_REQUEST *rqst)
  {
    Httpd_Detach_Request(rqst);
    __Unrefe(rqst->httpd);
    __Unrefe(rqst->sok);
    free(rqst->remote_addr);
    free(rqst->uri);
    __Unrefe(rqst->bf);
    __Unrefe(rqst->qhdr);
    __Unrefe(rqst->instrm);
    __Unrefe(rqst->outstrm);
    free(rqst->outstrm_type);
    free(rqst->location);
    free(rqst->cache_control);
    __Unrefe(rqst->cookie);
    free(rqst->outstrm_charset);
    __Destruct(rqst);
  }

enum
  {
    /* status */
    HTTPD_RQST_CONNECT     = 1,
    HTTPD_RQST_POSTDTA     = 2,
    HTTPD_RQST_PERFORM     = 3,

    HTTPD_STAT_TIMER       = 0x00010000,
    HTTPD_STAT_LONGRQST    = 0x81000000,
    HTTPD_STAT_IOFAIL      = 0x82000000,
    HTTPD_STAT_ACCEPTFAIL  = 0x83000000,
    HTTPD_STAT_REJECTED    = 0x84000000,
    HTTPD_STAT_BADMETHOD   = 0x85000000,
    HTTPD_STAT_FINISHED    = 0x00000000,

    /* HTTPD_RQST_CONNECT/HTTPD_RQST_POSTDTA result */
    HTTPD_ACCEPT           = 0,
    HTTPD_REJECT           = -1,

    /* HTTPD_RQST_PERFORM result */
    HTTPD_SUCCESS          = 200,
    HTTPD_PARTIAL          = 206,

    /* HTTPD_RQST_PERFORM/HTTPD_RQST_POSTDTA result */
    HTTPD_REDIRECT         = 301,
    HTTPD_FORBIDEN         = 403,
    HTTPD_NOTFOUND         = 404,
    HTTPD_SERVERROR        = 501,

    HTTPD_MAXBUF_LENGTH          = 64*1024,
    HTTPD_MAX_REQUEST_LENGTH     = 8*1024,
    HTTPD_MAXBUF_POSTDATA_LENGTH = 64*1024,

    HTTPD_GET_METHOD       = 1001,
    HTTPD_POST_METHOD      = 1002,
    HTTPD_PUT_METHOD       = 1003,
    HTTPD_HEAD_METHOD      = 1004,
    HTTPD_DELETE_METHOD    = 1005,

  };

char *Httpd_Method_String(int method)
  {
    switch(method)
      {
        case HTTPD_GET_METHOD:    return "GET";
        case HTTPD_POST_METHOD:   return "POST";
        case HTTPD_PUT_METHOD:    return "PUT";
        case HTTPD_HEAD_METHOD:   return "HEAD";
        case HTTPD_DELETE_METHOD: return "DELETE";
      }
      
    return "NONE";
  }

YOYO_HTTPD_REQUEST *Httpd_Request(YOYO_HTTPD *httpd, YOYO_TCPSOK *sok)
  {
    YOYO_HTTPD_REQUEST *rqst = __Object_Dtor(sizeof(YOYO_HTTPD_REQUEST),YOYO_HTTPD_REQUEST_Destruct);
    rqst->httpd = __Refe(httpd);
    rqst->sok = __Refe(sok);
    rqst->remote_addr = Ipv4_Format_Npl(sok->ip);
    rqst->remote_port = sok->port;
    rqst->next = httpd->rqst;
    httpd->rqst = rqst;
    rqst->bf = __Refe(Buffer_Init(0));
    rqst->qhdr = __Refe(Dicto_Ptrs());
    rqst->cookie = __Refe(Array_Pchars());
    Buffer_Reserve(rqst->bf,HTTPD_MAXBUF_LENGTH);
    return rqst;
  }

char *Httpd_Status_Text(int st)
  {
    switch ( st )
      {
        case 200: return "OK";
        case 201: return "Created";
        case 202: return "Accepted";
        case 203: return "Non-Authoritative Information";
        case 204: return "No Content";
        case 205: return "Reset Content";
        case 206: return "Partial Content";
        case 207: return "Multi-Status";
        case 208: return "Already Reported";
        case 226: return "IM Used";
        case 300: return "Multiple Choices";
        case 301: return "Moved Permanantly";
        case 302: return "Found";
        case 303: return "See Other";
        case 304: return "Not Modified";
        case 305: return "Use Proxy";
        case 306: return "Switch Proxy";
        case 307: return "Temporary Redirect";
        case 308: return "Resume Incomplete";
        case 400: return "Bad Request";
        case 401: return "Unauthorized";
        case 402: return "Payment Required";
        case 403: return "Forbidden";
        case 404: return "Not Found";
        case 405: return "Method Not Allowed";
        case 406: return "Not Acceptable";
        case 407: return "Proxy Authentication Required";
        case 408: return "Request Timeout";
        case 409: return "Conflict";
        case 410: return "Gone";
        case 411: return "Length Required";
        case 412: return "Precondition Failed";
        case 413: return "Request Entity Too Large";
        case 414: return "Request-URI Too Long";
        case 415: return "Unsupported Media Type";
        case 416: return "Requested Range Not Satisfiable";
        case 417: return "Expectation Failed";
        case 418: return "I'm a teapot";
        case 422: return "Unprocessable Entity";
        case 423: return "Locked";
        case 424: return "Failed Dependency";
        case 425: return "Unordered Collection";
        case 426: return "Upgrade Required";
        case 428: return "Precondition Required";
        case 429: return "Too Many Requests";
        case 431: return "Request Header Fields Too Large";
        case 500: return "Internal Server Error";
        case 501: return "Not Implemented";
        case 502: return "Bad Gateway";
        case 503: return "Service Unavailable";
        case 504: return "Gateway Timeout";
        case 505: return "HTTP Version Not Supported";
        case 506: return "Variant Also Negotiates";
        case 507: return "Insufficient Storage";
        case 508: return "Loop Detected";
        case 509: return "Bandwidth Limit Exceeded";
        case 510: return "Not Extended";
        case 511: return "Network Authentication Required";
        default:  
          return "Unknown Status"; 
      }
  }

void Httpd_Gen_Response(YOYO_HTTPD_REQUEST *rqst, int st)
  {
    int i;
    YOYO_BUFFER *bf = rqst->bf;
    bf->count = 0;
    Buffer_Printf(bf,"HTTP/1.1 %d %s\r\n",st,Httpd_Status_Text(st));
    Buffer_Append(bf,"Connection: close\r\n",-1);
    if ( rqst->location )
      {
        Buffer_Printf(bf,"Location: %s\r\n",rqst->location);
      }
    else
      {
        //if ( rqst->cache_control )
        //  Buffer_Printf(bf,);
        if ( rqst->cookie->count ) for ( i=0; i<rqst->cookie->count; ++i )
          Buffer_Printf(bf,"Set-Cookie: %s\r\n",rqst->cookie->at[i]);
        if ( rqst->outstrm_charset && rqst->outstrm_type )
          Buffer_Printf(bf,"Content-Type: %s; charset=%s\n\r\n",rqst->outstrm_type,rqst->outstrm_charset);
        else if ( !rqst->outstrm_type || !strncmp_I(rqst->outstrm_type,"text/",5) )
          Buffer_Printf(bf,"Content-Type: %s; charset=utf-8\r\n",rqst->outstrm_type?rqst->outstrm_type:"text/plain");
        //else if ( !rqst->outstrm_type )
        //  Buffer_Printf(bf,"Content-Type: %s\r\n","text/plain");
        else
          Buffer_Printf(bf,"Content-Type: %s\r\n",rqst->outstrm_type);
        if ( rqst->outstrm_length )
          Buffer_Printf(bf,"Content-Length: %d\r\n",rqst->outstrm_length);
        else
          Buffer_Append(bf,"Transfer-Encoding: chunked\r\n",-1);
      }
    Buffer_Append(bf,"\r\n",2);
    
    if ( rqst->outstrm )
      {
        rqst->left = rqst->outstrm_length;
        if ( rqst->left <= bf->capacity-bf->count)
          {
            int L = Yo_Minu(rqst->left,bf->capacity-bf->count);
            L = Oj_Read(rqst->outstrm,bf->at+bf->count,L,0);
            rqst->left -= L;
            bf->count += L;
          }
      }
  }  

int Cbk_Httpd_Sending_Result(void *_rqst, int status)
  {
    int L;
    YOYO_HTTPD_REQUEST *rqst = _rqst;
    YOYO_BUFFER *bf = rqst->bf;

    if ( status == ASIO_TIMER )
      return rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_STAT_TIMER),0;
    if ( !ASIO_SUCCEEDED(status) )
      return rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_STAT_IOFAIL),
             Tcp_Close(rqst->sok),0;
    
    if ( rqst->outstrm )
      if ( rqst->outstrm_length )
        {
          if ( !rqst->left ) goto finished;
          L = Yo_Minu(rqst->left,bf->capacity);
          L = Oj_Read(rqst->outstrm,bf->at,L,0);
          if ( !L ) goto finished;
          rqst->left -= L;
          return Tcp_Asio_Send(rqst->sok,bf->at,L,rqst,Cbk_Httpd_Sending_Result);
        }
      else /*chunked*/
        {
          int i, j;
          char len[30];
          L = bf->capacity - 32;        
          L = Oj_Read(rqst->outstrm,bf->at+30,L,0);
          sprintf(len,"%x\r\n",L);
          i = strlen(len);
          j = 30-i;
          memcpy(bf->at+j,len,i);
          memcpy(bf->at+30+L,"\r\n",2);
          if ( !L ) { rqst->outstrm_length = -1; rqst->left = 0; }
          return Tcp_Asio_Send(rqst->sok,bf->at,L,rqst,Cbk_Httpd_Sending_Result);
        }
      
  finished:
    rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_STAT_FINISHED);
    Tcp_Graceful_Close(rqst->sok);
    return 0;
  }

void Httpd_Continue_Request(YOYO_HTTPD_REQUEST *rqst, int st)
  {
    YOYO_BUFFER *bf = rqst->bf;
    Httpd_Gen_Response(rqst,st);
    Tcp_Asio_Send(rqst->sok,bf->at,bf->count,rqst,Cbk_Httpd_Sending_Result);
  }

void Httpd_Perform_Request(YOYO_HTTPD_REQUEST *rqst)
  {
    YOYO_BUFFER *bf = rqst->bf;
    int st;
    
    if ( rqst->method == HTTPD_POST_METHOD || rqst->method == HTTPD_PUT_METHOD )
      {
        if ( !rqst->instrm ) 
          {
            rqst->instrm_length = bf->count;
            rqst->instrm = __Refe(Buffer_As_File(bf));
          }
        Oj_Seek(rqst->instrm,0,0);
      }
      
    st = rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_RQST_PERFORM);
    if ( st )
      Httpd_Continue_Request(rqst,st);
  }
  
int Cbk_Httpd_Getting_Postdta(void *_rqst, int status, int count)
  {
    YOYO_HTTPD_REQUEST *rqst = _rqst;
    YOYO_BUFFER *bf = rqst->bf;
    
    if ( status == ASIO_TIMER )
      return rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_STAT_TIMER),0;
    if ( !ASIO_SUCCEEDED(status) )
      return rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_STAT_IOFAIL),
             Tcp_Close(rqst->sok),0;

    bf->count += count;
    rqst->left -= count;
    
    if ( rqst->instrm || bf->count > HTTPD_MAXBUF_POSTDATA_LENGTH )
      {
        if ( !rqst->instrm ) 
          {
            if ( HTTPD_ACCEPT != rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_RQST_POSTDTA) )
              {
                return rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_STAT_LONGRQST),
                        Tcp_Close(rqst->sok),0;
              }
            if ( !rqst->instrm )
              rqst->instrm = __Refe(Cfile_Temp());
          }
        Oj_Write(rqst->instrm,bf->at,bf->count,-1);
        rqst->instrm_length += bf->count;          
        bf->count = 0;
      }

    if ( rqst->left > 0 )
      {  
        int L;
        Buffer_Grow_Reserve(bf,bf->count+4*1024);      
        L = Yo_Minu(bf->capacity-bf->count,rqst->left);
        Tcp_Asio_Recv(rqst->sok,bf->at+bf->count,L,L,rqst,Cbk_Httpd_Getting_Postdta);
      }
    else
      {
        Httpd_Perform_Request(rqst);
      }  
    
    return 0;
  }

void Httpd_Analyze_Qline(char *text,YOYO_HTTPD_REQUEST *rqst)
  {
    char *S, *q;
    
    S = text;
    while ( *S && *S != '\n' && Isspace(*S) ) ++S;
    q = S;
    while ( *q && !Isspace(*q) ) ++q;
    
    if ( !strncmp_I(S,"GET",q-S) )
      rqst->method = HTTPD_GET_METHOD;
    else if ( !strncmp_I(S,"POST",q-S) )
      rqst->method = HTTPD_POST_METHOD;
    else if ( !strncmp_I(S,"HEAD",q-S) )
      rqst->method = HTTPD_HEAD_METHOD;
    else if ( !strncmp_I(S,"PUT",q-S) )
      rqst->method = HTTPD_PUT_METHOD;
    else if ( !strncmp_I(S,"DELETE",q-S) )
      rqst->method = HTTPD_DELETE_METHOD;
    else
      rqst->method = 0;
    
    S = q;
    while ( *S && Isspace(*S) ) ++S;
    q = S;
    while ( *q && !Isspace(*q) ) ++q;
    
    rqst->uri = Str_Range_Npl(S,q);
    
    S = q;
    while ( *S && Isspace(*S) ) ++S;
    q = S;
    while ( *q && !Isspace(*q) ) ++q;
    
    if ( !strncmp_I(S,"HTTP/1.",7) )
      rqst->httpver = strtol(S+7,0,10);
  }

void Httpd_Analyze_Headers(char *text,YOYO_DICTO *dct)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    int i;
    char *q, *Q, *S = text;
    while (*S!='\n') ++S; /* skip HTTP/1.x query line */
    q = ++S;
    for (;;)
      {
        while ( *q != '\n' ) ++q;
        *q = 0;
        for ( i = 1; q-i > S && Isspace(q[-i]); ++i ) q[-i] = 0;
        while (Isspace(*S)) ++S;
        if ( !*S ) break; /* empty line => end of headers*/
        Q = S;
        while ( *Q && *Q != ':' ) { *Q = toupper(*Q); ++Q; }
        if ( *Q == ':' )
          {
            *Q = 0;
            for ( i = 1; Q-i > S && Isspace(Q[-i]); ++i ) Q[-i] = 0;
            ++Q;
            while ( Isspace(*Q) ) ++Q;
            Dicto_Put(dct,S,(Q=Str_Copy_Npl(Q,-1)));
          }
        S = ++q;
      }
  }
#endif
  ;

int Cbk_Httpd_Getting_Request(void *_rqst, int status, int count)
  {
    int i;
    YOYO_HTTPD_REQUEST *rqst = _rqst;
    YOYO_BUFFER *bf = rqst->bf;

    if ( status == ASIO_TIMER )
      return rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_STAT_TIMER),0;
    if ( !ASIO_SUCCEEDED(status) )
      return rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_STAT_IOFAIL),
             Tcp_Close(rqst->sok),0;

    bf->count += count;

    if ( bf->count >= HTTPD_MAX_REQUEST_LENGTH )
      return rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_STAT_LONGRQST),
             Tcp_Close(rqst->sok),0;

    i = rqst->nline; 
  
  next_line:
    
    while ( i < bf->count && bf->at[i] != '\n' ) ++i;
    
    if ( bf->at[i] != '\n' )
      Tcp_Asio_Recv(rqst->sok,bf->at+bf->count,bf->capacity-bf->count,1,rqst,Cbk_Httpd_Getting_Request);
    else
      {
        if ( !rqst->nline )
          { rqst->nline = ++i; goto next_line; }
        else
          {
            int nonempty = 0;
            ++i;
            while ( rqst->nline < i )
              { nonempty |= !Isspace(bf->at[rqst->nline]); ++rqst->nline; }
            if ( nonempty )
              goto next_line;
            Httpd_Analyze_Qline(bf->at,rqst);
            Httpd_Analyze_Headers(bf->at,rqst->qhdr);
            if ( rqst->method == HTTPD_POST_METHOD 
              || rqst->method == HTTPD_PUT_METHOD )
              {
                memmove(bf->at,bf->at+rqst->nline,bf->count-rqst->nline);
                bf->count -= rqst->nline;
                rqst->left = Str_To_Int(Dicto_Get(rqst->qhdr,"CONTENT-LENGTH","0"));
                rqst->instrm_type = Str_Trim_Copy_Npl(Dicto_Get(rqst->qhdr,"CONTENT-TYPE","text/html"),-1);
                if ( bf->count >= rqst->left )
                  {
                    bf->count = rqst->left;
                    Httpd_Perform_Request(rqst);
                  }
                else
                  {
                    int L;
                    rqst->left -= bf->count;
                    Buffer_Grow_Reserve(bf,HTTPD_MAXBUF_POSTDATA_LENGTH);      
                    L = Yo_Minu(bf->capacity-bf->count,rqst->left);
                    Tcp_Asio_Recv(rqst->sok,bf->at+bf->count,L,L,rqst,Cbk_Httpd_Getting_Postdta);
                  }                
              }
            else if ( rqst->method == HTTPD_GET_METHOD 
              || rqst->method == HTTPD_HEAD_METHOD 
              || rqst->method == HTTPD_DELETE_METHOD )
              {
                Httpd_Perform_Request(rqst);
              }
            else
              return rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_STAT_BADMETHOD),
                     Tcp_Close(rqst->sok),0;

          }
      }

    return 0;
  }

int Cbk_Httpd_Accept(void *_httpd,int status,YOYO_TCPSOK *sok)
  {
    YOYO_HTTPD *httpd = _httpd;

    if ( status == ASIO_TIMER )
      return httpd->callback(httpd->obj,0,HTTPD_STAT_TIMER),0;

    if ( !ASIO_SUCCEEDED(status) )
      return httpd->callback(httpd->obj,0,HTTPD_STAT_ACCEPTFAIL),
              0;
    else
      {
        YOYO_HTTPD_REQUEST *rqst;
        Tcp_Asio_Accept(httpd->sok,httpd,Cbk_Httpd_Accept);
        rqst = Httpd_Request(httpd,sok);
        if ( HTTPD_ACCEPT == httpd->callback(httpd->obj,rqst,HTTPD_RQST_CONNECT) )
          Tcp_Asio_Recv(rqst->sok,rqst->bf->at,rqst->bf->capacity,1,rqst,Cbk_Httpd_Getting_Request);
        else
          httpd->callback(httpd->obj,rqst,HTTPD_STAT_REJECTED);
      }

    return 0;
  }

void Httpd_Listen(YOYO_HTTPD *httpd, char *host, int port)
  {
    httpd->sok = __Refe(Tcp_Listen(TCPSOK_ASYNC,host,port,0));
    free(httpd->host);
    httpd->host = Str_Copy_Npl(host,-1);
    httpd->port = port;
    Tcp_Asio_Accept(httpd->sok,httpd,Cbk_Httpd_Accept);
  }

void Http_Shutdown(YOYO_HTTPD *httpd)
  {
    Tcp_Asio_Shutdown(httpd->sok);
  }

void YOYO_HTTPD_Destruct(YOYO_HTTPD *httpd)
  {
    STRICT_REQUIRE(httpd->rqst == 0);
    free(httpd->host);
    __Unrefe(httpd->obj);
    __Unrefe(httpd->sok);
    __Destruct(httpd);
  }

YOYO_HTTPD *Httpd_Server(void *obj, httpd_callback_t callback)
  {
    YOYO_HTTPD *httpd = __Object_Dtor(sizeof(YOYO_HTTPD),YOYO_HTTPD_Destruct);
    httpd->obj  = __Refe(obj);
    httpd->callback = callback;
    return httpd;
  }

#endif /* C_once_BE85262D_CDA8_4AF5_B684_8A30EB6D7370 */

Changes to logout.hc.

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
...
118
119
120
121
122
123
124

125
126
127


128
129
130
131
132
133
134
...
204
205
206
207
208
209
210

211
212
213
214
215
216
217
...
220
221
222
223
224
225
226

227
228
229
230
231
232
233
...
235
236
237
238
239
240
241

242
243
244
245
246
247
248
...
250
251
252
253
254
255
256

257
258
259
260
261
262
263
  };

#ifdef _YOYO_LOGOUT_BUILTIN
static clock_t YOYO_Log_Clock = 0;
static int YOYO_Log_Line_No = 0;
static int YOYO_Log_Fd = -1;
static int YOYO_Log_Opt = 0;
int YOYO_Log_Level = YOYO_LOG_ERROR;
/* static int YOYO_Log_Pid = 0; */
#else
int YOYO_Log_Level;
#endif

enum
  {
................................................................................
#endif
  ;
  
void Set_Logout_Opt(int opt)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    YOYO_Log_Opt = opt;

  }
#endif
  ;



void Logout(int level, char *text)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    if ( level <= YOYO_Log_Level )
      __Xchg_Interlock
        {        
................................................................................
        free(text);
        va_end(va);
      }
  }
#endif
  ;


#define Log_Debug if (YOYO_Log_Level<YOYO_LOG_DEBUG); else Log_Debug_
void Log_Debug_(char *fmt, ...)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    va_list va;
    char *text;
    va_start(va,fmt);
................................................................................
    free(text);
    va_end(va);
  }
#endif
  ;



#define Log_Info if (YOYO_Log_Level<YOYO_LOG_INFO); else Log_Info_
void Log_Info_(char *fmt, ...)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    va_list va;
    char *text;
    va_start(va,fmt);
................................................................................
    Logout(YOYO_LOG_INFO,text);
    free(text);
    va_end(va);
  }
#endif
  ;


#define Log_Warning if (YOYO_Log_Level<YOYO_LOG_WARN); else Log_Warning_
void Log_Warning_(char *fmt, ...)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    va_list va;
    char *text;
    va_start(va,fmt);
................................................................................
    Logout(YOYO_LOG_WARN,text);
    free(text);
    va_end(va);
  }
#endif
  ;


/*#define Log_Error if (YOYO_Log_Level<YOYO_LOG_ERROR); else Log_Error_*/
void Log_Error(char *fmt, ...)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    va_list va;
    char *text;
    va_start(va,fmt);







|







 







>



>
>







 







>







 







>







 







>







 







>







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
...
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
...
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
  };

#ifdef _YOYO_LOGOUT_BUILTIN
static clock_t YOYO_Log_Clock = 0;
static int YOYO_Log_Line_No = 0;
static int YOYO_Log_Fd = -1;
static int YOYO_Log_Opt = 0;
int YOYO_Log_Level = YOYO_LOG_INFO;
/* static int YOYO_Log_Pid = 0; */
#else
int YOYO_Log_Level;
#endif

enum
  {
................................................................................
#endif
  ;
  
void Set_Logout_Opt(int opt)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    YOYO_Log_Opt = opt;
    YOYO_Log_Level = opt & 0x0ff;
  }
#endif
  ;

#define Log_Level(L) (YOYO_Log_Level<L)

void Logout(int level, char *text)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    if ( level <= YOYO_Log_Level )
      __Xchg_Interlock
        {        
................................................................................
        free(text);
        va_end(va);
      }
  }
#endif
  ;

#define Logout_Debug(S) if (YOYO_Log_Level<YOYO_LOG_DEBUG); else Logout(YOYO_LOG_DEBUG,S)
#define Log_Debug if (YOYO_Log_Level<YOYO_LOG_DEBUG); else Log_Debug_
void Log_Debug_(char *fmt, ...)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    va_list va;
    char *text;
    va_start(va,fmt);
................................................................................
    free(text);
    va_end(va);
  }
#endif
  ;


#define Logout_Info(S) if (YOYO_Log_Level<YOYO_LOG_INFO); else Logout(YOYO_LOG_INFO,S)
#define Log_Info if (YOYO_Log_Level<YOYO_LOG_INFO); else Log_Info_
void Log_Info_(char *fmt, ...)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    va_list va;
    char *text;
    va_start(va,fmt);
................................................................................
    Logout(YOYO_LOG_INFO,text);
    free(text);
    va_end(va);
  }
#endif
  ;

#define Logout_Warning(S) if (YOYO_Log_Level<YOYO_LOG_WARN); else Logout(YOYO_LOG_WARN,S)
#define Log_Warning if (YOYO_Log_Level<YOYO_LOG_WARN); else Log_Warning_
void Log_Warning_(char *fmt, ...)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    va_list va;
    char *text;
    va_start(va,fmt);
................................................................................
    Logout(YOYO_LOG_WARN,text);
    free(text);
    va_end(va);
  }
#endif
  ;

#define Logout_Error(S) if (YOYO_Log_Level<YOYO_LOG_ERROR); else Logout(YOYO_LOG_ERROR,S)
/*#define Log_Error if (YOYO_Log_Level<YOYO_LOG_ERROR); else Log_Error_*/
void Log_Error(char *fmt, ...)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    va_list va;
    char *text;
    va_start(va,fmt);

Added mime.hc.







































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243

/*

Copyright © 2010-2012, Alexéy Sudachén, alexey@sudachen.name, Chile

In USA, UK, Japan and other countries allowing software patents:

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    http://www.gnu.org/licenses/

Otherwise:

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

Except as contained in this notice, the name of a copyright holder shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization of the copyright holder.

*/

#ifndef C_once_E5DC0CBD_6EF6_4E8C_A4F5_CF78FA971011
#define C_once_E5DC0CBD_6EF6_4E8C_A4F5_CF78FA971011

#include "yoyo.hc"
#include "string.hc"

#ifdef _LIBYOYO
#define _YOYO_MIME_BUILTIN
#endif

#ifdef _YOYO_MIME_BUILTIN
  #define _YOYO_MIME_EXTERN 
#else
  #define _YOYO_MIME_EXTERN extern
#endif

enum
  {
    YOYO_MIME_NONE  = __FOUR_CHARS('`','`','`','`'),
    YOYO_MIME_OCTS  = __FOUR_CHARS('O','C','T','S'),
    YOYO_MIME_JPEG  = __FOUR_CHARS('J','P','E','G'),
    YOYO_MIME_PNG   = __FOUR_CHARS('x','P','N','G'),
    YOYO_MIME_GIF   = __FOUR_CHARS('x','G','I','F'),
    YOYO_MIME_PICT  = __FOUR_CHARS('P','I','C','T'),
    YOYO_MIME_HTML  = __FOUR_CHARS('H','T','M','L'),
    YOYO_MIME_TEXT  = __FOUR_CHARS('T','E','X','T'),
    YOYO_MIME_GZIP  = __FOUR_CHARS('G','Z','I','P'),
    YOYO_MIME_PKZIP = __FOUR_CHARS('x','Z','I','P'),
    YOYO_MIME_7ZIP  = __FOUR_CHARS('7','Z','I','P'),
    YOYO_MIME_APP   = __FOUR_CHARS('x','A','P','P'),
    YOYO_MIME_JS    = __FOUR_CHARS('x','x','J','S'),
    YOYO_MIME_CSS   = __FOUR_CHARS('x','C','S','S'),
    YOYO_MIME_EXE   = __FOUR_CHARS('x','E','X','E'),
    YOYO_MIME_UNKNOWN = -1,
  };

typedef struct _YOYO_EXT_MAP_RECORD
  {
    char *ext;
    int   extlen;
    int   code;
  } YOYO_EXT_MAP_RECORD; 

_YOYO_MIME_EXTERN YOYO_EXT_MAP_RECORD Mime_Ext_Map[] 
#ifdef _YOYO_MIME_BUILTIN
  = { 
    {".html", 5, YOYO_MIME_HTML},
    {".htm",  4, YOYO_MIME_HTML},
    {".txt",  4, YOYO_MIME_TEXT},
    {".jpeg", 5, YOYO_MIME_JPEG},
    {".jpg",  4, YOYO_MIME_JPEG},
    {".png",  4, YOYO_MIME_PNG},
    {".gif",  4, YOYO_MIME_GIF},
    {".zip",  4, YOYO_MIME_PKZIP},
    {".7z",   3, YOYO_MIME_7ZIP},
    {".gz",   3, YOYO_MIME_GZIP},
    {".exe",  4, YOYO_MIME_APP},
    {".js",   3, YOYO_MIME_JS},
    {".css",  4, YOYO_MIME_CSS},
    
    {0,0}
  }
#endif
  ;

int Mime_Code_Of_Path(char *path, int dflt)
#ifdef _YOYO_MIME_BUILTIN
  {
    YOYO_EXT_MAP_RECORD *R = Mime_Ext_Map;
    int L = strlen(path);
    for ( ; R->ext; ++R )
      {
        if ( L >= R->extlen && !strncmp_I(path+L-R->extlen,R->ext,R->extlen) )
          return R->code;
      }
    return dflt;
  }
#endif
  ;
  
int Mime_Code_Of(char *mime_type)
#ifdef _YOYO_MIME_BUILTIN
  {
    int i;
    char S[80] = {0};
    for ( i = 0; mime_type[i] && i < sizeof(S)-1; ++i ) S[i] = Tolower(mime_type[i]);
    if ( !strncmp(S,"application/",12) )
      {
        if ( !strcmp(S+12,"octet-stream") ) return YOYO_MIME_OCTS;
        if ( !strcmp(S+12,"x-javascript") ) return YOYO_MIME_JS;
        if ( !strcmp(S+12,"x-msdownload") ) return YOYO_MIME_EXE;
        return YOYO_MIME_APP;
      }
    else if ( !strncmp(S,"text/",5) )
      {
        if ( !strcmp(S+7,"html") ) return YOYO_MIME_HTML;
        if ( !strcmp(S+7,"css") ) return YOYO_MIME_CSS;
        if ( !strcmp(S+7,"javascript") ) return YOYO_MIME_JS;
        else return YOYO_MIME_TEXT;
      }
    else if ( !strncmp(S,"image/",6) )
      {
        if ( !strcmp(S+6,"jpeg") ) return YOYO_MIME_JPEG;
        if ( !strcmp(S+6,"png") )  return YOYO_MIME_PNG;
        if ( !strcmp(S+6,"gif") )  return YOYO_MIME_GIF;
        return YOYO_MIME_PICT;
      }
    return YOYO_MIME_NONE;
  }
#endif
  ;

int Mime_Is_Image(int mime)
#ifdef _YOYO_MIME_BUILTIN
  {
    switch(mime)
      {
        case YOYO_MIME_JPEG:  
        case YOYO_MIME_PNG:   
        case YOYO_MIME_GIF: 
        case YOYO_MIME_PICT: 
          return 1;
      }
    return 0;
  }
#endif
  ;
  
int Mime_Is_Compressed(int mime)
#ifdef _YOYO_MIME_BUILTIN
  {
    switch(mime)
      {
        case YOYO_MIME_JPEG:  
        case YOYO_MIME_PNG:   
        case YOYO_MIME_GIF: 
        case YOYO_MIME_GZIP: 
        case YOYO_MIME_PKZIP: 
        case YOYO_MIME_7ZIP: 
          return 1;
      }
    return 0;
  }
#endif
  ;
  
int Mime_Is_Text(int mime)
#ifdef _YOYO_MIME_BUILTIN
  {
    switch(mime)
      {
        case YOYO_MIME_HTML:
        case YOYO_MIME_TEXT:
        case YOYO_MIME_JS:
        case YOYO_MIME_CSS:
          return 1;
      }
    return 0;
  }
#endif
  ;
  
int Mime_Is_Binary(int mime)
#ifdef _YOYO_MIME_BUILTIN
  {
    return !Mime_Is_Text(mime);
  }
#endif
  ;
  
#define Mime_String_Of_Npl(Mime) Str_Copy_Npl(Mime_String_Of(Mime),-1)
char *Mime_String_Of(int mime)
#ifdef _YOYO_MIME_BUILTIN
  {
    switch(mime)
      {
        case YOYO_MIME_OCTS: return "application/octet-stream";
        case YOYO_MIME_JPEG: return "image/jpeg";
        case YOYO_MIME_PNG:  return "image/png";
        case YOYO_MIME_GIF:  return "image/gif";
        case YOYO_MIME_PICT: return "image/octet-stream";
        case YOYO_MIME_HTML: return "text/html";
        case YOYO_MIME_TEXT: return "text/plain";
        case YOYO_MIME_GZIP: return "application/x-gzip";
        case YOYO_MIME_PKZIP:return "application/zip";
        case YOYO_MIME_7ZIP: return "application/x-7zip";
        case YOYO_MIME_APP:  return "application/octet-stream";
        case YOYO_MIME_CSS:  return "text/css";
        case YOYO_MIME_JS:   return "text/javascript";
        case YOYO_MIME_EXE:  return "application/x-msdownload";
      }
    return "application/octet-stream";
  }
#endif
  ;
  
#endif /* C_once_E5DC0CBD_6EF6_4E8C_A4F5_CF78FA971011 */

Changes to pefile.hc.

47
48
49
50
51
52
53

54
55
56
57
58
59
60
...
741
742
743
744
745
746
747




































748
749
750
751
752
753
#define C_once_EA617668_2E48_4AC6_9079_699B387A0662

#ifdef _LIBYOYO
#define _YOYO_PEFILE_BUILTIN
#endif

#include "yoyo.hc"


// The Machine field has one of the following values that specifies its CPU type. 
// An image file can be run only on the specified machine or on a system that emulates the specified machine.

enum _PE_MACHINE
  {
    PE_FILE_MACHINE_UNKNOWN   = 0x0,    // The contents of this field are assumed to be applicable to any machine type
................................................................................
      {
        if ( E->SizeOfRawData && E->PointerToRawData )
          return Pe_Align_To_File(pe,E->PointerToRawData + E->SizeOfRawData);
      }
      
    return 0;
  }




































#endif
  ;

#endif /* C_once_EA617668_2E48_4AC6_9079_699B387A0662 */









>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
...
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
#define C_once_EA617668_2E48_4AC6_9079_699B387A0662

#ifdef _LIBYOYO
#define _YOYO_PEFILE_BUILTIN
#endif

#include "yoyo.hc"
#include "file.hc"

// The Machine field has one of the following values that specifies its CPU type. 
// An image file can be run only on the specified machine or on a system that emulates the specified machine.

enum _PE_MACHINE
  {
    PE_FILE_MACHINE_UNKNOWN   = 0x0,    // The contents of this field are assumed to be applicable to any machine type
................................................................................
      {
        if ( E->SizeOfRawData && E->PointerToRawData )
          return Pe_Align_To_File(pe,E->PointerToRawData + E->SizeOfRawData);
      }
      
    return 0;
  }
#endif
  ;

void *Pe_Read_NT_Headers(char *filename,int magic)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    PE_DOS_HEADER dos;
    void *hdr = __Zero_Malloc(sizeof(PE_HEADERS_64));
    YOYO_CFILE *f = Cfile_Open(filename,"r");
    Cfile_Read(f,&dos,sizeof(dos),sizeof(dos));
    if ( dos.e_magic != PE_DOS_SIGNATURE )
      __Raise(YOYO_ERROR_INCONSISTENT,"MZ signature doesn´t match");
    Cfile_Seek(f,dos.e_lfanew,0);
    Cfile_Read(f,hdr,sizeof(PE_HEADERS_64),sizeof(PE_HEADERS_64));
    if ( ((PE_HEADERS_64*)hdr)->Signature != PE_NT_SIGNATURE )
      __Raise(YOYO_ERROR_INCONSISTENT,"PE signature doesn´t match");
    if ( ((PE_HEADERS_64*)hdr)->OptionalHeader.Magic != magic )
      __Raise(YOYO_ERROR_INCONSISTENT,"magic doesn´t match");
    return hdr;
  }
#endif
  ;

PE_HEADERS_32 *Pe_Read_NT_Headers_32(char *filename)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    return (PE_HEADERS_32*)Pe_Read_NT_Headers(filename,PE_OPT32_MAGIC);
  }
#endif
  ;
  
PE_HEADERS_64 *Pe_Read_NT_Headers_64(char *filename)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    return (PE_HEADERS_64*)Pe_Read_NT_Headers(filename,PE_OPT64_MAGIC);
  }
#endif
  ;

#endif /* C_once_EA617668_2E48_4AC6_9079_699B387A0662 */


Added pipex.hc.



































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321

/*

Copyright © 2010-2011, Alexéy Sudachén, alexey@sudachen.name, Chile

In USA, UK, Japan and other countries allowing software patents:

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    http://www.gnu.org/licenses/

Otherwise:

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

Except as contained in this notice, the name of a copyright holder shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization of the copyright holder.

*/

#include "yoyo.hc"
#include "file.hc"

#ifdef __windoze
typedef HANDLE process_t;
#else
typedef int process_t;
#endif

#ifdef _LIBYOYO
#define _YOYO_PIPEX_BUILTIN
#endif

#ifdef _YOYO_PIPEX_BUILTIN
  #define YOYO_PIPEX_EXTERN
#else
  #define YOYO_PIPEX_EXTERN extern
#endif

#define INVALID_PROCESS_ID ((process_t)0)
enum { PIPEX_STILL_ACTIVE = -1, PIPEX_WAS_TERMINATED = -2 };

typedef struct _YOYO_PIPEX
  {
    char *command;
    YOYO_CFILE *fin;
    YOYO_CFILE *fout;
    YOYO_CFILE *ferr;
    process_t pid;
    int exitcode;
  } YOYO_PIPEX;

#ifdef __windoze

typedef struct _YOYO_PIPEX_WINPIPE
  {
    HANDLE pin;
    HANDLE pout;
    HANDLE xhndl;
  }YOYO_PIPEX_WINPIPE;

void YOYO_PIPEX_WINPIPE_Destruct(YOYO_PIPEX_WINPIPE *wp)
#ifdef _YOYO_PIPEX_BUILTIN
  {
    if ( wp->pin && wp->pin != INVALID_HANDLE_VALUE )
      CloseHandle(wp->pin);
    if ( wp->pout && wp->pout != INVALID_HANDLE_VALUE )
      CloseHandle(wp->pout);
    if ( wp->xhndl && wp->xhndl != INVALID_HANDLE_VALUE )
      CloseHandle(wp->xhndl);
    __Destruct(wp);
  }
#endif
  ;
  
#endif

YOYO_PIPEX_EXTERN char *PIPEX_NONE
#ifdef _YOYO_PIPEX_BUILTIN
  = (char*)-1
#endif
  ;

YOYO_PIPEX_EXTERN char *PIPEX_WRAP
#ifdef _YOYO_PIPEX_BUILTIN
  = (char*)0
#endif
  ;

YOYO_PIPEX_EXTERN char *PIPEX_TMPFILE
#ifdef _YOYO_PIPEX_BUILTIN
  = (char*)-2
#endif
  ;

#define PIPEX_TMPFILE(X) PIPEX_TMPFILE_GEN(X)
char *PIPEX_TMPFILE_GEN(char *fname)
#ifdef _YOYO_PIPEX_BUILTIN
  {
    return Str_Concat("~*",fname);
  }
#endif
  ;
  
void Pipex_Kill(YOYO_PIPEX *pipex)
#ifdef _YOYO_PIPEX_BUILTIN
  {
    if ( pipex->pid != INVALID_PROCESS_ID )
      {
        pipex->exitcode = PIPEX_WAS_TERMINATED;
        TerminateProcess(pipex->pid,255);
        CloseHandle(pipex->pid);
        pipex->pid = INVALID_PROCESS_ID;
      }
    __Unrefe(pipex->fin);
    __Unrefe(pipex->fout);
    __Unrefe(pipex->ferr);
  }
#endif
  ;
  
void YOYO_PIPEX_Destruct(YOYO_PIPEX *pipex)
#ifdef _YOYO_PIPEX_BUILTIN
  {
    Pipex_Kill(pipex);
    __Destruct(pipex);
  }
#endif
  ;
  
void Pipex_Init_Pipe(YOYO_PIPEX_WINPIPE **x, char *xstd, HANDLE *ystd, int wr)
#ifdef _YOYO_PIPEX_BUILTIN
  {
    SECURITY_ATTRIBUTES saa = {0};
    saa.nLength = sizeof(SECURITY_ATTRIBUTES);
    *x = __Object_Dtor(sizeof(YOYO_PIPEX_WINPIPE),YOYO_PIPEX_WINPIPE_Destruct);
    if ( xstd == PIPEX_WRAP )
      {
        if ( !CreatePipe(&(*x)->pin, &(*x)->pout, &saa, 0))
          __Raise_System_Error();
        *ystd = !wr ? (*x)->pin : (*x)->pout;
      }
    else if ( xstd == PIPEX_NONE )
      ;
    else
      {
        int flags = 0;
        HANDLE *xhndl = &(*x)->xhndl;
        
        if ( xstd == PIPEX_TMPFILE )
          {
            xstd = Str_Unicode_To_Utf8(_wtempnam(0,L"~pipex."));
            xhndl = &(*x)->pin;
            flags |= FILE_FLAG_DELETE_ON_CLOSE;
          } 
        else if ( Str_Starts_With(xstd,"~*") )
          {
            xstd = Str_Unicode_To_Utf8(_wtempnam(0,Str_Utf8_To_Unicode(xstd+2)));
            xhndl = &(*x)->pin;
            flags |= FILE_FLAG_DELETE_ON_CLOSE;
          }
        else if ( Str_Starts_With(xstd,"~") )
          {
            xhndl = &(*x)->pin;
            flags |= FILE_FLAG_DELETE_ON_CLOSE;
          }
          
        *xhndl = *ystd = CreateFileW(Str_Utf8_To_Unicode(xstd),
                            (wr?GENERIC_WRITE:0)|GENERIC_READ,
                            (wr?FILE_SHARE_WRITE:0)|FILE_SHARE_READ,0,
                            (wr?CREATE_ALWAYS:OPEN_EXISTING),
                            flags,0
                            );
                            
        if ( *ystd == INVALID_HANDLE_VALUE )
          __Raise_System_Error();
      }
   }
#endif
  ;

YOYO_CFILE *Pipex_Cfile(YOYO_PIPEX_WINPIPE *wp, int wr)
#ifdef _YOYO_PIPEX_BUILTIN
  {
    if ( !(!wr?wp->pin:wp->pout) )
      return 0;
    else
      {
        void *ret;
        int foo = _open_osfhandle((longptr_t)(!wr?wp->pin:wp->pout), (!wr?(_O_RDONLY|_O_BINARY):(_O_WRONLY|_O_BINARY)) );
        FILE *f = _fdopen(foo,!wr?"rb":"wb");
        ret = Cfile_Object(f,"pipex",0);
        if ( !wr )  wp->pin = 0; else wp->pout = 0;
        return ret;
      }
  }
#endif
  ;
  
YOYO_PIPEX *Pipex_Exec(char *command, char *xstdin, char *xstdout, char *xstderr)
#ifdef _YOYO_PIPEX_BUILTIN
  {
    YOYO_PIPEX *pipex = 0;
    __Auto_Ptr(pipex)
      {
        int foo;
        PROCESS_INFORMATION piProcInfo = {0};
        STARTUPINFOW siStartInfo = {0};
        STARTUPINFOW siStartInfo1 = {0};
        
        YOYO_PIPEX_WINPIPE *xin = 0, *xout = 0, *xerr = 0;
        wchar_t *comspec = __Zero_Malloc(257*sizeof(wchar_t));
        
        pipex = __Object_Dtor(sizeof(YOYO_PIPEX),YOYO_PIPEX_Destruct);

        siStartInfo1.cb = sizeof(STARTUPINFOW);
        siStartInfo1.dwFlags    = STARTF_USESTDHANDLES;
        GetStartupInfoW(&siStartInfo1);
        siStartInfo.hStdInput  = siStartInfo1.hStdInput;
        siStartInfo.hStdOutput = siStartInfo1.hStdOutput;
        siStartInfo.hStdError  = siStartInfo1.hStdError;
        
        Pipex_Init_Pipe(&xin,  xstdin,  &siStartInfo.hStdInput,  0);
        Pipex_Init_Pipe(&xout, xstdout, &siStartInfo.hStdOutput, 1);
        Pipex_Init_Pipe(&xerr, xstderr, &siStartInfo.hStdError,  1);

        siStartInfo.cb = sizeof(STARTUPINFOW);
        siStartInfo.dwFlags    = STARTF_USESTDHANDLES;
        siStartInfo.wShowWindow = SW_HIDE;
        
        if ( !siStartInfo.hStdInput )  siStartInfo.hStdInput  = GetStdHandle(STD_INPUT_HANDLE);
        if ( !siStartInfo.hStdOutput ) siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
        if ( !siStartInfo.hStdError )  siStartInfo.hStdError  = GetStdHandle(STD_ERROR_HANDLE);

        SetHandleInformation(siStartInfo.hStdInput, HANDLE_FLAG_INHERIT,HANDLE_FLAG_INHERIT);
        SetHandleInformation(siStartInfo.hStdOutput,HANDLE_FLAG_INHERIT,HANDLE_FLAG_INHERIT);
        SetHandleInformation(siStartInfo.hStdError, HANDLE_FLAG_INHERIT,HANDLE_FLAG_INHERIT);
          
        GetEnvironmentVariableW(L"COMSPEC", comspec, 256);

        if (!CreateProcessW(NULL,
            Str_Utf8_To_Unicode(__Format("\"%s\" /c %s",Str_Unicode_To_Utf8(comspec),command)),
            NULL,
            NULL,
            TRUE,
            0,//CREATE_NO_WINDOW,
            NULL,
            NULL,
            &siStartInfo,
            &piProcInfo))
          {
            __Raise_System_Error();
          }

        CloseHandle(piProcInfo.hThread);
        pipex->pid = piProcInfo.hProcess;

        pipex->fin  = __Refe(Pipex_Cfile(xin, 1));
        pipex->fout = __Refe(Pipex_Cfile(xout,0));
        pipex->ferr = __Refe(Pipex_Cfile(xerr,0));
      
      }      
    
    return pipex;
  }
#endif
  ;
  
int Pipex_Exit_Code(YOYO_PIPEX *pipex)
#ifdef _YOYO_PIPEX_BUILTIN
  {
    unsigned long ecode;
    if ( pipex->pid != INVALID_PROCESS_ID )
      if ( GetExitCodeProcess(pipex->pid,&ecode) )
        if ( ecode == STILL_ACTIVE )
          return PIPEX_STILL_ACTIVE;
        else
          pipex->exitcode = ecode;
    return pipex->exitcode;
  }
#endif
  ;
  
int Pipex_Wait(YOYO_PIPEX *pipex, int ms)
#ifdef _YOYO_PIPEX_BUILTIN
  {
    while ( Pipex_Exit_Code(pipex) == PIPEX_STILL_ACTIVE )
      {  
        if ( WaitForSingleObject(pipex->pid,ms) == WAIT_TIMEOUT ) 
          return PIPEX_STILL_ACTIVE;
      }
    return pipex->exitcode;
  }
#endif
  ;
  

Added sar.hc.



























































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221

/*

Copyright © 2010-2011, Alexéy Sudachén, alexey@sudachen.name, Chile

In USA, UK, Japan and other countries allowing software patents:

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    http://www.gnu.org/licenses/
    
Otherwise:

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

Except as contained in this notice, the name of a copyright holder shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization of the copyright holder.

*/

#ifndef C_once_B280024F_42F5_4D98_9F57_2A5BEABC1C88
#define C_once_B280024F_42F5_4D98_9F57_2A5BEABC1C88

#include "yoyo.hc"

#ifdef _LIBYOYO
#define _YOYO_SAR_BUITIN
#endif

typedef struct _YOYO_STRUCTED_ARRAY
  {
    byte_t *at;
    int  count;
    int  allocated;
  } YOYO_STRUCTED_ARRAY;

void *Structed_Array_Insert(YOYO_STRUCTED_ARRAY *arr,void *el,int width,int at, int count)
#ifdef _YOYO_SAR_BUITIN
  {
    STRICT_REQUIRE( arr != 0 );
    if ( at < 0 ) at = arr->count-at+1;
    STRICT_REQUIRE( at >= 0 );
    STRICT_REQUIRE( count >= 0 );
    STRICT_REQUIRE( el != 0 );
    STRICT_REQUIRE( width >= 0 );
    
    arr->count = Yo_Elm_Insert_Npl(&arr->at,at,arr->count,el,count,width,&arr->allocated);
    return arr->at+(at*width);
  }
#endif
  ;
  
int Structed_Array_Remove(YOYO_STRUCTED_ARRAY *arr,int width,int at,int count)
#ifdef _YOYO_SAR_BUITIN
  {
    STRICT_REQUIRE( arr != 0 );
    if ( at < 0 ) at = arr->count-at+1;
    STRICT_REQUIRE( at >= 0 );
    STRICT_REQUIRE( count >= 0 );
    STRICT_REQUIRE( el != 0 );
    STRICT_REQUIRE( width >= 0 );
    STRICT_REQUIRE( count <= arr->count );
    
    if ( arr->count < count && at < arr->count - count )
      memmove(arr->at+at*width,arr->at+(at+count)*width,arr->count-(at+count)*width);
    arr->count -= count;
    return count;
  }
#endif
  ;
  
int Structed_Array_Resize(YOYO_STRUCTED_ARRAY *arr,int width,int count)
#ifdef _YOYO_SAR_BUITIN
  {
    STRICT_REQUIRE( arr != 0 );
    STRICT_REQUIRE( count >= 0 );
    STRICT_REQUIRE( width >= 0 );

    if ( count*width > arr->allocated )
      Yo_Elm_Resize_Npl(&arr->at,count,width,&arr->allocated);
    arr->count = count;        
    return arr->allocated/width;
  }
#endif
  ;
  
int Structed_Array_Reserve(YOYO_STRUCTED_ARRAY *arr,int width,int count)
#ifdef _YOYO_SAR_BUITIN
  {
    STRICT_REQUIRE( arr != 0 );
    STRICT_REQUIRE( count >= 0 );
    STRICT_REQUIRE( width >= 0 );

    if ( count*width > arr->allocated )
      Yo_Elm_Resize_Npl(&arr->at,count,width,&arr->allocated);
    return arr->allocated/width;
  }
#endif
  ;
  
#define STRUCTED_ARRAY(Fpfx,Arr_Tp,Elm_Tp) \
  typedef struct _##Arr_Tp\
    {\
      Elm_Tp *at;\
      int count;\
      int _;\
    } Arr_Tp;\
  Elm_Tp *Fpfx##_Insert(Arr_Tp *arr,Elm_Tp el,int at)\
    {\
      return Structed_Array_Insert((YOYO_STRUCTED_ARRAY*)arr,&el,sizeof(Elm_Tp),at,1);\
    }\
  Elm_Tp *Fpfx##_Insert_Ptr(Arr_Tp *arr,Elm_Tp *el,int at,int count)\
    {\
      return Structed_Array_Insert((YOYO_STRUCTED_ARRAY*)arr,el,sizeof(Elm_Tp),at,count);\
    }\
  Elm_Tp *Fpfx##_Push(Arr_Tp *arr,Elm_Tp el)\
    {\
      return Structed_Array_Insert((YOYO_STRUCTED_ARRAY*)arr,&el,sizeof(Elm_Tp),-1,1);\
    }\
  Elm_Tp *Fpfx##_Push_Ptr(Arr_Tp *arr,Elm_Tp *el,int count)\
    {\
      return Structed_Array_Insert((YOYO_STRUCTED_ARRAY*)arr,el,sizeof(Elm_Tp),-1,count);\
    }\
  Elm_Tp *Fpfx##_Push_Front(Arr_Tp *arr,Elm_Tp el)\
    {\
      return Structed_Array_Insert((YOYO_STRUCTED_ARRAY*)arr,&el,sizeof(Elm_Tp),0,1);\
    }\
  Elm_Tp *Fpfx##_Push_Front_Ptr(Arr_Tp *arr,Elm_Tp *el,int count)\
    {\
      return Structed_Array_Insert((YOYO_STRUCTED_ARRAY*)arr,el,sizeof(Elm_Tp),0,count);\
    }\
  int Fpfx##_Remove(Arr_Tp *arr,int at,int count)\
    {\
      return Structed_Array_Remove((YOYO_STRUCTED_ARRAY*)arr,sizeof(Elm_Tp),at,count);\
    }\
  int Fpfx##_Empty(Arr_Tp *arr)\
    {\
      return !arr->count;\
    }\
  int Fpfx##_Pop(Arr_Tp *arr,Elm_Tp *top)\
    {\
      int result = 0;\
      if ( top && arr->count ) { *top = arr->at[arr->count-1]; result = 1; }\
      Structed_Array_Remove((YOYO_STRUCTED_ARRAY*)arr,sizeof(Elm_Tp),-1,1);\
      return result;\
    }\
  int Fpfx##_Pop_Front(Arr_Tp *arr,Elm_Tp *top)\
    {\
      int result = 0;\
      if ( top && arr->count ) { *top = arr->at[0]; result = 1; }\
      Structed_Array_Remove((YOYO_STRUCTED_ARRAY*)arr,sizeof(Elm_Tp),0,1);\
      return result;\
    }\
  int Fpfx##_Resize(Arr_Tp *arr,int count)\
    {\
      return Structed_Array_Resize((YOYO_STRUCTED_ARRAY*)arr,sizeof(Elm_Tp),count);\
    }\
  int Fpfx##_Reserve(Arr_Tp *arr,int count)\
    {\
      return Structed_Array_Reserve((YOYO_STRUCTED_ARRAY*)arr,sizeof(Elm_Tp),count);\
    }\
  void Arr_Tp##_Destruct(Arr_Tp *arr)\
    {\
      free(arr->at);\
      __Destruct(arr);\
    }\
  Arr_Tp *Fpfx##_Init(int count)\
    {\
      Arr_Tp *arr = __Object_Dtor(sizeof(Arr_Tp),Arr_Tp##_Destruct);\
      if ( count ) Fpfx##_Resize(arr,count);\
      return arr;\
    }

#define STRUCTED_ARRAY_DEF(Fpfx,Arr_Tp,Elm_Tp) \
  typedef struct _##Arr_Tp\
    {\
      Elm_Tp *at;\
      int count;\
      int _;\
    } Arr_Tp;\
  Elm_Tp *Fpfx##_Insert(Arr_Tp *arr,Elm_Tp el,int at);\
  Elm_Tp *Fpfx##_Insert_Ptr(Arr_Tp *arr,Elm_Tp *el,int at,int count);\
  Elm_Tp *Fpfx##_Push(Arr_Tp *arr,Elm_Tp el);\
  Elm_Tp *Fpfx##_Push_Ptr(Arr_Tp *arr,Elm_Tp *el,int count);\
  Elm_Tp *Fpfx##_Push_Front(Arr_Tp *arr,Elm_Tp el);\
  Elm_Tp *Fpfx##_Push_Front_Ptr(Arr_Tp *arr,Elm_Tp *el,int count);\
  int Fpfx##_Remove(Arr_Tp *arr,int at,int count);\
  int Fpfx##_Empty(Arr_Tp *arr);\
  int Fpfx##_Pop(Arr_Tp *arr,Elm_Tp *top);\
  int Fpfx##_Pop_Front(Arr_Tp *arr,Elm_Tp *top);\
  int Fpfx##_Resize(Arr_Tp *arr,int count);\
  int Fpfx##_Reserve(Arr_Tp *arr,int count);\
  void Arr_Tp##_Destruct(Arr_Tp *arr);\
  Arr_Tp *Fpfx##_Init(int count);

#endif /*C_once_B280024F_42F5_4D98_9F57_2A5BEABC1C88*/

Added sar/quad.hc.



























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

/*

Copyright © 2010-2011, Alexéy Sudachén, alexey@sudachen.name, Chile

In USA, UK, Japan and other countries allowing software patents:

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    http://www.gnu.org/licenses/
    
Otherwise:

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

Except as contained in this notice, the name of a copyright holder shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization of the copyright holder.

*/

#ifndef C_once_631AF050_DD3C_45AA_9B7D_1213254067C2
#define C_once_631AF050_DD3C_45AA_9B7D_1213254067C2

#include "../sar.hc"

#ifdef _LIBYOYO
#define YOYO_QUADARRAY_BUILTIN
#endif

#ifdef YOYO_QUADARRAY_BUILTIN
STRUCTED_ARRAY(Qarray,YOYO_QUAD_ARRAY,quad_t);
#else
STRUCTED_ARRAY_DEF(Qarray,YOYO_QUAD_ARRAY,quad_t);
#endif

#endif /*C_once_631AF050_DD3C_45AA_9B7D_1213254067C2*/

Changes to tcpip.hc.

101
102
103
104
105
106
107
108
109
110

111
112
113
114
115
116
117
...
159
160
161
162
163
164
165












166
167
168
169
170
171
172
173
174
175
176
...
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439

#else
#define _WSA_Init()
#endif


#define Ipv4_Format(Ip) __Pool(Ipv4_Format_Npl(Ip))
char *Ipv4_Format_Npl(ipaddr_t ip)
#ifdef _YOYO_TCPIP_BUILTIN
  {

    return __Format_Npl("%d.%d.%d.%d"
              ,(ip&0x0ff)
              ,((ip>>8)&0x0ff)
              ,((ip>>16)&0x0ff)
              ,((ip>>24)&0x0ff));
  }
#endif
................................................................................
#endif
        sok->skt = -1;
      }
  }
#endif
  ;
  












void YOYO_TCPSOK_Destruct(YOYO_TCPSOK *sok)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    Tcp_Close(sok);
    __Destruct(sok);
  }
#endif
  ;
  
int Tcp_Read(YOYO_TCPSOK *sok, void *out, int count, int mincount)
#ifdef _YOYO_TCPIP_BUILTIN  
................................................................................
    if ( status == ASIO_TIMER || !ASIO_SUCCEEDED(status) )
      return ((YOYO_TCPSOK_ACCEPT*)obj)->callback(((YOYO_TCPSOK_ACCEPT*)obj)->obj,status,0);
    else
      {
        struct sockaddr_in *addr = ((struct sockaddr_in*)_addr);
        YOYO_TCPSOK *sok = Tcp_Socket( (status&ASIO_SYNCHRONOUS)?0:TCPSOK_ASYNC );
        sok->ip = addr->sin_addr.s_addr;
        sok->port = addr->sin_port;
        sok->skt = skt;
        if ( sok->async )
          Tcp_Set_Async(sok->skt);
        return ((YOYO_TCPSOK_ACCEPT*)obj)->callback(((YOYO_TCPSOK_ACCEPT*)obj)->obj,status,sok);
      }
  }
#endif







|


>







 







>
>
>
>
>
>
>
>
>
>
>
>



|







 







|







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
...
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452

#else
#define _WSA_Init()
#endif


#define Ipv4_Format(Ip) __Pool(Ipv4_Format_Npl(Ip))
char *Ipv4_Format_Npl(ipaddr_t _ip)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    uint_t ip = (uint_t)_ip;
    return __Format_Npl("%d.%d.%d.%d"
              ,(ip&0x0ff)
              ,((ip>>8)&0x0ff)
              ,((ip>>16)&0x0ff)
              ,((ip>>24)&0x0ff));
  }
#endif
................................................................................
#endif
        sok->skt = -1;
      }
  }
#endif
  ;
  
void Tcp_Graceful_Close(YOYO_TCPSOK *sok)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    if ( sok->skt != INVALID_SOCKET ) 
      {
        shutdown(sok->skt,SB_BOTH);
        Tcp_Close(sok);
      }
  }
#endif
  ;

void YOYO_TCPSOK_Destruct(YOYO_TCPSOK *sok)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    Tcp_Graceful_Close(sok);
    __Destruct(sok);
  }
#endif
  ;
  
int Tcp_Read(YOYO_TCPSOK *sok, void *out, int count, int mincount)
#ifdef _YOYO_TCPIP_BUILTIN  
................................................................................
    if ( status == ASIO_TIMER || !ASIO_SUCCEEDED(status) )
      return ((YOYO_TCPSOK_ACCEPT*)obj)->callback(((YOYO_TCPSOK_ACCEPT*)obj)->obj,status,0);
    else
      {
        struct sockaddr_in *addr = ((struct sockaddr_in*)_addr);
        YOYO_TCPSOK *sok = Tcp_Socket( (status&ASIO_SYNCHRONOUS)?0:TCPSOK_ASYNC );
        sok->ip = addr->sin_addr.s_addr;
        sok->port = ntohs(addr->sin_port);
        sok->skt = skt;
        if ( sok->async )
          Tcp_Set_Async(sok->skt);
        return ((YOYO_TCPSOK_ACCEPT*)obj)->callback(((YOYO_TCPSOK_ACCEPT*)obj)->obj,status,sok);
      }
  }
#endif

Added tests/httpd.c.

























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

/*

Copyright © 2010-2012, Alexéy Sudachén, alexey@sudachen.name, Chile

In USA, UK, Japan and other countries allowing software patents:

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    http://www.gnu.org/licenses/

Otherwise:

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

Except as contained in this notice, the name of a copyright holder shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization of the copyright holder.

*/

#define _LIBYOYO
#include <httpd.hc>
#include <webhost.hc>
#include <webcfg.hc>
#include <xdata.hc>
#include <prog.hc>
#include <defpars.hc>

int main(int argc,char **argv)
  {

    Prog_Init(argc,argv,
      "?|help,"
      "d|debug,"
      "p:|port:,"
      "h:|host:,"
      "r:|doc_root:,"
      "c:|cfg:|config:,"
      "e:|exec_root:,"
      ,PROG_EXIT_ON_ERROR);

    //__Try_Exit(0)
      {
        YOYO_WEBHOST *webhost = Webhost_Init();
        
        __Auto_Release
          {
            int   port = 80;
            char *foo;
            char *host = "127.0.0.1";
            YOYO_XDATA *cfg;
    
            if ( Prog_Has_Opt("debug") ) Set_Logout_Opt(YOYO_LOG_DEBUG);
    
            Webhost_Add_Index(webhost,"index.html");
        
            if ( !!(foo = Prog_First_Opt("cfg",0)) )
              {
                cfg = Def_Parse_File(foo);
                Webhost_Config(webhost,cfg);
                port = Xnode_Value_Get_Int(&cfg->root,"port",0);
                host = Xnode_Value_Get_Str(&cfg->root,"host",host);
              }
              
            port = Prog_First_Opt_Int("port",port);
            host = Prog_First_Opt("host",host);

            if ( !!(foo = Prog_First_Opt("doc_root",0)) )
              Webhost_Set_Doc_Root(webhost,foo);
            if ( !!(foo = Prog_First_Opt("exec_root",0)) )
              Webhost_Set_Exec_Root(webhost,foo);

            Httpd_Listen(Httpd_Server(webhost,Webhost_Callback),host,port);
          }
          
        while ( Asio_Perform_IO(10,0) )
          {
            ;
          }
      }

    return 0;
  }

Changes to url.hc.

61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
..
90
91
92
93
94
95
96






97
98

99
100
101
102
103
104
105
106
...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
...
216
217
218
219
220
221
222





223
224
225
226
227
228
229
    URLX_FILE     = -1,
  };

typedef struct _YOYO_URL 
  {
    char *host, *user, *passw, *query, *args, *anchor, *uri, *endpoint;
    int   port, proto;

  } YOYO_URL;

void YOYO_URL_Destruct(YOYO_URL *url)
#ifdef _YOYO_URL_BUILTIN
  {
    free(url->host);
    free(url->user);
    free(url->passw);
    free(url->query);
    free(url->args);
    free(url->anchor);
    free(url->uri);
    free(url->endpoint);

    __Destruct(url);
  }
#endif
  ;
  
int Url_Proto(char *S)
#ifdef _YOYO_URL_BUILTIN
................................................................................
    if ( !strcmp_I(S,"https") )  return URLX_HTTPS;
    if ( !strcmp_I(S,"file")  )  return URLX_FILE;
    return URLX_UNKNOWN;
  }
#endif
  ;
  






#define Url_Parse(Url) Url_Parse_(Url,0)
#define Url_Parse_Uri(Url) Url_Parse_(Url,1)

YOYO_URL *Url_Parse_(char *url,int uri_only)
#ifdef _YOYO_URL_BUILTIN
  {
    YOYO_URL *urlout = 0;
    __Auto_Ptr(urlout)
      {
        /* proto://user:passwd@host:port/query#anchor?args */
      
................................................................................
        char *query = 0;
        char *anchor= 0;
        char *endpoint = 0;
        int   port  = 0;
        
        while ( *pS && Isspace(*pS) ) ++pS;
        
        if ( !uri_only )
          {
            p = pS;
            while ( *p && Isalpha(*p) ) ++p;
            
            if ( *p && *p == ':' && p[1] && p[1] == '/' && p[2] && p[2] == '/' )
              {
                proto = Str_Range(pS,p);
................................................................................
                char S[13];
                sprintf(S,":%u",port);
                Str_Cat(&endpoint,S,-1);
              }
          }
          
        urlout->endpoint = __Retain(endpoint);





      }
      
    return urlout;
  }
#endif
  ;








>













>







 







>
>
>
>
>
>

|
>
|







 







|







 







>
>
>
>
>







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
..
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
...
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
    URLX_FILE     = -1,
  };

typedef struct _YOYO_URL 
  {
    char *host, *user, *passw, *query, *args, *anchor, *uri, *endpoint;
    int   port, proto;
    YOYO_DICTO *argv;
  } YOYO_URL;

void YOYO_URL_Destruct(YOYO_URL *url)
#ifdef _YOYO_URL_BUILTIN
  {
    free(url->host);
    free(url->user);
    free(url->passw);
    free(url->query);
    free(url->args);
    free(url->anchor);
    free(url->uri);
    free(url->endpoint);
    __Unrefe(args);
    __Destruct(url);
  }
#endif
  ;
  
int Url_Proto(char *S)
#ifdef _YOYO_URL_BUILTIN
................................................................................
    if ( !strcmp_I(S,"https") )  return URLX_HTTPS;
    if ( !strcmp_I(S,"file")  )  return URLX_FILE;
    return URLX_UNKNOWN;
  }
#endif
  ;
  
enum 
  {
    URLX_PARSE_NOHOST = 1,
    URLX_PARSE_ARGUMENTS = 2,
  }

#define Url_Parse(Url) Url_Parse_(Url,0)
#define Url_Parse_Uri(Url) Url_Parse_(Url,URLX_PARSE_NOHOST)
#define Url_Parse_Full(Url) Url_Parse_(Url,URLX_PARSE_ARGUMENTS)
YOYO_URL *Url_Parse_(char *url,int flags)
#ifdef _YOYO_URL_BUILTIN
  {
    YOYO_URL *urlout = 0;
    __Auto_Ptr(urlout)
      {
        /* proto://user:passwd@host:port/query#anchor?args */
      
................................................................................
        char *query = 0;
        char *anchor= 0;
        char *endpoint = 0;
        int   port  = 0;
        
        while ( *pS && Isspace(*pS) ) ++pS;
        
        if ( !(flags&URLX_PARSE_NOHOST)  )
          {
            p = pS;
            while ( *p && Isalpha(*p) ) ++p;
            
            if ( *p && *p == ':' && p[1] && p[1] == '/' && p[2] && p[2] == '/' )
              {
                proto = Str_Range(pS,p);
................................................................................
                char S[13];
                sprintf(S,":%u",port);
                Str_Cat(&endpoint,S,-1);
              }
          }
          
        urlout->endpoint = __Retain(endpoint);
        
        if ( flags & URLX_PARSE_ARGUMENTS )
          {
            urlout->argv = __Refe(Dicto_Ptrs())
          }
      }
      
    return urlout;
  }
#endif
  ;

Added webcfg.hc.

























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

/*

Copyright © 2010-2012, Alexéy Sudachén, alexey@sudachen.name, Chile

In USA, UK, Japan and other countries allowing software patents:

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    http://www.gnu.org/licenses/

Otherwise:

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

Except as contained in this notice, the name of a copyright holder shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization of the copyright holder.

*/

#ifndef C_once_A719E9E5_B5AB_4A78_A061_34860A495936
#define C_once_A719E9E5_B5AB_4A78_A061_34860A495936

#include "webhost.hc"
#include "xdata.hc"

#ifdef _LIBYOYO
#define _YOYO_WEBCFG_BUILTIN
#endif

YOYO_WEBHOST *Webhost_Config(YOYO_WEBHOST *host, YOYO_XDATA *cfg)
#ifdef _YOYO_WEBCFG_BUILTIN
  {
    char *foo;

    if ( !host ) host = Webhost_Init();

    foo = cfg?Xnode_Value_Get_Str(&cfg->root,"doc_root",0):0;
    if ( !foo ) foo = Current_Directory();
    Webhost_Set_Doc_Root(host,foo);
  
    foo = cfg?Xnode_Value_Get_Str(&cfg->root,"exec_root",0):0;
    Webhost_Set_Exec_Root(host,foo);

    return host;
  }
#endif
  ;

#endif /*C_once_A719E9E5_B5AB_4A78_A061_34860A495936*/

Added webhost.hc.





















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538

/*

Copyright © 2010-2012, Alexéy Sudachén, alexey@sudachen.name, Chile

In USA, UK, Japan and other countries allowing software patents:

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    http://www.gnu.org/licenses/

Otherwise:

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

Except as contained in this notice, the name of a copyright holder shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization of the copyright holder.

*/

#ifndef C_once_47E24D4B_C225_4002_B318_6FB9DDE274BE
#define C_once_47E24D4B_C225_4002_B318_6FB9DDE274BE

#include "httpd.hc"
#include "mime.hc"
#include "pipex.hc"
#include "logout.hc"

#ifdef _LIBYOYO
#define _YOYO_WEBHOST_BUILTIN
#endif

enum { WEBHOST_VERSION = 100 };

typedef struct _YOYO_WEBHOST
  {
    char *doc_root;
    char *exec_root;
    YOYO_ARRAY *indexes;
    
    int disable_index: 1;
    
  } YOYO_WEBHOST;
  
void YOYO_WEBHOST_Destruct(YOYO_WEBHOST *host)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    __Unrefe(host->indexes);
    free(host->doc_root);
    free(host->exec_root);
    __Destruct(host);
  }
#endif
  ;
  
YOYO_WEBHOST *Webhost_Init()
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    YOYO_WEBHOST *host = __Object_Dtor(sizeof(YOYO_WEBHOST),YOYO_WEBHOST_Destruct);
    host->indexes = __Refe(Array_Pchars());
    return host;
  }
#endif
  ;
  
YOYO_WEBHOST *Webhost_Set_Doc_Root(YOYO_WEBHOST *host, char *doc_root)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    free(host->doc_root);
    host->doc_root = doc_root?Str_Copy_Npl(doc_root,-1):0;
    return host;
  }
#endif
  ;
  
YOYO_WEBHOST *Webhost_Set_Exec_Root(YOYO_WEBHOST *host, char *exec_root)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    free(host->exec_root);
    host->exec_root = exec_root?Str_Copy_Npl(exec_root,-1):0;
    return host;
  }
#endif
  ;

YOYO_WEBHOST *Webhost_Add_Index(YOYO_WEBHOST *host, char *index)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    Array_Push(host->indexes,Str_Copy_Npl(index,-1));
    return host;
  }
#endif
  ;
  
char *Webhost_Conenttype_Of(char *path)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    int code = Mime_Code_Of_Path(path,YOYO_MIME_OCTS);
    return Mime_String_Of(code);
  }
#endif
  ;
  
int Webhost_Is_Executable(YOYO_BUFFER *bf, int L, YOYO_ARRAY *extL)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    int i;
    
    for ( i = 0; i < extL->count; ++i )
      {
        char *ext = extL->at[i];
        int j = strlen(ext);
        if ( L > j && !strncmp_I(bf->at+(L-j),ext,j) )
          {
            YOYO_FILE_STATS stats = {0};
            if ( File_Get_Stats(bf->at,&stats,1)->f.exists )
              {
                if ( !stats.f.is_directory )
                  return 1;
              }
            break;
          }
      }
    
    return 0;
  }
#endif
  ;
   
int Webhost_Find_Executable_1(YOYO_BUFFER *bf, int L, YOYO_ARRAY *extL)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    int i;
    YOYO_FILE_STATS stats = {0};
    
    bf->at[L] = 0;
    
    if ( File_Get_Stats(bf->at,&stats,1)->f.exists && !stats.f.is_directory )
      return Webhost_Is_Executable(bf,L,extL);
        
    for ( i = 0; i < extL->count; ++i )
      {
        char *ext = extL->at[i];
        bf->at[L] = 0;
        bf->count = L;
        Buffer_Append(bf,ext,-1); 
        if ( File_Get_Stats(bf->at,&stats,1)->f.exists )
          if ( !stats.f.is_directory )
            return 1;
      }
    
    return 0;
  }
#endif
  ;
  
char *Webhost_Find_Executable(char *execdir, char *query, char **script, char **pathinfo)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    char *fpath = 0;
    
    __Auto_Ptr(fpath)
      {
        int i, L;

        YOYO_ARRAY *extL = Str_Split(getenv("PATHEXT"),";");
        YOYO_ARRAY *patL = Str_Split(query,"/");
        YOYO_BUFFER *bf  = Buffer_Acquire(Path_Normilize_Npl(execdir));
        
        L = bf->count;
        
        for ( i = 0; i < patL->count; ++i )
          {
            if ( *(char*)patL->at[i] == 0 ) continue;
            Buffer_Grow(bf,L+1);
            bf->at[L] = YOYO_PATH_SEPARATOR;
            Buffer_Append(bf,patL->at[i],-1);
            L = bf->count;
            if ( Webhost_Find_Executable_1(bf,L,extL) )
              {
                int j;
                L = bf->count+1;
                Buffer_Fill_Append(bf,'\0',1);
                for ( j = 0; j <= i ; ++j ) 
                  {
                    if ( *(char*)patL->at[j] == 0 ) continue;
                    Buffer_Fill_Append(bf,'/',1);
                    Buffer_Append(bf,patL->at[j],-1);
                  }
                j = bf->count+1;
                Buffer_Fill_Append(bf,'\0',1);
                for ( ++i; i < patL->count ; ++i ) 
                  {
                    Buffer_Fill_Append(bf,'/',1);
                    Buffer_Append(bf,patL->at[i],-1);
                  }
                
                fpath = Buffer_Take_Data(bf);
                *script = fpath+L;
                *pathinfo = fpath+j;
                break;
              }
          }
      }
      
    return fpath;    
  }
#endif
  ;
    
void Webhost_Setup_Environment(YOYO_WEBHOST *host, YOYO_HTTPD_REQUEST *rqst, char *path, char *script, char *pathinfo, YOYO_URL *url)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    __Auto_Release
      {    
        char *method = 0;
        
        putenv("GATEWAY_INTERFACE=CGI/1.1");
        putenv("SERVER_PROTOCOL=HTTP/1.1");
        putenv(__Format("SERVER_SOFTWARE=YOYO/WEBHOST/%d",WEBHOST_VERSION));
        putenv(Str_Concat("SCRIPT_NAME=",script));
        putenv(Str_Concat("SCRIPT_FILENAME=",path));
        putenv(Str_Concat("PATH_INFO=",pathinfo));
        putenv(Str_Concat("QUERY_STRING=",url->args));
        
        if ( rqst->instrm_type )
          {
            putenv(__Format("CONTENT_LENGTH=%d",rqst->instrm_length));
            putenv(Str_Concat("CONTENT_TYPE=",rqst->instrm_type));
          }
        else
          {
            putenv("CONTENT_LENGTH=0");
            putenv("CONTENT_TYPE=text/html");
          }
          
        switch(rqst->method)
          {
            case HTTPD_GET_METHOD:  method = "GET";  break;
            case HTTPD_POST_METHOD: method = "POST"; break;
            case HTTPD_HEAD_METHOD: method = "HEAD"; break;
            case HTTPD_PUT_METHOD:  method = "PUT";  break;
          }
        
        putenv(Str_Concat("REQUEST_METHOD=",method));
        putenv(Str_Concat("REMOTE_ADDR=",rqst->remote_addr));
        putenv(Str_Concat("REMOTE_HOST=",rqst->remote_addr));
        putenv(Str_Concat("REQUEST_URI=",url->uri));
        putenv(Str_Concat("DOCUMENT_ROOT=",host->doc_root));
        
        putenv(Str_Concat("HTTP_REFERRER=",Dicto_Get(rqst->qhdr,"REFERRER","")));
        if ( Dicto_Has(rqst->qhdr,"COOKIE") )
          putenv(Str_Concat("HTTP_COOKIE=",Dicto_Get(rqst->qhdr,"COOKIE","")));
        
        //putenv("HTTP_USER_AGENT");
        //putenv("HTTP_ACCEPT_LANGUAGE");

        //putenv("SERVER_NAME");
        //putenv("SERVER_PORT");
      } 
  }
#endif
  ;
  
int Webhost_CGI_Headers(YOYO_HTTPD_REQUEST *rqst, void *strm)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    int retcode = HTTPD_SUCCESS;
    for (;;)
      {
        static char s_Content_Type[] = "Content-Type:";
        static char s_Content_Length[] = "Content-Length:";
        static char s_Location[] = "Location:";
        static char s_Set_Cookie[] = "Set-Cookie:";
        char *S = Oj_Read_Line(strm);
        if ( Str_Is_Empty(S) )
          break;
        if ( !strncmp_I(S,s_Content_Type,sizeof(s_Content_Type)-1) )
          {
            free(rqst->outstrm_type);
            rqst->outstrm_type = Str_Trim_Copy_Npl(S+sizeof(s_Content_Type)-1,-1);
          }
        else if ( !strncmp_I(S,s_Content_Length,sizeof(s_Content_Length)-1) )
          {
            rqst->outstrm_length = strtol(S+sizeof(s_Content_Length)-1,0,0);
          }
        else if ( !strncmp_I(S,s_Location,sizeof(s_Location)-1) )
          {
            rqst->location = Str_Trim_Copy_Npl(S+sizeof(s_Content_Type)-1,-1);
            retcode = HTTPD_REDIRECT;
          }
        else if ( !strncmp_I(S,s_Set_Cookie,sizeof(s_Set_Cookie)-1) )
          {
          }
        else
          {
          }
      }
    return retcode;
  }
#endif
  ;
    
typedef struct _YOYO_WEBHOST_CGIST
  {
    YOYO_WEBHOST *host;
    YOYO_HTTPD_REQUEST *rqst;
    YOYO_URL *url;
    YOYO_PIPEX *pipex;
    char *path;
    char *script;
    char *pathinfo;
  } YOYO_WEBHOST_CGIST;

void YOYO_WEBHOST_CGIST_Destruct(YOYO_WEBHOST_CGIST *st)
  {
    __Unrefe(st->host);
    __Unrefe(st->url);
    __Unrefe(st->rqst);
    __Unrefe(st->pipex);
    free(st->path);
    __Destruct(st);
  }

YOYO_WEBHOST_CGIST *Webhost_CGI_State(YOYO_WEBHOST *host, YOYO_HTTPD_REQUEST *rqst, char *path, char *script, char *pathinfo, YOYO_URL *url)
  {
    YOYO_WEBHOST_CGIST *st = __Object_Dtor(sizeof(YOYO_WEBHOST_CGIST),YOYO_WEBHOST_CGIST_Destruct);
    st->host = __Refe(host);
    st->url  = __Refe(url);
    st->rqst = __Refe(rqst);
    st->path = path;
    st->script = script;
    st->pathinfo = pathinfo;
    return st;
  }
  
void Webhost_Check_CGI_Status(YOYO_WEBHOST_CGIST *st, int status)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    int retcode = 0;
    
    if ( !ASIO_SUCCEEDED(status) ) return;
    
    __Auto_Release 
      {
        __Try_Except
          {
            if (  Pipex_Exit_Code(st->pipex) == PIPEX_STILL_ACTIVE )
              {
                Asio_Alert(0,st,Webhost_Check_CGI_Status);
              }
            else
              if ( st->pipex->exitcode == 0 )
                {
                  YOYO_HTTPD_REQUEST *rqst = st->rqst;
                  YOYO_BUFFER *bf = Buffer_Init(0);
                  YOYO_BUFFER_FILE *fbf = Buffer_As_File(bf);
                  __Unrefe(rqst->outstrm);
                  rqst->outstrm_type = Mime_String_Of_Npl(YOYO_MIME_HTML);
                  rqst->outstrm = __Refe(st->pipex->fout);
                  Oj_Seek(rqst->outstrm,0,0);
                  retcode = Webhost_CGI_Headers(rqst,rqst->outstrm);
                  rqst->outstrm_length = Oj_Available(rqst->outstrm);
                }
              else
                {
                  retcode = 500;
                }
          }
        __Except
          {
            Log_Error("[ERR/EXCEPTION] %s\n%s",__Format_Error(),__Format_Error_Btrace());
            retcode = 500;
          }
      }
        
    if ( retcode )
      Httpd_Continue_Request(st->rqst,retcode);
  }
#endif
  ;
  
int Webhost_Execute_CGI(YOYO_WEBHOST_CGIST *st)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    int retcode = 0;
    
    __Auto_Release 
      {
        char *curdir = Current_Directory();
        
        __Try_Except
          {
            Change_Directory(Path_Dirname(st->path));
            Webhost_Setup_Environment(st->host,st->rqst,st->path,st->script,st->pathinfo,st->url);
            
            st->pipex = __Refe(Pipex_Exec(Path_Basename(st->path),0,PIPEX_TMPFILE,PIPEX_NONE));
            
            if ( st->rqst->instrm )
              {
                int c = Oj_Copy_File(st->rqst->instrm,st->pipex->fin);
                Oj_Flush(st->pipex->fin);
                Oj_Close(st->pipex->fin);
              }
              
            Asio_Alert(0,st,Webhost_Check_CGI_Status);
            retcode = 0;
          }
        __Except
          {
            Log_Error("[ERR/EXCEPTION] %s\n%s",__Format_Error(),__Format_Error_Btrace());
            retcode = 500;
          }

        Change_Directory(curdir);
      }
      
    return retcode;
  }
#endif
  ;
    
int Webhost_Callback(void *_host, YOYO_HTTPD_REQUEST *rqst, int status)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    YOYO_WEBHOST *host = _host;
    
    if ( status == HTTPD_RQST_CONNECT )
      {
        Log_Debug("[%p] CONNECT %s:%d",rqst,rqst->remote_addr,rqst->remote_port);
        return HTTPD_ACCEPT;
      }
    else if ( status == HTTPD_RQST_POSTDTA )
      return HTTPD_ACCEPT;
    else if ( status == HTTPD_RQST_PERFORM )
      {
        YOYO_FILE_STATS stats = {0};
        YOYO_URL *url = Url_Parse_Uri(rqst->uri);
        char *path = 0;

        Log_Info("[%p] %s/1.%d %s",rqst,Httpd_Method_String(rqst->method),rqst->httpver,rqst->uri);
        Logout_Debug(Dicto_Format(rqst->qhdr,Buffer_Print,0,1));
        
        if ( rqst->instrm_length && Log_Level(YOYO_LOG_INFO) )
          {
            enum { MAX_L = 60 };
            int i, L = Yo_Minu(MAX_L,rqst->instrm_length);
            byte_t *b = __Zero_Malloc(MAX_L+1);
            Oj_Seek(rqst->instrm,0,0);
            Oj_Read(rqst->instrm,b,L,L);
            Oj_Seek(rqst->instrm,0,0);
            for ( i = 0; i < L; ++i ) if ( b[i] < 30 || b[i] > 127 ) b[i] = '.';
            if ( rqst->instrm_length > MAX_L ) memcpy(b+MAX_L-3,">>>",3);
            Log_Info("[%p] POSTDTA %s",rqst,b);
          }
        
        if ( host->exec_root )
          {
            char *script = 0, *pathinfo = 0;
            path = Webhost_Find_Executable(host->exec_root,url->query,&script,&pathinfo);
            if ( path )
              return Webhost_Execute_CGI(Webhost_CGI_State(host, rqst, __Retain(path), script, pathinfo, url));
          }
          
        path = Path_Join(host->doc_root,url->query);
        path = Path_Normposix(path);
        
        if ( File_Get_Stats(path,&stats,1)->f.exists )
          {
            if ( stats.f.is_directory )
              {
                int i;
                for ( i = 0; i < host->indexes->count; ++i )
                  {
                    char *path1 = Path_Join(path,host->indexes->at[i]);
                    if ( File_Get_Stats(path1,&stats,1)->f.exists )
                      {
                        path = path1;
                        goto open_file;
                      }
                  }
                /* list directory */
                if ( !host->disable_index )
                  {
                    YOYO_BUFFER *obf = Buffer_Init(0);
                    YOYO_ARRAY *L = File_List_Directory(path,0);
                    for ( i = 0; i < L->count; ++i )
                      {
                        Buffer_Printf(obf,"<a href=\"%s/%s\">%s</a><br>",url->query,L->at[i],L->at[i]);
                      }
                    rqst->outstrm = __Refe(Buffer_As_File(obf));
                    rqst->outstrm_length = obf->count;
                    rqst->outstrm_type = Mime_String_Of_Npl(YOYO_MIME_HTML);
                    return HTTPD_SUCCESS;
                  }
                return HTTPD_NOTFOUND;
              }
          open_file:  
            rqst->outstrm = __Refe(Cfile_Open(path,"r"));
            rqst->outstrm_type = Str_Copy_Npl(Webhost_Conenttype_Of(path),-1);
            rqst->outstrm_length = (int)stats.length;
            return HTTPD_SUCCESS;
          }
        else
          return HTTPD_NOTFOUND;
      }
    
    return HTTPD_REJECT;
  }
#endif
  ;

#endif /*C_once_47E24D4B_C225_4002_B318_6FB9DDE274BE*/

Changes to yoyo.hc.

1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
#endif
  ;

void *Yo_Object_Dtor(int size,void *dtor)
#ifdef _YOYO_CORE_BUILTIN
  {
    int Sz = Yo_Align(sizeof(YOYO_OBJECT)+size);
    YOYO_OBJECT *o = Yo_Malloc_Npl(Sz+sizeof(YOYO_DYNAMIC));
    memset(o,0,Sz+sizeof(YOYO_DYNAMIC));
    o->signature = YOYO_OBJECT_SIGNATURE;
    o->rc = 1;
    o->dynamic = (YOYO_DYNAMIC*)((char*)o + Sz);
    o->dynamic->contsig = (YOYO_DYNCO_ATS<<8)|1;
    o->dynamic->funcs[0].name = Oj_Destruct_OjMID;
    o->dynamic->funcs[0].func = dtor;
    o->dynamic->typeid = Yo_Atomic_Increment(&Yo_Typeid_Counter);







|
<







1256
1257
1258
1259
1260
1261
1262
1263

1264
1265
1266
1267
1268
1269
1270
#endif
  ;

void *Yo_Object_Dtor(int size,void *dtor)
#ifdef _YOYO_CORE_BUILTIN
  {
    int Sz = Yo_Align(sizeof(YOYO_OBJECT)+size);
    YOYO_OBJECT *o = Yo_Zero_Malloc_Npl(Sz+sizeof(YOYO_DYNAMIC));

    o->signature = YOYO_OBJECT_SIGNATURE;
    o->rc = 1;
    o->dynamic = (YOYO_DYNAMIC*)((char*)o + Sz);
    o->dynamic->contsig = (YOYO_DYNCO_ATS<<8)|1;
    o->dynamic->funcs[0].name = Oj_Destruct_OjMID;
    o->dynamic->funcs[0].func = dtor;
    o->dynamic->typeid = Yo_Atomic_Increment(&Yo_Typeid_Counter);