//TIMESTAMP|NAME=foo|LAST_CHECK=123123123 void conf_timestamp(char **keys, char **values, int items,void *optarg) { char *name, *last_check; site_t *site = NULL; int i; name = parser_findkey(keys, values, items, "NAME"); last_check = parser_findkey(keys, values, items, "LAST_CHECK"); if (!name) { printf("TIMESTAMP Entry in conf without NAME= field\n"); return; } for (i = 0; i < num_sites; i++) { if (sites[i] && !mystrccmp(name, sites[i]->name)) { site = sites[i]; break; } } if (!site) { printf("Unable to find site '%s' used in TIMESTAMP\n", name); return; } if (last_check) { site->last_check = strtoul(last_check, NULL, 10); site->last_check -= default_age; } else { site->last_check = lion_global_time; site->last_check -= default_age; } }
lion64_t llrar_getsize(request_t *node) { int i; llrar_cache_entry_t *runner; char *path, *name = NULL; debugf("[llrar] CACHE Looking for RAR '%s' rar_file '%s' \n", node->disk_path, node->rar_file ? node->rar_file : ""); if (!node->rar_file) return 0; if (!node->rar_directory) path = "/"; else path = node->rar_directory; for (i = 0; i < LLRAR_CACHE_SIZE; i++) { if (llrar_cache[i].path && !mystrccmp(llrar_cache[i].path, node->disk_path)) { name = misc_strjoin(path, node->rar_file); debugf(" found RAR: looking for '%s'\n", name); for (runner = llrar_cache[i].files; runner; runner=runner->next) { if (!mystrccmp(name, runner->file.name)) { SAFE_FREE(name); return runner->file.size; } } SAFE_FREE(name); } // RAR name match } // for all cache nodes return 0; // Not found }
yesnoauto_t str2yna(char *s) { if (!s || !*s) return YNA_AUTO; if (!mystrccmp("AUTO", s)) return YNA_AUTO; if (!mystrccmp("NO", s)) return YNA_NO; if (!mystrccmp("YES", s)) return YNA_YES; switch(atoi(s)) { case 0: return YNA_NO; case 1: return YNA_YES; default: return YNA_AUTO; } // NOT REACHED return YNA_AUTO; }
// WELCOME|name=FXP.Oned|version=0.1|build=359|protocol=1.2|SSL=optional void site_cmd_welcome(char **keys, char **values, int items,void *optarg) { fxpone_t *the_engine = optarg; char *ssl; ssl = parser_findkey(keys, values, items, "SSL"); if (ssl && !mystrccmp("disabled", ssl)) { send_auth(the_engine); return; } lion_printf(the_engine->handle, "SSL\r\n"); }
static int root_zfs_handler(lion_t *handle, void *user_data, int status, int size, char *line) { char *zfs_attribute = (char *) user_data; // If node isn't set, it's b0rken. if (!zfs_attribute) return 0; switch(status) { case LION_PIPE_RUNNING: debugf(" : zfs command running\n"); break; case LION_PIPE_FAILED: debugf(" : zfs command failed: %d\n", size); break; case LION_PIPE_EXIT: debugf(" : zfs command finished.\n"); break; case LION_INPUT: if (line && *line) { // "/export/media ON". zfs list -H should be separated by TAB. char *path, *value; path = misc_digtoken(&line, "\t\r\n"); value = misc_digtoken(&line, "\t\r\n"); if (path && value && !mystrccmp("on", value)) { char *keys[2] = {"PATH", NULL}; char *values[2] = {path, NULL}; debugf(" : zfs adding '%s'\n", path); // Don't add "ZFS" here, or we will fork-bomb. root_cmd(keys, values, 1, NULL); } } // line break; } return 0; }
site_t *site_find(char *name) { int i; for (i = 0; i < num_sites; i++) { if (!sites[i]) continue; if (!mystrccmp(sites[i]->name, name)) return sites[i]; } return NULL; }
void file_strdup_name(file_t *file, char *name, char *type) { char buffer[1024]; char *test = NULL; file->name = misc_url_decode(name); if (!mystrccmp(type, "DIRECTORY")) { file->directory = YNA_YES; snprintf(buffer, sizeof(buffer), "</8>%s/<!8>", file->name); file->display_name = strdup(buffer); return; } file->directory = YNA_NO; snprintf(buffer, sizeof(buffer), "</32>%s<!32>", test ? test : file->name); file->display_name = strdup(buffer); return; }
//SITE|NAME=foo|DIR=/tv/|USESKIP=1|INCTEST=%s-INCOMPLETE|LAST_CHECK=123123123 //NUKETEST=!NUKED-%s void conf_site(char **keys, char **values, int items,void *optarg) { char *name, *dir, *useskip, *inctest, *nuketest, *last_check, *hide; site_t *site, **tmp; char **dtmp; char *strtmp; int i; name = parser_findkey(keys, values, items, "NAME"); useskip = parser_findkey(keys, values, items, "USESKIP"); inctest = parser_findkey(keys, values, items, "INCTEST"); nuketest = parser_findkey(keys, values, items, "NUKETEST"); hide = parser_findkey(keys, values, items, "HIDE"); last_check = parser_findkey(keys, values, items, "LAST_CHECK"); if (!name) { printf("SITE Entry in conf without NAME= field\n"); return; } // Attempt to find a site already defined by name, if found, allow // HIDE to be concatenated. for (i = 0; i < num_sites; i++) { if (sites[i] && !mystrccmp(name, sites[i]->name)) { if (hide) { if (!sites[i]->hide) { SAFE_COPY(sites[i]->hide, hide); } else { strtmp = sites[i]->hide; sites[i]->hide = misc_strjoin(strtmp?strtmp:"", hide); SAFE_FREE(strtmp); } } return; } } site = calloc(1, sizeof(*site)); if (!site) return; tmp = realloc(sites, sizeof(site_t *) * (num_sites + 1)); if (!tmp) return; sites = tmp; sites[num_sites] = site; num_sites++; SAFE_COPY(site->name, name); while ((dir = parser_findkey_once(keys, values, items, "DIR"))) { dtmp = (char **) realloc(site->dirs, sizeof(char *) * (site->num_dirs + 1)); if (!dtmp) break; site->dirs = dtmp; site->dirs[ site->num_dirs ] = strdup(dir); site->num_dirs++; } SAFE_COPY(site->inctest, inctest); SAFE_COPY(site->nuketest, nuketest); SAFE_COPY(site->hide, hide); if (useskip) site->use_lists = atoi(useskip); if (last_check) { site->last_check = strtoul(last_check, NULL, 10); site->last_check -= default_age; } else { site->last_check = lion_global_time; site->last_check -= default_age; } site->num_files = 0; }
int file_parse(lfile_t *result, char *line) { char *ar, *perm, *thingy, *user, *group, *size, *name; char date[14]; yesnoauto_t directory; yesnoauto_t soft_link = YNA_NO; int len; //debugf(" [file] '%s'\n", line); if (!line) return -1; memset(result, 0, sizeof(*result)); // drwxr-xr-x 7 root root 1024 Mar 3 18:36 .. // -rw-r--r-- 1 ftp ftp 5 Nov 10 11:42 Return // drwxr-xr-x F0 lftpd lftpd 0 Mar 27 1999 Cd2 // -rw-r--r-- D0 lftpd lftpd 0 Mar 27 1999 sample.j // drwxrwxrwx 1 user group 0 Jun 22 1999 old // -rwxrwxrwx 1 user group 5327872 Nov 30 1998 q2-3.20-x86.exe // dr-xr-xr-x 1 owner group 0 Feb 25 0:31 developr // -r-xr-xr-x 1 owner group 7983 Jan 28 1999 dirmap.htm // // Bollox, some FTP sites don't have that initial argument. // ar = (char *)line; if (!(perm = misc_digtoken(&ar, " \t\r\n"))) goto parse_error; if (!mystrccmp("total", perm)) { // it's the "total XX" line, ignore it. file_free(result); return -1; } if (strlen(perm) != 10) { // We assume it's always this length debugf("[%s] Unknown data, permission section isn't strlen 10 :'%s' - '%s'\n", "file", perm, ar); goto parse_error; } // Parse out the rest if (!(thingy = misc_digtoken(&ar, " \t\r\n"))) goto parse_error; if (!(user = misc_digtoken(&ar, " \t\r\n"))) goto parse_error; if (!(group = misc_digtoken(&ar, " \t\r\n"))) goto parse_error; if (!(size = misc_digtoken(&ar, " \t\r\n"))) goto parse_error; // Bollox! // Here, if size is actually a month "Feb" etc, we have // one less argument than expected!! // So we try to back track somewhat... // if ((strlen(size) == 3) && isalpha(size[0]) && isalpha(size[1]) && isalpha(size[2])) { // Back the date into area, decrementing a char * hmmm :) *(--ar) = ' '; *(--ar) = size[2]; *(--ar) = size[1]; *(--ar) = size[0]; size = group; group = user; user = thingy; } while (*ar == ' ') ar++; // skip any whitespace to the date section. strncpy(date, ar, 12); date[12] = 0; if (strlen(date) != 12) goto parse_error; // The rest is file/dir name. // This is faulty. Technically would parse filenames starting with // a space incorrectly. " hello" would be "hello". name = &ar[12]; while (*name == ' ') name++; #if 0 printf("Parsed line: \n"); printf("\tperm: '%s'\n", perm); printf("\tthingy: '%s'\n", thingy); printf("\tuser: '******'\n", user); printf("\tgroup: '%s'\n", group); printf("\tsize: '%s'\n", size); printf("\tdate: '%s'\n", date); printf("\tname: '%s'\n", name); #endif // Check it is either a file or a dir. Ignore all other switch (tolower(perm[0])) { case 'd': directory = YNA_YES; break; case '-': case 'b': // block device. For device nodes etc. case 'c': // character device. directory = YNA_NO; break; case 'l': // Ok we need to handle links as well directory = YNA_AUTO; soft_link = YNA_YES; break; default: // Skip all others goto parse_error; } // Always ignore . and .. // really? Also, return failure, not success len = strlen(name); if (!strcmp(name, ".") || !strcmp(name, "..")) return 1; if ((len >= 2) && !strcmp(&name[len-2], "/.")) return 1; if ((len >= 3) && !strcmp(&name[len-3], "/..")) return 1; result->size = (lion64u_t) strtoull(size, NULL, 10); result->directory = directory; result->soft_link = soft_link; result->name = strdup(name); result->user = strdup(user); result->group = strdup(group); result->date = misc_getdate(date); strcpy(result->perm, perm); //debugf("[file] parsed '%s' ok\n", name); // Return node. return 0; parse_error: debugf("[file] unable to parse input: '%s'\n", ar ? ar : "(null)"); file_free(result); return -1; }
time_t misc_getdate(char *date) { struct tm tmw, *tmn; char *ar, *token, *r; int i; static char months[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; // It is either // 'Nov 10 11:44' for less than 6mnths old or // 'Mar 27 1999' for more. memset(&tmw, 0, sizeof(tmw)); ar = date; // read month if (!(token = misc_digtoken(&ar, " "))) goto getdate_error; for (i = 0; i < 12; i++) if (!mystrccmp(months[i], token)) { tmw.tm_mon = i; break; } if (i == 12) goto getdate_error; // get day of month if (!(token = misc_digtoken(&ar, " "))) goto getdate_error; tmw.tm_mday = atoi(token); // get either time, or, year if (!(token = misc_digtoken(&ar, " "))) goto getdate_error; if ((r = strchr(token, ':'))) { // it's time *r = 0; tmn = localtime(&lion_global_time); if (!tmn) goto getdate_error; tmw.tm_hour = atoi(token); tmw.tm_min = atoi(&r[1]); tmw.tm_year = tmn->tm_year; // Ok, if we are in January, but the Month read was Dec or // earlier, we need to go -1 on the year. I think this can be // expressed as now_month - read_month < -6 if ((tmn->tm_mon - tmw.tm_mon) <= -6) tmw.tm_year -= 1; } else { // It's the year tmw.tm_year = atoi(token) - 1900; // as according to the man page } // Convert it into a time_t, well, as close as possible. return mktime(&tmw); getdate_error: return 0; }
//<< DIRLIST|SID=1|FID=0|NAME=giana_sounds|DATE=1057590000|SIZE=512|USER=nobody|GROUP=nobody|PERM=drwxrwxrwx|type=directory void site_cmd_dirlist(char **keys, char **values, int items,void *optarg) { fxpone_t *the_engine = optarg; char *sid, *name, *fid, *date, *size, *type, *end, *begin; int i; unsigned int id; site_t *site; file_t *file, **tmp; sid = parser_findkey(keys, values, items, "SID"); name = parser_findkey(keys, values, items, "NAME"); fid = parser_findkey(keys, values, items, "FID"); date = parser_findkey(keys, values, items, "DATE"); size = parser_findkey(keys, values, items, "SIZE"); type = parser_findkey(keys, values, items, "FTYPE"); begin = parser_findkey(keys, values, items, "BEGIN"); end = parser_findkey(keys, values, items, "END"); if (!sid) return; if (begin) return; id = atoi(sid); for (i = 0; i < num_sites; i++) { if (!sites[i]) continue; if (sites[i]->sid == id) { site = sites[i]; if (end) { site->current_dir++; if (site->current_dir >= site->num_dirs) { site_ready(the_engine->handle, site); return; } printf("Site %s processing dir '%s'\n", sites[i]->name, sites[i]->dirs[sites[i]->current_dir]); lion_printf(the_engine->handle, "CWD|SID=%u|PATH=%s\r\n", sites[i]->sid, sites[i]->dirs[sites[i]->current_dir]); return; } // Don't show entries in HIDE if (sites[i]->hide && file_listmatch(sites[i]->hide, name)) return; // SAFE_COPY(sites[i]->name, name); file = file_new(); if (!file) return; tmp = realloc(site->files, sizeof(file_t *)*(site->num_files + 1)); if (!tmp) { file_free(file); return; } site->files = tmp; site->files[ site->num_files ] = file; site->num_files++; SAFE_COPY(file->name, name); if (date) file->date = strtoul(date, NULL, 10); if (size) file->size = strtoull(size, NULL, 10); if (type && !mystrccmp("directory", type)) file->type = 1; // Remember the source path we came from file->current_dir = site->current_dir; } } }
static int llrar_handler(lion_t *handle, void *user_data, int status, int size, char *line) { request_t *node = (request_t *) user_data; int directory; char list[1024]; char *name, *fsize, *packed, *ratio, *date, *thyme, *attr; char *ar, *path, *slash, *root; llrar_cache_entry_t *runner, *next; llrar_cache_t *cache; // If node isn't set, it's b0rken. if (!node) return 0; switch(status) { case LION_CONNECTION_CONNECTED: debugf("[llrar] connected to external process, issuing root for /%s\n", node->path); break; case LION_PIPE_RUNNING: debugf("[llrar] unrar is running\n"); //lion_printf(handle, "HELLO THERE\r\n"); debugf("[llrar] clearing cache slot %d.\n", llrar_cache_index); // Set up RAR cache here. cache = &llrar_cache[ llrar_cache_index ]; node->llrar_cacher = (void *) cache; // If this entry is in use, free it. SAFE_FREE(cache->path); cache->path = strdup(node->disk_path); for (runner = cache->files; runner; runner = next) { next = runner->next; file_free(&runner->file); SAFE_FREE(runner); } cache->files = NULL; // Increase cache pointer llrar_cache_index++; if (llrar_cache_index >= LLRAR_CACHE_SIZE) llrar_cache_index = 0; break; case LION_PIPE_FAILED: debugf("[llrar] unrar failed to launch: %d:%s\n", size, line); node->llrar_cacher = NULL; node->althandle = NULL; SAFE_FREE(node->rar_name); request_finishdir(node); break; case LION_PIPE_EXIT: debugf("[llrar] unrar finished: %d\n", size); if (size == -1) { lion_want_returncode(handle); break; } node->llrar_cacher = NULL; node->althandle = NULL; SAFE_FREE(node->rar_name); request_finishdir(node); //llrar_dumpcache(); break; case LION_INPUT: // Name Size Packed Ratio Date Time Attr CRC Meth Ver //------------------------------------------------------------------------------- // aaf-rc.s03e13.avi 105119744 14999906 --> 11-11-07 23:52 .....A. 78AF2535 m0g 2.0 //------------------------------------------------------------------------------- debugf("[llrar] >> '%s'\n", line); switch(node->unrar_parse) { case 0: // start of unrar list, waiting for line with ----- if (!strncmp("--------------------", line, 20)) node->unrar_parse++; break; case 1: // woohooo, actually parsing entries // This is the filename part // " directory1/directory2/file2.avi" if (!strncmp("--------------------", line, 20)) { node->unrar_parse = 0; break; } if (*line != ' ') { debugf("[llrar] unable to parse: '%s'\n", line); break; } // Skip that leading space. if (*line == ' ') line++; // Remember this line until next parsing line. node->rar_name = strdup(line); node->unrar_parse++; break; case 2: // parse out filesize, type etc. // " 7 17 242% 04-12-07 14:11 -rw-r--r-- 16B28489 m3b 2.9" // Alternate filename/data lines, change back to filename node->unrar_parse = 1; ar = line; // node->rar_name hold the FULL path name. fsize = misc_digtoken(&ar, " \r\n"); packed = misc_digtoken(&ar, " \r\n"); ratio = misc_digtoken(&ar, " \r\n"); date = misc_digtoken(&ar, " \r\n"); thyme = misc_digtoken(&ar, " \r\n"); attr = misc_digtoken(&ar, " \r\n"); if (!node->rar_name || !fsize|| !*fsize|| !attr || !*attr) { debugf("[llrar] unable to parse -- skipping\n"); break; } // Files spanning Volumes will be repeated, but we can tell by // lookip at "ratio" column. if (!mystrccmp("<->", ratio) || !mystrccmp("<--", ratio)) { SAFE_FREE(node->rar_name); break; } debugf("[llrar] parsed name '%s'\n", node->rar_name); // Now we need to look at the rar_file fullname, and // split it into directory/filename // Find last slash. Will windows use '\' ? #ifdef WIN32 for (name = node->rar_name; *name; name++) if (*name == '\\') *name = '/'; #endif slash = strrchr(node->rar_name, '/'); if (!slash) { // We are in root. path = "/"; name = node->rar_name; } else { // We are in a subdir *slash = 0; name = &slash[1]; path = node->rar_name; } // Now "path" should hold full path, and "name" just the // entry name. if (node->rar_directory) { root = node->rar_directory; // Skip leading "/" as unrar wont start with / while (*root == '/') root++; } else root = "/"; debugf("[llrar] Checking '%s' == '%s'\n", path, root); // Now check if it is for a path we care about // and not in cachefill-only mode if (!node->llrar_cache_fill && !mystrccmp(path, root)) { // It is //rar attributes. If DOS format, it will be // .D..... : 7 chars. // Unix format: // d--------- : 10 chars directory = 0; if ((tolower(*attr) == 'd') || (tolower(attr[1]) == 'd')) directory = 1; if (node->dvdread_file) { if (directory) snprintf(list, sizeof(list), "drwxr-xr-x 1 unrar unrar %s Jun 7 %s %s?fv=%"PRIu64",%s&d=%s/%s", fsize, thyme, node->path, node->bytes_size, node->dvdread_file, node->rar_directory ? node->rar_directory : "", name); else snprintf(list, sizeof(list), "-rwxr-xr-x 1 unrar unrar %s Jun 7 %s %s?fv=%"PRIu64",%s&f=%s,%s/%s", fsize, thyme, node->path, node->bytes_size, node->dvdread_file, fsize, node->rar_directory ? node->rar_directory : "", name); } else { // No dvdread_file (RARISO) if (directory) snprintf(list, sizeof(list), "drwxr-xr-x 1 unrar unrar %s Jun 7 %s %s?d=%s/%s", fsize, thyme, node->path, node->rar_directory ? node->rar_directory : "", name); else snprintf(list, sizeof(list), "-rwxr-xr-x 1 unrar unrar %s Jun 7 %s %s?f=%s,%s/%s", fsize, thyme, node->path, fsize, node->rar_directory ? node->rar_directory : "", name); } // dvdread_file skin_write_type(node, list); } // directory we care about (in our path) // RAR cache. if (node->llrar_cacher) { llrar_cache_entry_t *nfile; nfile = (llrar_cache_entry_t *)malloc(sizeof(llrar_cache_entry_t)); if (nfile) { memset(nfile, 0, sizeof(*nfile)); nfile->file.name = misc_strjoin(path, name); nfile->file.size = strtoull(fsize, NULL, 10); nfile->file.directory = YNA_NO; // Link in nfile->next = ((llrar_cache_t *)(node->llrar_cacher))->files; ((llrar_cache_t *)(node->llrar_cacher))->files = nfile; } // malloc } // cacher // Release the filename from previous line. SAFE_FREE(node->rar_name); break; case 3: // seen ----- the rest is fluff break; } break; } return 0; }
int llrar_get(request_t *node, char *executable) { char buffer[1024]; int keep_process; debugf("[llrar] get file requested: '%s' ('%s')\n", node->path, node->dvdread_file ? node->dvdread_file : ""); // Alas, subtitle lookup will have wrong size:( if (node->rar_file && !lfnmatch("*.srt", node->rar_file, LFNM_CASEFOLD)) { node->bytes_size = 500 * 1024; } // HEAD MODE, DO NOTHING if (node->head_method) return 0; // Safety, we aren't called if this is not set in request.c if (!node->rar_file) return 0; // Now, we both need to url_decode this part, and re-assign. // name = request_url_decode(ar); // Keep process? keep_process = 0; debugf("[llrar] checking for resume: rar_name (%s), althandle (%p), name (%s), from (%"PRIu64") >= sent (%"PRIu64")\n", node->rar_name ? node->rar_name : "", node->althandle, node->rar_file ? node->rar_file : "", node->bytes_from, node->bytes_sent); if (node->rar_name && node->althandle && !mystrccmp(node->rar_file, node->rar_name) && node->bytes_from >= node->bytes_sent) { keep_process = 1; debugf("[llrar] resuming old unrar\n"); llrar_resumed_get++; } // Now, if we have special unrar with seek support, we should use it if // we are seeking far. if (keep_process) { // We thought we were going to keep the process, but lets see if the // seek is too big, we might as well abort, and use the seek feature. if ((node->bytes_from - node->bytes_sent) >= LLRAR_SEEK_TRIGGER) { keep_process = 0; debugf("[llrar] seek too large, respawning with seek: %"PRIu64" <= %"PRIu64"\n", node->bytes_from, node->bytes_sent); } } if (!keep_process) { #ifdef WITH_UNRAR_BUFFERS // We have decided we need to restart the unrar process here, // but as a special case, if we can satisfy the ENTIRE request // from cached-buffers, do so instead and update no variables. if (llrar_incaches(node)) return 0; #endif llrar_stop_process(node); // Copy the rar_file name to rar_name, so we can compare for resumes node->rar_name = strdup(node->rar_file); #ifdef WIN32 // Skip leading slash, since we skip that in the print. Then // convert all "/" to "\" since unrar.exe expects it. { char *r = node->rar_name; while (*r == '/') r++; while ((r = strchr(r, '/'))) *r = '\\'; } #endif debugf("[[llrar] using unrar with seek %"PRIu64".\n", node->bytes_from); if (node->dvdread_file) { debugf("[llrar] RARISO for '%s'\n", node->dvdread_file); snprintf(buffer, sizeof(buffer), "%s p -X \"%s\" -R \"%s\" -inul -c- -p- -y -cfg- -sk%"PRIu64" -- \"%s\" \"%s\"", executable, skin_get_rar(), node->dvdread_file, node->bytes_from, node->disk_path, (node->rar_name[0] == '/') ? &node->rar_name[1] : node->rar_name); } else { // Not ISO in RAR, straight... snprintf(buffer, sizeof(buffer), "%s p -inul -c- -p- -y -cfg- -sk%"PRIu64" -- \"%s\" \"%s\"", executable, node->bytes_from, node->disk_path, (node->rar_name[0] == '/') ? &node->rar_name[1] : node->rar_name); } // RARISO // Make it think we've already seen "seek" bytes. node->bytes_sent = node->bytes_from; debugf("[llrar] spawning new '%s'\n", buffer); node->unrar_parse = 0; llrar_spawned_get++; node->althandle = lion_system(buffer, 1, LION_FLAG_NONE, node); if (!node->althandle) { debugf("[llrar] failed to launch unrar\n"); llrar_fail(node); // request_reply(node, 513, "failed to launch unrar"); return -2; } // Set extract handler lion_set_handler(node->althandle, llrar_extract_handler); // Set binary mode lion_enable_binary(node->althandle); // Disable read until we are ready lion_disable_read(node->althandle); } // !keep_process // Set right chunk mode. llrar_compute_blocksize(node); debugf("[llrar] processing: sent (%"PRIu64") bytes_from (%"PRIu64") bytes_to (%"PRIu64")\n", node->bytes_sent, node->bytes_from, node->bytes_to); return 0; }
// // This takes the "virtual path" ->path sent over by the HTTP request, and // attempts to match it to one of the roots we have setup from conf file. // If there is a valid match, ->disk_path is assigned. // // Note that if "disk_path" is already set, we don't do anything, and assume // it is good. Only place that sets it apart from this function, is when we // copy over the temporary filename, which is strictly controlled in // request_action() // int root_setpath(request_t *node) { char *tmpname, *subdir, *skin_root = NULL; char *str; int i; // If disk_path is set, we need not do anything. if (node->disk_path && node->disk_path) { debugf("[root] trusting that '%s' is valid.\n", node->disk_path); // However, if the path is "/", or stat to a directory we // call dirlist. stat(node->disk_path, &node->stat); return 0; } // Reduce away any naughty "../../../" parts. root_undot(node->path); // If its "/" we just leave it as that. if (!mystrccmp("/", node->path)) { // Strictly not needed. We dont expand "/" to the real root as // we may have multiple real roots. So it is left as a secret // match strict which starts listing of all roots. SAFE_COPY(node->disk_path, node->path); return 0; } // Anything else, we need to find the "right" root, and // set full path. Any multiple hits are ignored as we just // settle for first come. // First we check if it is in the skin directory. if ((skin_root = skin_get_root(node->skin_type))) { tmpname = misc_strjoin(skin_root, node->path); debugf("[root] testing path '%s'\n", tmpname); // Windows does not like "directory/" in stat. misc_stripslash(tmpname); if (!stat(tmpname, &node->stat)) { // misc_strjoin allocates string, so we can just assign it. node->disk_path = tmpname; // Caveat, if the target is a directory, we have to ensure // it has a trailing "/" for dirlist's precat in ->path if (S_ISDIR(node->stat.st_mode) && node->path[ strlen(node->path) ] != '/') { tmpname = misc_strjoin(node->path, ""); SAFE_FREE(node->path); node->path = tmpname; } return 0; } SAFE_FREE(tmpname); } // skin #if 0 // The above (identical) code uses skin_get_root() which should return // the root of the current skin, which should be set to the upnp skin // in skin_set_skin(). // First we check if it is in the upnpskin directory. if (skin_upnp_root) { tmpname = misc_strjoin(skin_upnp_root, node->path); debugf("[root] testing path '%s'\n", tmpname); // Windows does not like "directory/" in stat. misc_stripslash(tmpname); if (!stat(tmpname, &node->stat)) { // misc_strjoin allocates string, so we can just assign it. node->disk_path = tmpname; // Caveat, if the target is a directory, we have to ensure // it has a trailing "/" for dirlist's precat in ->path if (S_ISDIR(node->stat.st_mode) && node->path[ strlen(node->path) ] != '/') { tmpname = misc_strjoin(node->path, ""); SAFE_FREE(node->path); node->path = tmpname; } return 0; } SAFE_FREE(tmpname); } //upnp skin #endif // Now try all the roots defined. for (i = 0; i < root_count; i++) { // Check for exact http ROOT matches if (root_array[i].http_host) { // If its a proxy request (file mode) if (node->cgi_host && node->cgi_file) { node->root_index = i; node->stat.st_mode = S_IFREG; node->disk_path = strdup("http-proxy"); return 0; } // it will start with a slash, so skip it str = node->path; while (*str == '/') str++; // Compare it if (!mystrccmp(root_array[i].path, str)) { debugf("[root] ROOT|http match '%s'\n", str); node->root_index = i; // Due to stat()s, we need to send a real dir here. // Don't worry, "/" means dirlist, not that it lists from root node->disk_path = strdup("http-listing"); //Fake a stat of a dirlist node->stat.st_mode = S_IFDIR; return 0; } } tmpname = misc_strjoin(root_array[i].path, node->path); misc_stripslash(tmpname); debugf("[root] testing path '%s'\n", tmpname); if (!stat(tmpname, &node->stat)) { // misc_strjoin allocates string, so we can just assign it. node->disk_path = tmpname; // Caveat, if the target is a directory, we have to ensure // it has a trailing "/" for dirlist's precat in ->path if (S_ISDIR(node->stat.st_mode) && node->path[ strlen(node->path) ] != '/') { tmpname = misc_strjoin(node->path, ""); SAFE_FREE(node->path); node->path = tmpname; } node->root_index = i; return 0; } SAFE_FREE(tmpname); } // This test destroys node->path, so it needs to be last debugf("[root] testing for SUBDIR type: '%s'\n", node->path); // it might be using a SUBDIR style syntax. str = node->path; while (*str == '/') str++; // Might be the root of SUBDIR, or deeper request. if ((subdir = strchr(str, '/'))) { *subdir = 0; subdir++; } else { subdir = ""; } debugf("[root] looking for '%s' rest '%s'\n", str, subdir); for (i = 0; i < root_count; i++) { if (root_array[i].subdir && !mystrccmp(root_array[i].subdir, str)) { node->disk_path = misc_strjoin(root_array[i].path, subdir); debugf("[root] testing subdir path '%s'\n", node->disk_path); misc_stripslash(node->disk_path); if (!stat(node->disk_path, &node->stat)) { // Caveat, if the target is a directory, we have to ensure // it has a trailing "/" for dirlist's precat in ->path // path = path + subdir tmpname = misc_strjoin(node->path, subdir); SAFE_FREE(node->path); node->path = tmpname; if (S_ISDIR(node->stat.st_mode) && node->path[ strlen(node->path) ] != '/') { tmpname = misc_strjoin(node->path, ""); SAFE_FREE(node->path); node->path = tmpname; } node->root_index = i; debugf("[root] returning subdir: '%s':%d\n", node->disk_path, node->root_index); return 0; } // stat } // mystrccmp } // for roots debugf("[root] giving up, path not valid.\n"); // we've trashed the path anyway? SAFE_FREE(node->path); // Invalid path. Do we ensure it will fail later here? Or just assume // that the stat will fail later on. return -1; }
// // Take a http request node, which should have "cwd" filled in appropriately. // We then call dirlist to issue listing(s) for this path. // void root_list(request_t *node, char *newpath) { int flags; // Fetch the current directory. Note if they request "/" // we need to iterate all "root"s. debugf("[root] listing of '%s' requested\n", newpath); // FIXME, no paths. if (!root_count) return; // If next_list is 0 we only list one directory. If it is not 0, // we list that and increment. node->next_list = 0; if (!mystrccmp("/", newpath)) { // List more, if any. node->next_list = 1; } // Set handler to be here, temporarily lion_set_handler(node->tmphandle, root_handler); if (node->next_list) { debugf("[root] root listing, iterating roots\n"); node->next_list = 0; // Issue listing request root_next_list(node, node->tmphandle); return; } // HTTP method if ((node->root_index < 0) || (node->root_index >= root_count)) return; if (root_array[node->root_index].http_host) { root_http_list(node, node->tmphandle); return; } // Stop dirlisting at this one. node->next_list = root_count; // Some dirlist flags need to be passed down to libdirlist... flags = skin_get_sort_flags(node); flags &= (DIRLIST_SHOW_DIRSIZE|DIRLIST_SHOW_GENRE); debugf("[root] asking for dirlist of '%s' with precat of '%s'\n", newpath, node->path); // Just list dirlist_list(node->tmphandle, newpath, node->path, root_isregistered(node) ? (root_array[node->root_index].flags|DIRLIST_SHOW_DOT|flags) : (root_array[node->root_index].flags|flags), node); }
file_t *file_parse(char *line, int raw) { file_t *result; char *ar, *perm, *thingy, *user, *group, *size, *name, *month, *day, *timeyear; char date[14]; yesnoauto_t directory = YNA_NO; yesnoauto_t soft_link = YNA_NO; //debugf(" [file] '%s'\n", line); if (!line) return NULL; result = (file_t *) malloc(sizeof(*result)); if (!result) return NULL; memset(result, 0, sizeof(*result)); // Copy the line if they requested it. if (raw) result->raw = strdup(line); // drwxr-xr-x 7 root root 1024 Mar 3 18:36 .. // -rw-r--r-- 1 ftp ftp 5 Nov 10 11:42 Return // drwxr-xr-x F0 lftpd lftpd 0 Mar 27 1999 Cd2 // -rw-r--r-- D0 lftpd lftpd 0 Mar 27 1999 sample.j // drwxrwxrwx 1 user group 0 Jun 22 1999 old // -rwxrwxrwx 1 user group 5327872 Nov 30 1998 q2-3.20-x86.exe // dr-xr-xr-x 1 owner group 0 Feb 25 0:31 developr // -r-xr-xr-x 1 owner group 7983 Jan 28 1999 dirmap.htm // // drwxr-xr-x 1 cubnc cubnc 512 Aug 7 7:54 TV-TODAY // drwxr-xr-x 1 cubnc cubnc 512 Jul 31 6:36 0c 3.7 Terrabytes Online // drwxr-xr-x 1 cubnc cubnc 512 Jul 31 6:36 MUSICDVDR // Bollox, some FTP sites don't have that initial argument. // ar = (char *)line; if (!(perm = misc_digtoken(&ar, " \t\r\n"))) goto parse_error; if (!mystrccmp("total", perm)) { // it's the "total XX" line, ignore it. file_free(result); return NULL; } if (strlen(perm) != 10) { // We assume it's always this length debugf("[%s] Unknown data, permission section isn't strlen 10 :'%s' - '%s'\n", "file", perm, ar); goto parse_error; } // Parse out the rest if (!(thingy = misc_digtoken(&ar, " \t\r\n"))) goto parse_error; if (!(user = misc_digtoken(&ar, " \t\r\n"))) goto parse_error; if (!(group = misc_digtoken(&ar, " \t\r\n"))) goto parse_error; if (!(size = misc_digtoken(&ar, " \t\r\n"))) goto parse_error; // Bollox! // Here, if size is actually a month "Feb" etc, we have // one less argument than expected!! // So we try to back track somewhat... // if ((strlen(size) == 3) && isalpha(size[0]) && isalpha(size[1]) && isalpha(size[2])) { // Back the date into area, decrementing a char * hmmm :) *(--ar) = ' '; *(--ar) = size[2]; *(--ar) = size[1]; *(--ar) = size[0]; size = group; group = user; user = thingy; } while (*ar == ' ') ar++; // skip any whitespace to the date section. // Ok, we can not assume date is always 12 chars. Shame. // "Jan 28 1999" // "Aug 7 7:54" if (!(month = misc_digtoken(&ar, " \t\r\n"))) goto parse_error; if (!(day = misc_digtoken(&ar, " \t\r\n"))) goto parse_error; if (!(timeyear = misc_digtoken(&ar, " \t\r\n"))) goto parse_error; if ((strlen(month) + strlen(day) + strlen(timeyear)) <= 10) snprintf(date, sizeof(date), "%s %s %s", month, day, timeyear); else strcpy(date, "Jan 1 1970"); //strncpy(date, ar, 12); //date[12] = 0; //if (strlen(date) != 12) // goto parse_error; // Now, there HAS to be ONE space after the date. // Anymore and it COULD be part of the filename. // The rest is file/dir name. // This is faulty. Technically would parse filenames starting with // a space incorrectly. " hello" would be "hello". //name = &ar[12]; name = ar; while (*name == ' ') name++; // <- wrong #if 0 printf("Parsed line: \n"); printf("\tperm: '%s'\n", perm); printf("\tthingy: '%s'\n", thingy); printf("\tuser: '******'\n", user); printf("\tgroup: '%s'\n", group); printf("\tsize: '%s'\n", size); printf("\tdate: '%s'\n", date); printf("\tname: '%s'\n", name); #endif // Check it is either a file or a dir. Ignore all other switch (tolower(perm[0])) { case 'd': directory = YNA_YES; break; case '-': directory = YNA_NO; break; case 'l': // Ok we need to handle links as well directory = YNA_AUTO; soft_link = YNA_YES; break; default: // Skip all others goto parse_error; } // Always ignore . and .. // really? if (!strcmp(name, ".") || !strcmp(name, "..")) { file_free(result); return NULL; } result->size = (lion64u_t) strtoull(size, NULL, 10); result->directory = directory; result->soft_link = soft_link; result->name = strdup(name); result->user = strdup(user); result->group = strdup(group); result->date = misc_getdate(date); strcpy(result->perm, perm); //debugf("[file] parsed '%s' ok\n", name); // Return node. return result; parse_error: debugf("[file] unable to parse input: '%s'\n", ar ? ar : "(null)"); file_free(result); return NULL; }
// >> SITELIST|SITEID=1|NAME=localhost|HOST=127.0.0.1|PORT=21|USER=mp3|PASS=mp3|PASSIVE=1|FXP_PASSIVE=2|CONTROL_TLS=2|DATA_TLS=2|optional_variable=roger moore void site_cmd_sitelist(char **keys, char **values, int items,void *optarg) { fxpone_t *the_engine = optarg; char *name, *siteid, *end; char *dskiplist, *dpasslist, *fskiplist, *fpasslist, *fskipempty; int i; end = parser_findkey(keys, values, items, "END"); name = parser_findkey(keys, values, items, "NAME"); siteid = parser_findkey(keys, values, items, "SITEID"); if (end) { // num_sitelist has how many sites we found and connected to // num_sites is how many we are waiting for before processing. num_sites = num_sitelist; return; } if (!name || !siteid) return; dskiplist = parser_findkey(keys, values, items, "DSKIPLIST"); dpasslist = parser_findkey(keys, values, items, "DPASSLIST"); fskiplist = parser_findkey(keys, values, items, "FSKIPLIST"); fpasslist = parser_findkey(keys, values, items, "FPASSLIST"); fskipempty = parser_findkey(keys, values, items, "FSKIPEMPTY"); for (i = 0; i < num_sites; i++) { if (!sites[i]) continue; if (!mystrccmp(sites[i]->name, name)) { sites[i]->siteid = atoi(siteid); SAFE_COPY(sites[i]->dskiplist, dskiplist); SAFE_COPY(sites[i]->dpasslist, dpasslist); SAFE_COPY(sites[i]->fskiplist, fskiplist); SAFE_COPY(sites[i]->fpasslist, fpasslist); if (fskipempty && (atoi(fskipempty) == 0)) sites[i]->fskipempty = 0; else sites[i]->fskipempty = 1; num_sitelist++; // IRC sets skip, so we dont do initial login if (!sites[i]->skip) lion_printf(the_engine->handle, "SESSIONNEW|SITEID=%u\r\n", atoi(siteid)); } } }