/* this is a HACK */ Rune* urlcombine(Rune *b, Rune *u) { Rune *p, *q, *sep, *s; Rune endrune[] = { L'?', L'#' }; int i, restore; if(u == nil) error("urlcombine: u == nil"); if(validurl(u)) return erunestrdup(u); if(b==nil || !validurl(b)) error("urlcombine: b==nil || !validurl(b)"); if(runestrncmp(u, L"//", 2) == 0){ q = runestrchr(b, L':'); return runesmprint("%.*S:%S", (int)(q-b), b, u); } p = runestrstr(b, L"://"); if(p != nil) p += 3; sep = L""; q = nil; if(*u ==L'/') q = runestrchr(p, L'/'); else if(*u==L'#' || *u==L'?'){ for(i=0; i<nelem(endrune); i++) if(q = runestrchr(p, endrune[i])) break; }else if(p != nil){ sep = L"/"; restore = 0; s = runestrchr(p, L'?'); if(s != nil){ *s = '\0'; restore = 1; } q = runestrrchr(p, L'/'); if(restore) *s = L'?'; }else sep = L"/"; if(q == nil) p = runesmprint("%S%S%S", b, sep, u); else p = runesmprint("%.*S%S%S", (int)(q-b), b, sep, u); urlcanon(p); return p; }
/* * Get the next argument from the current line. */ Rune* copyarg(void) { static Rune buf[MaxLine]; int c; Rune *r; if(_readx(buf, sizeof buf, ArgMode, 0) < 0) return nil; r = runestrstr(buf, L("\\\"")); if(r){ *r = 0; while((c = getrune()) >= 0 && c != '\n') ; ungetrune('\n'); } r = erunestrdup(buf); return r; }
void urlcanon(Rune *name) { Rune *s, *e, *tail, tailr; Rune **comp, **p, **q; int n; name = runestrstr(name, L"://"); if(name == nil) return; name = runestrchr(name+3, '/'); if(name == nil) return; if(*name == L'/') name++; n = 0; for(e = name; *e != 0; e++) if(*e == L'/') n++; comp = emalloc((n+2)*sizeof *comp); /* * Break the name into a list of components */ p = comp; *p++ = name; tail = nil; tailr = L'☺'; /* silence compiler */ for(s = name; *s != 0; s++){ if(*s == '?' || *s == '#'){ tail = s+1; tailr = *s; *s = 0; break; } else if(*s == L'/'){ *p++ = s+1; *s = 0; } } /* * go through the component list, deleting components that are empty (except * the last component) or ., and any .. and its predecessor. */ for(p = q = comp; *p != nil; p++){ if(runestrcmp(*p, L"") == 0 && p[1] != nil || runestrcmp(*p, L".") == 0) continue; else if(q>comp && runestrcmp(*p, L"..") == 0 && runestrcmp(q[-1], L"..") != 0) q--; else *q++ = *p; } *q = nil; /* * rebuild the path name */ s = name; for(p = comp; p<q; p++){ n = runestrlen(*p); memmove(s, *p, sizeof(Rune)*n); s += n; if(p[1] != nil) *s++ = '/'; } *s = 0; if(tail) runeseprint(s, e+1, "%C%S", tailr, tail); free(comp); }