// $Id: uniform.c,v 1.43 2008/03/29 20:36:43 lynx Exp $ // vim:syntax=lpc // // URLs.. URIs.. UNLs.. UNIs.. maybe even URNs.. // the fact they wear a uniform is the only thing these items have in common // after all.. they are not always resources, not always locators, // not always identificators.. but one thing is for sure, they have a // common format.. the uniform :) // // TODO: first move everything called _uniform or url somewhere into here // then rename everything into uniform, also uniform.c and uniform.h.. #include #include string legal_url(string url, string scheme) { if (scheme &&! abbrev(scheme+":", url)) return 0; if (index(url, '"') >= 0) return 0; if (index(url, ' ') >= 0) return 0; // just if (index(url, '\t') >= 0) return 0; // paranoid return url; } /** pass it a URL string and it will find out if that string ** is a uniform, and if so return an array as defined in uniform.h ** ** what about using ** http://www.gbiv.com/protocols/uri/rfc/rfc3986.html#regexp ? ** sweet, i really like that. can we do that? ** only we have to change that regexp a lot. like we don't ** need $1, $6 and $8, we need USlashes instead of $3, but ** what's tough is, we need UQuery to support ; or ? and ** we need UUser, UPass, UPort, UTransport, and UHostPort. ** all of that isn't in that regexp yet... */ varargs array(mixed) parse_uniform(string url, vaint tolerant) { array(string) u = allocate(USize); string t; string s; u[UString] = url; if (sscanf(url, "%s:%s", u[UScheme], t) != 2) { if (tolerant) t = url; else return 0; } ASSERT("parse_uniform w/out scheme", u[UScheme] || tolerant, url) P3(("parse_uniform %s of %O (tolerant: %O)\n", url, u[UScheme], tolerant)) if (abbrev("//", t)) { t = t[2..]; u[USlashes] = "//"; } else u[USlashes] = ""; switch(u[UScheme]) { case "sip": sscanf(t, "%s;%s", t, u[UQuery]); break; case "telnet": break; case "psyc": sscanf(t, "%s#%s", t, u[UChannel]); break; #if 0 //def MUCSUC case "xmpp": sscanf(t, "%s#%s", t, u[UChannel]); break; #endif //case "mailto": default: sscanf(t, "%s?%s", t, u[UQuery]); } u[UBody] = t; sscanf(t, "%s/%s", t, u[UResource]); #if 0 // int n; if (-1 != (n = member(u[UResource], '#'))) { u[UChannel] = u[UResource][n+1..]; // strlen checken?? } #endif u[UUserAtHost] = t; if (sscanf(t, "%s@%s", s, t)) { unless (sscanf(s, "%s:%s", u[UUser], u[UPass])) u[UUser] = s; } u[UHostPort] = t; // if (complete) u[UCircuit] = u[UScheme]+":"+u[UHostPort]; u[URoot] = u[UScheme]+":"+u[USlashes]+u[UHostPort]; if (sscanf(t, "%s:%s", t, s)) { unless (sscanf(s, "%d%s", u[UPort], u[UTransport])) u[UTransport] = s; unless (strlen(u[UTransport])) u[UTransport] = 0; } u[UHost] = t; P4(("parse_uniform %s = %O (tolerant: %O)\n", url, u, tolerant)) u[UNick] = u[UUser] || (strlen(u[UResource]) && u[UResource][1 ..]) || u[UBody]; return u; } string render_uniform(array(mixed) u) { string s, t; // wird aufgerufen wenn dieser string nicht mehr gültig ist: // if (u[UString]) return u[UString]; unless (s = u[UHost]) return 0; if (u[UUser]) s = u[UPass] ? (u[UUser]+":"+u[UPass]+"@"+s) : (u[UUser]+"@"+s); if (u[UScheme]) s = u[UScheme]+"://"+s; t = u[UPort] ? to_string(u[UPort]) : ""; if (u[UTransport]) t += u[UTransport]; if (t != "") s += ":"+t+"/"; if (u[UResource]) s += u[UResource]; if (u[UChannel]) s += "#"+ u[UChannel]; if (u[UQuery]) s += "?"+ u[UQuery]; D2( if (u[UString] == s) D("render_uniform: das war umsonst..\n"); ) P3(("render_uniform %O = %s\n", u, s)) return u[UString] = s; } // convert GENERIC psyc url stringp()s to objects (if local) #if 0 mixed urlobject(string url) { array(mixed) u; object o; // we avoid errors! we rule! u = parse_uniform(url); unless (query_udp_port() == (u[UPort] || PSYC_PORT)) return url; unless (u[UHost] == __HOST_IP_NUMBER__ || lower_case(u[UHost]) == lower_case(SERVER_HOST)) return url; if (u[UResource][0] == '~') o = find_person(u[UResource][1..]); else if (u[UUser]) o = find_person(u[UUser]); else o = find_object(u[UResource]); unless(objectp(o)) return url; return o; } #endif