📄 smb.c
字号:
while (p > url && !isdigit(*p)) p--; if (p == url) goto print_as_is; /* FIXME: Use parse_date()? */ /* year */ while (p > url && isdigit(*p)) p--; if (p == url || !isspace(*p)) goto print_as_is; while (p > url && isspace(*p)) p--; /* seconds */ while (p > url && isdigit(*p)) p--; if (p == url || *p != ':') goto print_as_is; p--; /* minutes */ while (p > url && isdigit(*p)) p--; if (p == url || *p != ':') goto print_as_is; p--; /* hours */ while (p > url && isdigit(*p)) p--; if (p == url || !isspace(*p)) goto print_as_is; p--; /* day as number */ while (p > url && isdigit(*p)) p--; while (p > url && isspace(*p)) p--; if (p == url) goto print_as_is; /* month */ while (p > url && !isspace(*p)) p--; if (p == url || !isspace(*p)) goto print_as_is; p--; /* day name */ while (p > url && !isspace(*p)) p--; if (p == url || !isspace(*p)) goto print_as_is; while (p > url && isspace(*p)) p--; /* file size */ if (p == url || !isdigit(*p)) goto print_as_is; if (*p == '0' && isspace(*(p - 1))) may_be_dir = 1; while (p > url && isdigit(*p)) p--; if (p == url) goto print_as_is; /* Magic to determine if we have a * filename or a dirname. Thanks to * smbclient ambiguous output. */ { unsigned char *pp = p; while (pp > url && isspace(*pp)) pp--; if (p - pp <= 8) { while (pp > url && (*pp == 'D' || *pp == 'H' || *pp == 'A' || *pp == 'S' || *pp == 'R' || *pp == 'V')) { if (*pp == 'D' && may_be_dir) dir = 1; pp--; } } while (pp > url && isspace(*pp)) pp--; p = pp; } /* Don't display '.' directory */ if (p == url && *url == '.') goto ignored; p++; add_to_string(page, " <a href=\""); add_bytes_to_string(page, url, p - url); if (dir) add_char_to_string(page, '/'); add_to_string(page, "\">"); add_bytes_to_string(page, url, p - url); add_to_string(page, "</a>"); add_bytes_to_string(page, p, line_end - p); } else { goto print_as_is; } } else {print_as_is: add_bytes_to_string(page, line_start, line_len); } add_char_to_string(page, ASCII_LF);ignored: line_start = line_end + start_offset + 1; } add_to_string(page, "</pre></body></html>");}static voidend_smb_connection(struct connection *conn){ struct smb_connection_info *si = conn->info; struct uri *uri; enum connection_state state = S_OK; if (smb_get_cache(conn)) return; if (conn->from) { truncate_entry(conn->cached, conn->from, 1); conn->cached->incomplete = 0; goto bye; } /* Ensure termination by LF + NUL chars, memory for this * was reserved by smb_read_text(). */ if (si->textlen && si->text[si->textlen - 1] != ASCII_LF) si->text[si->textlen++] = ASCII_LF; si->text[si->textlen] = '\0'; uri = conn->uri; if (uri->datalen && uri->data[uri->datalen - 1] != '/' && uri->data[uri->datalen - 1] != '\\' && (strstr(si->text, "NT_STATUS_FILE_IS_A_DIRECTORY") || strstr(si->text, "NT_STATUS_ACCESS_DENIED") || strstr(si->text, "ERRbadfile"))) { redirect_cache(conn->cached, "/", 1, 0); } else { struct string page; if (!init_string(&page)) { state = S_OUT_OF_MEM; goto bye; } parse_smbclient_output(uri, si, &page); add_fragment(conn->cached, 0, page.source, page.length); conn->from += page.length; truncate_entry(conn->cached, page.length, 1); conn->cached->incomplete = 0; done_string(&page); mem_free_set(&conn->cached->content_type, stracpy("text/html")); }bye: close_socket(conn, &conn->socket); close_socket(conn, &conn->data_socket); abort_conn_with_state(conn, state);}/* Close all non-terminal file descriptors. */static voidclose_all_non_term_fd(void){ int n; int max = 1024;#ifdef RLIMIT_NOFILE struct rlimit lim; if (!getrlimit(RLIMIT_NOFILE, &lim)) max = lim.rlim_max;#endif for (n = 3; n < max; n++) close(n);}voidsmb_protocol_handler(struct connection *conn){ int out_pipe[2] = { -1, -1 }; int err_pipe[2] = { -1, -1 }; unsigned char *share, *dir; unsigned char *p; pid_t cpid; int dirlen; struct smb_connection_info *si; struct uri *uri; si = mem_calloc(1, sizeof(*si) + 2); if (!si) { abort_conn_with_state(conn, S_OUT_OF_MEM); return; } conn->info = si; uri = conn->uri; p = strchr(uri->data, '/'); if (p && p - uri->data < uri->datalen) { share = memacpy(uri->data, p - uri->data); dir = p + 1; /* FIXME: ensure @dir do not contain dangerous chars. --Zas */ } else if (uri->datalen) { if (smb_get_cache(conn)) return; redirect_cache(conn->cached, "/", 1, 0); abort_conn_with_state(conn, S_OK); return; } else { share = stracpy(""); dir = ""; } if (!share) { abort_conn_with_state(conn, S_OUT_OF_MEM); return; } dirlen = strlen(dir); if (!*share) { si->list_type = SMB_LIST_SHARES; } else if (!dirlen || dir[dirlen - 1] == '/' || dir[dirlen - 1] == '\\') { si->list_type = SMB_LIST_DIR; } if (c_pipe(out_pipe) || c_pipe(err_pipe)) { int s_errno = errno; if (out_pipe[0] >= 0) close(out_pipe[0]); if (out_pipe[1] >= 0) close(out_pipe[1]); mem_free(share); abort_conn_with_state(conn, -s_errno); return; } conn->from = 0; cpid = fork(); if (cpid == -1) { int s_errno = errno; close(out_pipe[0]); close(out_pipe[1]); close(err_pipe[0]); close(err_pipe[1]); mem_free(share); retry_conn_with_state(conn, -s_errno); return; } if (!cpid) {#define SMBCLIENT "smbclient"#define MAX_SMBCLIENT_ARGS 32 int n = 0; unsigned char *v[MAX_SMBCLIENT_ARGS]; unsigned char *optstr; close(1); dup2(out_pipe[1], 1); close(2); dup2(err_pipe[1], 2); close(0); dup2(open("/dev/null", O_RDONLY), 0); close_all_non_term_fd(); close(out_pipe[0]); close(err_pipe[0]); /* Usage: smbclient service <password> [options] */ v[n++] = SMBCLIENT; /* FIXME: handle alloc failures. */ /* At this point, we are the child process. * Maybe we just don't care if the child kills itself * dereferencing a NULL pointer... -- Miciah */ /* Leaving random core files after itself is not what a nice * program does. Also, the user might also want to know, why * the hell does he see nothing on the screen. --pasky */ if (*share) { /* Construct service path. */ asprintf((char **) &v[n++], "//%.*s/%s", uri->hostlen, uri->host, share); /* Add password if any. */ if (uri->passwordlen && !uri->userlen) { v[n++] = memacpy(uri->password, uri->passwordlen); } } else { /* Get a list of shares available on a host. */ v[n++] = "-L"; v[n++] = memacpy(uri->host, uri->hostlen); } v[n++] = "-N"; /* Don't ask for a password. */ v[n++] = "-E"; /* Write messages to stderr instead of stdout. */ v[n++] = "-d 0"; /* Disable debug mode. */ if (uri->portlen) { /* Connect to the specified port. */ v[n++] = "-p"; v[n++] = memacpy(uri->port, uri->portlen); } if (uri->userlen) { /* Set the network username. */ v[n++] = "-U"; if (!uri->passwordlen) { /* No password. */ v[n++] = memacpy(uri->user, uri->userlen); } else { /* With password. */ asprintf((char **) &v[n++], "%.*s%%%.*s", uri->userlen, uri->user, uri->passwordlen, uri->password); } } if (*share) { /* FIXME: use si->list_type here ?? --Zas */ if (!dirlen || dir[dirlen - 1] == '/' || dir[dirlen - 1] == '\\') { if (dirlen) { /* Initial directory. */ v[n++] = "-D"; v[n++] = dir; } v[n++] = "-c"; /* Execute semicolon separated commands. */ v[n++] = "ls"; /* List files. */ } else { /* Copy remote file to stdout. */ unsigned char *s = straconcat("get \"", dir, "\" -", NULL); unsigned char *ss = s; v[n++] = "-c"; /* Execute semicolon separated commands. */ while ((ss = strchr(ss, '/'))) *ss = '\\'; /* Escape '/' */ v[n++] = s; } } /* Optionally add SMB credentials file. */ optstr = get_opt_str("protocol.smb.credentials"); if (optstr[0]) { v[n++] = "-A"; v[n++] = optstr; } v[n++] = NULL; /* End of arguments list. */ assert(n < MAX_SMBCLIENT_ARGS); execvp(SMBCLIENT, (char **) v); /* FIXME: this message will never be displayed, since execvp() * failed. */ fprintf(stderr, SMBCLIENT " not found in $PATH"); _exit(1);#undef MAX_SMBCLIENT_ARGS#undef SMBCLIENT } mem_free(share); conn->data_socket.fd = out_pipe[0]; conn->socket.fd = err_pipe[0]; close(out_pipe[1]); close(err_pipe[1]); set_handlers(out_pipe[0], (void (*)(void *)) smb_got_data, NULL, NULL, conn); set_handlers(err_pipe[0], (void (*)(void *)) smb_got_text, NULL, NULL, conn); set_connection_state(conn, S_CONN);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -