1 #include "links.h"
2
3 #ifndef DISABLE_SMB
4
5 #define SMBCLIENT 0
6 #define SMBC 1
7 #define N_CLIENTS 2
8
9 static int smb_client = 0;
10
11 #define CLIENT_NOT_FOUND_STRING "client not found"
12
13 struct smb_connection_info {
14 int client;
15 int list;
16 int cl;
17 int ntext;
18 unsigned char text[1];
19 };
20
21 static void smb_got_data(struct connection *);
22 static void smb_got_text(struct connection *);
23 static void end_smb_connection(struct connection *);
24
smb_func(struct connection * c)25 void smb_func(struct connection *c)
26 {
27 int i;
28 int po[2];
29 int pe[2];
30 unsigned char *host, *user, *pass, *port, *data1, *data, *share, *dir;
31 int datal;
32 unsigned char *p;
33 pid_t r;
34 int rs;
35 struct smb_connection_info *si;
36 si = mem_alloc(sizeof(struct smb_connection_info) + 2);
37 memset(si, 0, sizeof(struct smb_connection_info));
38 c->info = si;
39 si->client = smb_client;
40 host = get_host_name(c->url);
41 if (!host) {
42 setcstate(c, S_INTERNAL);
43 abort_connection(c);
44 return;
45 }
46 if (!(user = get_user_name(c->url))) user = stracpy(cast_uchar "");
47 if (!(pass = get_pass(c->url))) pass = stracpy(cast_uchar "");
48 if (!(port = get_port_str(c->url))) port = stracpy(cast_uchar "");
49 if (!(data1 = get_url_data(c->url))) data1 = cast_uchar "";
50 data = init_str(), datal = 0;
51 add_conv_str(&data, &datal, data1, (int)strlen(cast_const_char data1), -2);
52
53 for (i = 0; data[i]; i++) if (data[i] < 32 || data[i] == ';' || (data[i] == '"' && smb_client == SMBCLIENT)) {
54 /* ';' shouldn't cause security problems but samba doesn't like it */
55 /* '"' is allowed for smbc */
56 mem_free(host);
57 mem_free(port);
58 mem_free(user);
59 mem_free(pass);
60 mem_free(data);
61 setcstate(c, S_BAD_URL);
62 abort_connection(c);
63 return;
64 }
65
66 if ((p = cast_uchar strchr(cast_const_char data, '/'))) share = memacpy(data, p - data), dir = p + 1;
67 else if (*data) {
68 if (!c->cache) {
69 if (get_cache_entry(c->url, &c->cache)) {
70 mem_free(host);
71 mem_free(port);
72 mem_free(user);
73 mem_free(pass);
74 mem_free(data);
75 setcstate(c, S_OUT_OF_MEM);
76 abort_connection(c);
77 return;
78 }
79 c->cache->refcount--;
80 }
81 if (c->cache->redirect) mem_free(c->cache->redirect);
82 c->cache->redirect = stracpy(c->url);
83 c->cache->redirect_get = 1;
84 add_to_strn(&c->cache->redirect, cast_uchar "/");
85 c->cache->incomplete = 0;
86 mem_free(host);
87 mem_free(port);
88 mem_free(user);
89 mem_free(pass);
90 mem_free(data);
91 setcstate(c, S__OK);
92 abort_connection(c);
93 return;
94 } else share = stracpy(cast_uchar ""), dir = cast_uchar "";
95 if (!*share) si->list = 1;
96 else if (!*dir || dir[strlen(cast_const_char dir) - 1] == '/' || dir[strlen(cast_const_char dir) - 1] == '\\') si->list = 2;
97 if (c_pipe(po)) {
98 int err = errno;
99 mem_free(host);
100 mem_free(port);
101 mem_free(user);
102 mem_free(pass);
103 mem_free(share);
104 mem_free(data);
105 setcstate(c, get_error_from_errno(err));
106 abort_connection(c);
107 return;
108 }
109 if (c_pipe(pe)) {
110 int err = errno;
111 mem_free(host);
112 mem_free(port);
113 mem_free(user);
114 mem_free(pass);
115 mem_free(share);
116 mem_free(data);
117 EINTRLOOP(rs, close(po[0]));
118 EINTRLOOP(rs, close(po[1]));
119 setcstate(c, get_error_from_errno(err));
120 abort_connection(c);
121 return;
122 }
123 c->from = 0;
124 EINTRLOOP(r, fork());
125 if (r == -1) {
126 int err = errno;
127 mem_free(host);
128 mem_free(port);
129 mem_free(user);
130 mem_free(pass);
131 mem_free(share);
132 mem_free(data);
133 EINTRLOOP(rs, close(po[0]));
134 EINTRLOOP(rs, close(po[1]));
135 EINTRLOOP(rs, close(pe[0]));
136 EINTRLOOP(rs, close(pe[1]));
137 setcstate(c, get_error_from_errno(err));
138 retry_connection(c);
139 return;
140 }
141 if (!r) {
142 int n;
143 unsigned char *v[32];
144 unsigned char *uphp;
145 close_fork_tty();
146 EINTRLOOP(rs, close(1));
147 if (si->list)
148 EINTRLOOP(rs, dup2(pe[1], 1));
149 else
150 EINTRLOOP(rs, dup2(po[1], 1));
151 EINTRLOOP(rs, close(2));
152 EINTRLOOP(rs, dup2(pe[1], 2));
153 EINTRLOOP(rs, close(0));
154 EINTRLOOP(rs, open("/dev/null", O_RDONLY));
155 EINTRLOOP(rs, close(po[0]));
156 EINTRLOOP(rs, close(pe[0]));
157 EINTRLOOP(rs, close(po[1]));
158 EINTRLOOP(rs, close(pe[1]));
159 n = 0;
160 switch (si->client) {
161 case SMBCLIENT:
162 v[n++] = cast_uchar "smbclient";
163 if (!*share) {
164 v[n++] = cast_uchar "-L";
165 v[n++] = host;
166 } else {
167 unsigned char *s = stracpy(cast_uchar "//");
168 add_to_strn(&s, host);
169 add_to_strn(&s, cast_uchar "/");
170 add_to_strn(&s, share);
171 v[n++] = s;
172 if (*pass && !*user) {
173 v[n++] = pass;
174 }
175 }
176 v[n++] = cast_uchar "-N";
177 v[n++] = cast_uchar "-E";
178 if (*port) {
179 v[n++] = cast_uchar "-p";
180 v[n++] = port;
181 }
182 if (*user) {
183 v[n++] = cast_uchar "-U";
184 if (!*pass) {
185 v[n++] = user;
186 } else {
187 unsigned char *s = stracpy(user);
188 add_to_strn(&s, cast_uchar "%");
189 add_to_strn(&s, pass);
190 v[n++] = s;
191 }
192 }
193 if (*share) {
194 if (!*dir || dir[strlen(cast_const_char dir) - 1] == '/' || dir[strlen(cast_const_char dir) - 1] == '\\') {
195 if (*dir) {
196 v[n++] = cast_uchar "-D";
197 v[n++] = dir;
198 }
199 v[n++] = cast_uchar "-c";
200 v[n++] = cast_uchar "ls";
201 } else {
202 unsigned char *ss;
203 unsigned char *s = stracpy(cast_uchar "get \"");
204 add_to_strn(&s, dir);
205 add_to_strn(&s, cast_uchar "\" -");
206 while ((ss = cast_uchar strchr(cast_const_char s, '/'))) *ss = '\\';
207 v[n++] = cast_uchar "-c";
208 v[n++] = s;
209 }
210 }
211 break;
212 case SMBC:
213 v[n++] = cast_uchar "smbc";
214 uphp = stracpy(cast_uchar "");
215 if (*user) {
216 add_to_strn(&uphp, user);
217 if (*pass) {
218 add_to_strn(&uphp, cast_uchar ":");
219 add_to_strn(&uphp, pass);
220 }
221 add_to_strn(&uphp, cast_uchar "@");
222 }
223 add_to_strn(&uphp, host);
224 if (*port) {
225 add_to_strn(&uphp, cast_uchar ":");
226 add_to_strn(&uphp, port);
227 }
228 if (!*share) {
229 v[n++] = cast_uchar "-L";
230 v[n++] = uphp;
231 } else {
232 add_to_strn(&uphp, cast_uchar "/");
233 add_to_strn(&uphp, share);
234 if (!*dir || dir[strlen(cast_const_char dir) - 1] == '/' || dir[strlen(cast_const_char dir) - 1] == '\\') {
235 add_to_strn(&uphp, cast_uchar "/");
236 add_to_strn(&uphp, dir);
237 v[n++] = uphp;
238 v[n++] = cast_uchar "-c";
239 v[n++] = cast_uchar "ls";
240 } else {
241 unsigned char *d = init_str();
242 int dl = 0;
243 unsigned char *dp = dir;
244 v[n++] = uphp;
245 v[n++] = cast_uchar "-c";
246 add_to_str(&d, &dl, cast_uchar "pipe cat ");
247 while (*dp) {
248 if (*dp <= ' ' || *dp == '\\' || *dp == '"' || *dp == '\'' || *dp == '*' || *dp == '?') add_chr_to_str(&d, &dl, '\\');
249 add_chr_to_str(&d, &dl, *dp);
250 dp++;
251 }
252 v[n++] = d;
253 }
254 }
255 break;
256 default:
257 internal("unsupported smb client");
258 }
259 v[n++] = NULL;
260 EINTRLOOP(rs, execvp(cast_const_char v[0], (void *)v));
261 hard_write(2, cast_uchar CLIENT_NOT_FOUND_STRING, (int)strlen(CLIENT_NOT_FOUND_STRING));
262 _exit(1);
263 }
264 c->pid = r;
265 mem_free(host);
266 mem_free(port);
267 mem_free(user);
268 mem_free(pass);
269 mem_free(share);
270 mem_free(data);
271 c->sock1 = po[0];
272 c->sock2 = pe[0];
273 EINTRLOOP(rs, close(po[1]));
274 EINTRLOOP(rs, close(pe[1]));
275 set_handlers(po[0], (void (*)(void *))smb_got_data, NULL, NULL, c);
276 set_handlers(pe[0], (void (*)(void *))smb_got_text, NULL, NULL, c);
277 setcstate(c, S_CONN);
278 }
279
smbc_get_num(unsigned char * text,int * ptr,off_t * res)280 static int smbc_get_num(unsigned char *text, int *ptr, off_t *res)
281 {
282 off_t num;
283 int dec, dec_order, unit;
284 int was_digit;
285 int i = *ptr;
286 const off_t max_off_t = (((off_t)1 << ((sizeof(off_t) * 8 - 2))) - 1) * 2 + 1;
287
288 while (text[i] == ' ' || text[i] == '\t') i++;
289 was_digit = 0;
290 num = 0;
291 while (text[i] >= '0' && text[i] <= '9') {
292 if (num >= max_off_t / 10) return -1;
293 num = num * 10 + text[i] - '0';
294 i++;
295 was_digit = 1;
296 }
297 dec = 0; dec_order = 1;
298 if (text[i] == '.') {
299 i++;
300 while (text[i] >= '0' && text[i] <= '9') {
301 if (dec_order < 1000000) {
302 dec = dec * 10 + text[i] - '0';
303 dec_order *= 10;
304 }
305 i++;
306 was_digit = 1;
307 }
308 }
309 if (!was_digit) return -1;
310 if (upcase(text[i]) == 'B') unit = 1;
311 else if (upcase(text[i]) == 'K') unit = 1 << 10;
312 else if (upcase(text[i]) == 'M') unit = 1 << 20;
313 else if (upcase(text[i]) == 'G') unit = 1 << 30;
314 else return -1;
315 i++;
316 *ptr = i;
317 if (num >= max_off_t / unit) return -1;
318 *res = num * unit + (off_t)((double)dec * ((double)unit / (double)dec_order));
319 return 0;
320 }
321
smb_read_text(struct connection * c,int sock)322 static void smb_read_text(struct connection *c, int sock)
323 {
324 int r;
325 struct smb_connection_info *si = c->info;
326 if ((unsigned)sizeof(struct smb_connection_info) + si->ntext + page_size + 2 > MAXINT) overalloc();
327 si = mem_realloc(si, sizeof(struct smb_connection_info) + si->ntext + page_size + 2);
328 c->info = si;
329 EINTRLOOP(r, (int)read(sock, si->text + si->ntext, page_size));
330 if (r == -1) {
331 setcstate(c, get_error_from_errno(errno));
332 retry_connection(c);
333 return;
334 }
335 if (r == 0) {
336 if (!si->cl) {
337 si->cl = 1;
338 set_handlers(sock, NULL, NULL, NULL, NULL);
339 return;
340 }
341 end_smb_connection(c);
342 return;
343 }
344 si->ntext += r;
345 if (!c->from) setcstate(c, S_GETH);
346 if (c->from && si->client == SMBC) {
347 int lasti = 0;
348 int i = 0;
349 si->text[si->ntext] = 0;
350 for (i = 0; si->ntext - i > 7; i++) {
351 nexti:
352 if ((si->text[i] == '\n' || si->text[i] == '\r') && (si->text[i + 1] == ' ' || (si->text[i + 1] >= '0' && si->text[i + 1] <= '9')) && ((si->text[i + 2] == ' ' && si->text[i + 1] == ' ') || (si->text[i + 2] >= '0' && si->text[i + 2] <= '9')) && (si->text[i + 3] >= '0' && si->text[i + 3] <= '9') && si->text[i + 4] == '%' && si->text[i + 5] == ' ' && si->text[i + 6] == '[') {
353 off_t position, total = 0; /* against warning */
354 i += 7;
355 while (si->text[i] != ']') {
356 if (!si->text[i] || si->text[i] == '\n' || si->text[i] == '\r') {
357 goto nexti;
358 }
359 i++;
360 }
361 i++;
362 if (smbc_get_num(si->text, &i, &position)) {
363 goto nexti;
364 }
365 while (si->text[i] == ' ' || si->text[i] == '\t') i++;
366 if (si->text[i] != '/') {
367 goto nexti;
368 }
369 i++;
370 if (smbc_get_num(si->text, &i, &total)) {
371 goto nexti;
372 }
373 if (total < c->from) total = c->from;
374 c->est_length = total;
375 lasti = i;
376 }
377 }
378 if (lasti) memmove(si->text, si->text + lasti, si->ntext -= lasti);
379 }
380 }
381
smb_got_data(struct connection * c)382 static void smb_got_data(struct connection *c)
383 {
384 struct smb_connection_info *si = c->info;
385 unsigned char *buffer = mem_alloc(page_size);
386 int r;
387 int a;
388 if (si->list) {
389 smb_read_text(c, c->sock1);
390 mem_free(buffer);
391 return;
392 }
393 EINTRLOOP(r, (int)read(c->sock1, buffer, page_size));
394 if (r == -1) {
395 setcstate(c, get_error_from_errno(errno));
396 retry_connection(c);
397 mem_free(buffer);
398 return;
399 }
400 if (r == 0) {
401 mem_free(buffer);
402 if (!si->cl) {
403 si->cl = 1;
404 set_handlers(c->sock1, NULL, NULL, NULL, NULL);
405 return;
406 }
407 end_smb_connection(c);
408 return;
409 }
410 setcstate(c, S_TRANS);
411 if (!c->cache) {
412 if (get_cache_entry(c->url, &c->cache)) {
413 setcstate(c, S_OUT_OF_MEM);
414 abort_connection(c);
415 mem_free(buffer);
416 return;
417 }
418 c->cache->refcount--;
419 }
420 if ((off_t)(0UL + c->from + r) < 0) {
421 setcstate(c, S_LARGE_FILE);
422 abort_connection(c);
423 mem_free(buffer);
424 return;
425 }
426 c->received += r;
427 a = add_fragment(c->cache, c->from, buffer, r);
428 if (a < 0) {
429 setcstate(c, a);
430 abort_connection(c);
431 mem_free(buffer);
432 return;
433 }
434 if (a == 1) c->tries = 0;
435 c->from += r;
436 mem_free(buffer);
437 }
438
smb_got_text(struct connection * c)439 static void smb_got_text(struct connection *c)
440 {
441 smb_read_text(c, c->sock2);
442 }
443
end_smb_connection(struct connection * c)444 static void end_smb_connection(struct connection *c)
445 {
446 struct smb_connection_info *si = c->info;
447 if (!c->cache) {
448 if (get_cache_entry(c->url, &c->cache)) {
449 setcstate(c, S_OUT_OF_MEM);
450 abort_connection(c);
451 return;
452 }
453 c->cache->refcount--;
454 }
455 if (!c->from) {
456 int sdir;
457 if (si->ntext && si->text[si->ntext - 1] != '\n') si->text[si->ntext++] = '\n';
458 si->text[si->ntext] = 0;
459 if (!strcmp(cast_const_char si->text, CLIENT_NOT_FOUND_STRING "\n")) {
460 setcstate(c, S_NO_SMB_CLIENT);
461 if (++si->client < N_CLIENTS) {
462 if (si->client > smb_client) smb_client = si->client;
463 c->tries = -1;
464 retry_connection(c);
465 } else {
466 smb_client = 0;
467 abort_connection(c);
468 }
469 return;
470 }
471 sdir = 0;
472 if (si->client == SMBC) {
473 unsigned char *st = si->text;
474 if (!memcmp(st, "ServerName", 10) && strchr(cast_const_char st, '\n')) st = cast_uchar strchr(cast_const_char st, '\n') + 1;
475 if (!memcmp(st, "Logged", 6) && strchr(cast_const_char st, '\n')) st = cast_uchar strchr(cast_const_char st, '\n') + 1;
476 if (!strstr(cast_const_char st, "ERR")) sdir = 1;
477 }
478 if (!si->list && *c->url &&
479 c->url[strlen(cast_const_char c->url) - 1] != '/' &&
480 c->url[strlen(cast_const_char c->url) - 1] != '\\' &&
481 (strstr(cast_const_char si->text, "NT_STATUS_FILE_IS_A_DIRECTORY") ||
482 strstr(cast_const_char si->text, "NT_STATUS_ACCESS_DENIED") ||
483 strstr(cast_const_char si->text, "ERRbadfile") || sdir)) {
484 if (c->cache->redirect) mem_free(c->cache->redirect);
485 c->cache->redirect = stracpy(c->url);
486 c->cache->redirect_get = 1;
487 add_to_strn(&c->cache->redirect, cast_uchar "/");
488 c->cache->incomplete = 0;
489 } else {
490 unsigned char *ls, *le, *le2;
491 unsigned char *ud;
492 unsigned char *t = init_str();
493 int l = 0;
494 int type = 0;
495 int pos = 0;
496 int a;
497 add_to_str(&t, &l, cast_uchar "<html><head><title>");
498 ud = stracpy(c->url);
499 if (strchr(cast_const_char ud, POST_CHAR)) *cast_uchar strchr(cast_const_char ud, POST_CHAR) = 0;
500 add_conv_str(&t, &l, ud, (int)strlen(cast_const_char ud), -1);
501 mem_free(ud);
502 add_to_str(&t, &l, cast_uchar "</title></head><body><pre>");
503 if (si->list == 1 && si->client == SMBC) {
504 /* smbc has a nasty bug that it writes field descriptions to stderr and data to
505 stdout. Because of stdout buffer, they'll get mixed in the output. Try to
506 demix them. */
507 #define SERVER "Server Comment\n------ -------\n"
508 #define WORKGR "Workgroup Master\n--------- ------\n"
509 unsigned char *spos = cast_uchar strstr(cast_const_char si->text, SERVER);
510 unsigned char *gpos;
511 unsigned char *p, *pp, *ppp;
512 if (spos) memmove(spos, spos + strlen(SERVER), strlen(cast_const_char spos) - strlen(SERVER) + 1);
513 gpos = cast_uchar strstr(cast_const_char si->text, WORKGR);
514 if (gpos) memmove(gpos, gpos + strlen(WORKGR), strlen(cast_const_char gpos) - strlen(WORKGR) + 1);
515 if (!spos && !gpos) goto sc;
516 pp = NULL, ppp = NULL, p = si->text;
517 while ((p = cast_uchar strstr(cast_const_char p, "\n\n"))) ppp = pp, pp = p + 2, p++;
518 if (!pp) goto sc;
519 if (!spos || !gpos) ppp = NULL;
520 if (spos) {
521 if (!ppp) ppp = pp, pp = NULL;
522 memmove(ppp + strlen(SERVER), ppp, strlen(cast_const_char ppp) + 1);
523 memcpy(ppp, SERVER, strlen(SERVER));
524 if (pp) pp += strlen(SERVER);
525 }
526 if (gpos && pp) {
527 memmove(pp + strlen(WORKGR), pp, strlen(cast_const_char pp) + 1);
528 memcpy(pp, WORKGR, strlen(WORKGR));
529 }
530 goto sc;
531 }
532 sc:
533 ls = si->text;
534 while ((le = cast_uchar strchr(cast_const_char ls, '\n'))) {
535 unsigned char *lx;
536 unsigned char *st;
537 le2 = cast_uchar strchr(cast_const_char ls, '\r');
538 if (!le2 || le2 > le) le2 = le;
539 lx = memacpy(ls, le2 - ls);
540 if (si->list == 1) {
541 unsigned char *ll, *lll;
542 if (!*lx) type = 0;
543 if (strstr(cast_const_char lx, "Sharename") && (st = cast_uchar strstr(cast_const_char lx, "Type"))) {
544 pos = (int)(st - lx);
545 type = 1;
546 goto af;
547 }
548 if (strstr(cast_const_char lx, "Server") && strstr(cast_const_char lx, "Comment")) {
549 type = 2;
550 goto af;
551 }
552 if (strstr(cast_const_char lx, "Workgroup") && (st = cast_uchar strstr(cast_const_char lx, "Master"))) {
553 pos = (int)(st - lx);
554 type = 3;
555 goto af;
556 }
557 if (!type) goto af;
558 for (ll = lx; *ll; ll++) if (!WHITECHAR(*ll) && *ll != '-') goto np;
559 goto af;
560 np:
561 for (ll = lx; *ll; ll++) if (!WHITECHAR(*ll)) break;
562 for (lll = ll; *lll /* && lll[1]*/; lll++) if (WHITECHAR(*lll) /*&& WHITECHAR(lll[1])*/) break;
563 if (type == 1) {
564 unsigned char *llll;
565 if (!strstr(cast_const_char lll, "Disk")) goto af;
566 if (pos && (size_t)pos < strlen(cast_const_char lx) && WHITECHAR(*(llll = lx + pos - 1)) && llll > ll) {
567 while (llll > ll && WHITECHAR(*llll)) llll--;
568 if (!WHITECHAR(*llll)) lll = llll + 1;
569 }
570 add_conv_str(&t, &l, lx, (int)(ll - lx), 0);
571 add_to_str(&t, &l, cast_uchar "<a href=\"/");
572 add_conv_str(&t, &l, ll, (int)(lll - ll), 1);
573 add_to_str(&t, &l, cast_uchar "/\">");
574 add_conv_str(&t, &l, ll, (int)(lll - ll), 0);
575 add_to_str(&t, &l, cast_uchar "</a>");
576 add_conv_str(&t, &l, lll, (int)strlen(cast_const_char lll), 0);
577 } else if (type == 2) {
578 sss:
579 add_conv_str(&t, &l, lx, (int)(ll - lx), 0);
580 add_to_str(&t, &l, cast_uchar "<a href=\"smb://");
581 add_conv_str(&t, &l, ll, (int)(lll - ll), 1);
582 add_to_str(&t, &l, cast_uchar "/\">");
583 add_conv_str(&t, &l, ll, (int)(lll - ll), 0);
584 add_to_str(&t, &l, cast_uchar "</a>");
585 add_conv_str(&t, &l, lll, (int)strlen(cast_const_char lll), 0);
586 } else if (type == 3) {
587 if ((size_t)pos < strlen(cast_const_char lx) && pos && WHITECHAR(lx[pos - 1]) && !WHITECHAR(lx[pos])) ll = lx + pos;
588 else for (ll = lll; *ll; ll++) if (!WHITECHAR(*ll)) break;
589 for (lll = ll; *lll; lll++) if (WHITECHAR(*lll)) break;
590 goto sss;
591 } else goto af;
592 } else if (si->list == 2 && si->client == SMBCLIENT) {
593 if (strstr(cast_const_char lx, "NT_STATUS")) {
594 le[1] = 0;
595 goto af;
596 }
597 if (le2 - ls >= 5 && ls[0] == ' ' && ls[1] == ' ' && ls[2] != ' ') {
598 int dir;
599 unsigned char *pp;
600 unsigned char *p = ls + 3;
601 while (le2 - p >= 2) {
602 if (p[0] == ' ' && p[1] == ' ') goto o;
603 p++;
604 }
605 goto af;
606 o:
607 dir = 0;
608 pp = p;
609 while (pp < le2 && *pp == ' ') pp++;
610 while (pp < le2 && *pp != ' ') {
611 if (*pp == 'D') {
612 dir = 1;
613 break;
614 }
615 pp++;
616 }
617 add_to_str(&t, &l, cast_uchar " <a href=\"./");
618 add_conv_str(&t, &l, ls + 2, (int)(p - (ls + 2)), 1);
619 if (dir) add_chr_to_str(&t, &l, '/');
620 add_to_str(&t, &l, cast_uchar "\">");
621 add_conv_str(&t, &l, ls + 2, (int)(p - (ls + 2)), 0);
622 add_to_str(&t, &l, cast_uchar "</a>");
623 add_conv_str(&t, &l, p, (int)(le - p), 0);
624 } else goto af;
625 } else if (si->list == 2 && si->client == SMBC) {
626 unsigned char *d;
627 if (le2 - ls <= 17) goto af;
628 d = ls + 17;
629 smbc_next_chr:
630 if (d + 9 >= le2) goto af;
631 if (!(d[0] == ':' && d[1] >= '0' && d[1] <= '9' && d[2] >= '0' && d[2] <= '9' && d[3] == ' ' && ((d[4] == '1' && d[5] == '9') || (d[4] == '2' && d[5] >= '0' && d[5] <= '9')) && d[6] >= '0' && d[6] <= '9' && d[7] >= '0' && d[7] <= '9' && d[8] == ' ')) {
632 d++;
633 goto smbc_next_chr;
634 }
635 d += 9;
636 add_conv_str(&t, &l, ls, (int)(d - ls), 0);
637 add_to_str(&t, &l, cast_uchar "<a href=\"./");
638 add_conv_str(&t, &l, d, (int)(le2 - d), 1);
639 if (ls[4] == 'D') add_chr_to_str(&t, &l, '/');
640 add_to_str(&t, &l, cast_uchar "\">");
641 add_conv_str(&t, &l, d, (int)(le2 - d), 0);
642 add_to_str(&t, &l, cast_uchar "</a>");
643 } else af: add_conv_str(&t, &l, ls, (int)(le2 - ls), 0);
644 add_chr_to_str(&t, &l, '\n');
645 ls = le + 1;
646 mem_free(lx);
647 }
648 /*add_to_str(&t, &l, si->text);*/
649 a = add_fragment(c->cache, 0, t, l);
650 if (a < 0) {
651 mem_free(t);
652 setcstate(c, a);
653 abort_connection(c);
654 return;
655 }
656 c->from += l;
657 truncate_entry(c->cache, l, 1);
658 c->cache->incomplete = 0;
659 mem_free(t);
660 if (!c->cache->head) c->cache->head = stracpy(cast_uchar "\r\n");
661 add_to_strn(&c->cache->head, cast_uchar "Content-Type: text/html\r\n");
662 }
663 } else {
664 truncate_entry(c->cache, c->from, 1);
665 c->cache->incomplete = 0;
666 }
667 close_socket(&c->sock1);
668 close_socket(&c->sock2);
669 setcstate(c, S__OK);
670 abort_connection(c);
671 return;
672 }
673
674 #endif
675