From pe@iki.fi Tue Aug 5 16:53:41 1997 Date: Tue, 5 Aug 1997 16:53:35 +0300 (EEST) From: Pasi Eronen To: HTDig mailing list Subject: Patches for local home directories Hi! Few days ago, I posted patches for local filesystem access to HTDig. Since then, I've received a request for supporting user home directory URLs (like http://www.my.com/~user/foo.html), and made a patch for that, too. The syntax of the new configuration file option is: local_user_urls: prefix1=[path1],dir1 ... If you leave the "path" part out, it looks up the user's home directory in /etc/passwd (or NIS or whatever). For example, to map "http://www.my.org/~joe/foo/bar.html" to "/home/joe/www/foo/bar.html" you would say: local_user_urls: http://www.my.org/=/home/,/www/ The default behaviour of many WWW servers is approximately: local_user_urls: http://www.my.org/=,/public_html/ (NOTE: All the slashes in these examples are REQUIRED!) This patch is a bit large, so I won't post it here. Instead, it's available from . I'm not indexing any home directories myself, so comments are very welcome. (Tip: you can see what local filename it's trying to use if you specify options '-v -v' to htdig.) Thanks to Geoff Hutchison for testing this patch. Best regards, Pasi --- Pasi Eronen , +358-50-5123499 *** htcommon/defaults.cc.orig Mon Aug 4 18:14:48 1997 --- htcommon/defaults.cc Mon Aug 4 18:15:10 1997 *************** *** 65,68 **** --- 65,69 ---- {"locale", "iso_8859_1"}, {"local_urls", ""}, + {"local_user_urls", ""}, {"maintainer", "andrew@contigo.com"}, {"match_method", "or"}, *** htdig/Retriever.h.orig Mon Aug 4 18:12:20 1997 --- htdig/Retriever.h Mon Aug 4 18:12:38 1997 *************** *** 117,120 **** --- 117,121 ---- int IsValidURL(char *url); String * IsLocal(char *url); + String * IsLocalUser(char *url); void RetrievedDocument(Document &, char *url, DocumentRef *ref); void parse_url(URLRef &urlRef); *** htdig/Retriever.cc.orig Mon Aug 4 18:12:27 1997 --- htdig/Retriever.cc Mon Aug 4 18:13:30 1997 *************** *** 27,30 **** --- 27,31 ---- #include "Document.h" #include + #include static WordList words; *************** *** 261,265 **** // Retrive document, first trying local file access if possible. Document::DocStatus status; ! String *local_filename = IsLocal(url.get()); if (local_filename) { --- 262,268 ---- // Retrive document, first trying local file access if possible. Document::DocStatus status; ! String *local_filename = IsLocalUser(url.get()); ! if (!local_filename) ! local_filename = IsLocal(url.get()); if (local_filename) { *************** *** 538,541 **** --- 541,548 ---- } + // This shouldn't happen, but check anyway... + if (strstr(url, "..")) + return 0; + String *prefix, *path; prefixes->Start_Get(); *************** *** 556,559 **** --- 563,665 ---- + //***************************************************************************** + // String* Retriever::IsLocalUser(char *url) + // If the URL has ~user part, returns a string containing the + // (possible) local filename of the given url, or 0 if it's + // definitely not local. + // THE CALLER MUST FREE THE STRING AFTER USE! + // + String* + Retriever::IsLocalUser(char *url) + { + static StringList *prefixes = 0, *paths = 0, *dirs = 0; + static Dictionary home_cache; + + // + // Initialize prefix/path list if this is the first time. + // The list is given in format "prefix1=path1,dir1 ..." + // If path is zero-length, user's home directory is looked up. + // + if (!prefixes) + { + prefixes = new StringList(); + paths = new StringList(); + dirs = new StringList(); + String t = config["local_user_urls"]; + char *p = strtok(t, " \t"); + while (p) + { + char *path = strchr(p, '='); + if (!path) + continue; + *path++ = '\0'; + char *dir = strchr(path, ','); + if (!dir) + continue; + *dir++ = '\0'; + prefixes->Add(p); + paths->Add(path); + dirs->Add(dir); + p = strtok(0, " \t"); + } + } + + // Can we do anything about this? + if (!strchr(url, '~') || !prefixes->Count() || strstr(url, "..")) + return 0; + + // Split the URL to components + String tmp = url; + char *name = strchr(tmp, '~'); + *name++ = '\0'; + char *rest = strchr(name, '/'); + if (!rest || (rest-name <= 1) || (rest-name > 32)) + return 0; + *rest++ = '\0'; + + // Look it up in the prefix/path/dir table + prefixes->Start_Get(); + paths->Start_Get(); + dirs->Start_Get(); + String *prefix, *path, *dir; + while (prefix = (String*) prefixes->Get_Next()) + { + path = (String*) paths->Get_Next(); + dir = (String*) dirs->Get_Next(); + if (strcasecmp(*prefix, tmp) != 0) + continue; + + String *local = new String; + // No path, look up home directory + if (path->length() == 0) + { + String *home = (String*) home_cache[name]; + if (!home) + { + struct passwd *passwd = getpwnam(name); + if (passwd) + { + home = new String(passwd->pw_dir); + home_cache.Add(name, home); + } + } + if (home) + *local += *home; + else + return 0; + } + else + { + *local += *path; + *local += name; + } + *local += *dir; + *local += rest; + return local; + } + return 0; + } + + //***************************************************************************** // DocumentRef *Retriever::GetRef(char *u)