void h_mfmt(struct context *ctx, char *arg) { char *t; struct stat st; struct tm tm; DebugIn(DEBUG_COMMAND); t = arg; while (*arg && !isspace((int) *arg)) arg++; if (!isspace((int) *arg)) { reply(ctx, MSG_500_arguments_required); DebugOut(DEBUG_COMMAND); return; } memset(&tm, 0, sizeof(tm)); *arg++ = 0; if (*arg && 6 == sscanf(t, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec)) { struct utimbuf ut; tm.tm_year -= 1900; tm.tm_mon--; ut.modtime = mktime(&tm); if ((t = buildpath(ctx, arg)) && (!pickystat(ctx, &st, t)) && (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) && st.st_uid == ctx->uid) { ut.actime = st.st_atime; if (utime(t, &ut)) reply(ctx, MSG_550_Permission_denied); else { struct stat sst; char u[40]; if (stat(t, &sst)) sst.st_mtime = ut.modtime; strftime(u, sizeof(u), "213 Modify=%Y%m%d%H%M%S; ", gmtime(&sst.st_mtime)); replyf(ctx, "%s%s\r\n", u, t); } } else reply(ctx, MSG_550_Permission_denied); } else reply(ctx, MSG_500_missing_filename); DebugOut(DEBUG_COMMAND); }
bool http_servlet::doPost(acl::HttpServletRequest& req, acl::HttpServletResponse& res) { // 如果需要 http session 控制,请打开下面注释,且需要保证 // 在 master_service.cpp 的函数 thread_on_read 中设置的 // memcached 服务正常工作 /* const char* sid = req.getSession().getAttribute("sid"); if (*sid == 0) req.getSession().setAttribute("sid", "xxxxxx"); sid = req.getSession().getAttribute("sid"); */ // 如果需要取得浏览器 cookie 请打开下面注释 /* */ res.setContentType("text/xml; charset=utf-8") // 设置响应字符集 .setKeepAlive(req.isKeepAlive()) // 设置是否保持长连接 .setContentEncoding(true) // 自动支持压缩传输 .setChunkedTransferEncoding(false); // chunk 传输方式 const char* cmd = req.getParameter("cmd"); if (cmd == NULL || *cmd == 0) { logger_error("cmd not found"); return replyf(req, res, 400, "%s", "no cmd"); } #define EQ !strcasecmp acl::string buf; commands_action action(addr_, req, res, cmd); action.set_conf(conf_); int status = action.run(buf); return reply_json(req, res, status, buf); }
static void h_xstor(struct context *ctx, char *arg, int flags) { char *t; int f = -1; struct stat st; int stou = 0; char tbuf[PATH_MAX + 1]; DebugIn(DEBUG_COMMAND); if (ctx->transfer_in_progress) { reply(ctx, MSG_501_Transfer_in_progress); DebugOut(DEBUG_COMMAND); return; } ctx->outgoing_data = 0; if (ctx->dfn > -1 && io_get_cb_i(ctx->io, ctx->dfn) == (void *) accept_data) { io_set_i(ctx->io, ctx->dfn); io_clr_o(ctx->io, ctx->dfn); io_set_cb_e(ctx->io, ctx->dfn, (void *) cleanup_data); io_set_cb_h(ctx->io, ctx->dfn, (void *) cleanup_data); } quota_add(ctx, 0); if (ctx->quota_path && (ctx->quota_ondisk >= ctx->quota_limit)) { reply(ctx, MSG_451_quota_exceeded); logmsg("%s: quota limit reached", ctx->user); DebugOut(DEBUG_COMMAND); return; } if (!arg) { stou = -1; snprintf(tbuf, sizeof(tbuf), "%s/stou.XXXXXX", ctx->cwd); arg = tbuf; t = buildpath(ctx, arg); } else if (acl_binary_only(ctx, arg, (t = buildpath(ctx, arg)))) { reply(ctx, MSG_504_no_ascii); cleanup_data_reuse(ctx, ctx->dfn); DebugOut(DEBUG_COMMAND); return; } st.st_size = 0; if (t) acl_set_umask(ctx, arg, t); if (ctx->anonymous || stou) flags |= O_EXCL; if (t && (!ctx->anonymous || check_incoming(ctx, t, 077)) && !pickystat_path(ctx, &st, t) && (stat(t, &st), (f = myopen(t, O_RDWR | O_CREAT | O_LARGEFILE | O_NOFOLLOW | flags, ctx->chmod_filemask | (0644 & ~ctx->umask), stou)) > -1)) { fcntl(f, F_SETFD, FD_CLOEXEC); ctx->quota_filesize_before_stor = st.st_size; ctx->quota_update_on_close = 1; if (ctx->dfn < 0) connect_port(ctx); if (ctx->dfn < 0) { reply(ctx, MSG_431_Opening_datacon_failed); close(f); ctx->dbuf = buffer_free_all(ctx->dbuf); DebugOut(DEBUG_COMMAND); return; } ctx->ffn = f; if (strlen(t) >= sizeof(ctx->filename)) { logerr("buffer too small in %s:%d (%s/%s)", __FILE__, __LINE__, ctx->user, t); reply(ctx, MSG_551_Internal_error); close(f); cleanup(ctx, ctx->dfn); ctx->dbuf = buffer_free_all(ctx->dbuf); DebugOut(DEBUG_COMMAND); return; } strcpy(ctx->filename, t); ctx->filesize = 0; ctx->bytecount = 0; if (io_get_cb_i(ctx->io, ctx->dfn) == (void *) socket2buffer || is_connected(ctx->dfn)) { if (stou) replyf(ctx, "125 FILE: %s\r\n", ctx->filename + ctx->rootlen); else replyf(ctx, MSG_125_Starting_dc, ctx->use_ascii ? "ASCII" : "BINARY", ctx->use_tls_d ? "TLS " : ""); } else { if (stou) replyf(ctx, "150 FILE: %s\r\n", ctx->filename + ctx->rootlen); else replyf(ctx, MSG_150_Opening_dc, ctx->use_ascii ? "ASCII" : "BINARY", ctx->use_tls_d ? "TLS " : ""); } ctx->transfer_in_progress = 1; if (ctx->io_offset) { if (ctx->use_ascii) { ctx->offset = 0; ctx->remaining = st.st_size; io_sched_add(ctx->io, ctx, (void *) skipbytes, 0, 0); #ifdef WITH_MMAP if (use_mmap) ctx->iomode = IOMODE_mmap; else #endif ctx->iomode = IOMODE_read, ctx->iomode_fixed = 1; } else { lseek(f, ctx->io_offset, SEEK_SET); ctx->io_offset = 0; } } if (io_get_cb_i(ctx->io, ctx->dfn) == (void *) socket2buffer) { /* already connected */ io_clr_o(ctx->io, ctx->dfn); io_set_i(ctx->io, ctx->dfn); } ctx->transferstart = io_now.tv_sec; ctx->count_files++; } else { if (stou && errno == EEXIST) reply(ctx, MSG_451_unique_file_failure); else reply(ctx, MSG_550_Permission_denied); cleanup_data_reuse(ctx, ctx->dfn); } DebugOut(DEBUG_COMMAND); }
void file2control(struct context *ctx, char *arg, char *file) { Debug((DEBUG_PROC, "+ %s (%s)\n", __func__, file ? file : "(NULL)")); if (file && ctx->multiline_banners) { int i = -1; struct stat st; int is_banner = file == ctx->welcome || file == ctx->banner || file == ctx->goodbye; char form[PATH_MAX + 1], path[PATH_MAX + 1]; char *l, *t, llang[10]; if (!is_banner && ctx->readme_once && (!pickystat(ctx, &st, ctx->cwd)) && dir_visited(ctx, &st)) { Debug((DEBUG_PROC, "already visited\n")); DebugOut(DEBUG_PROC); return; } l = llang, t = lang[ctx->lang]; *l++ = '-'; while (*t) *l++ = tolower((int) *t++); *l = 0; if ((sizeof(form) <= (size_t) snprintf(form, sizeof(form), "%s/%s", (is_banner || file[0] == '/') ? "" : ctx->cwd, file)) || (sizeof(path) <= (size_t) snprintf(path, sizeof(path), form, llang))) { DebugOut(DEBUG_PROC); return; } if (is_banner) { i = open(path, O_RDONLY); if (i < 0 && strstr(form, "%s")) { if (sizeof(path) <= (size_t) snprintf(path, sizeof(path), form, "")) { DebugOut(DEBUG_PROC); return; } i = open(path, O_RDONLY); } } else { if (((pickystat(ctx, &st, path) || (i = open(path, O_RDONLY)) < 0)) && strstr(form, "%s")) { if (sizeof(path) <= (size_t) snprintf(path, sizeof(path), form, "")) { DebugOut(DEBUG_PROC); return; } if (!pickystat(ctx, &st, path)) i = open(path, O_RDONLY); } if (i > -1 && ctx->readme_notify) { long days_ago = (io_now.tv_sec - st.st_mtime) / 86400; char tb[2 * PATH_MAX]; close(i); replyf(ctx, "%s-", arg); replyf(ctx, MSG_Readme_notify_1, file); strftime(tb, sizeof(tb), MSG_Readme_notify_2, localtime(&st.st_mtime)); replyf(ctx, "%s-%s", arg, tb); if (days_ago == 1) reply(ctx, MSG_Readme_notify_31); else replyf(ctx, MSG_Readme_notify_3n, days_ago); DebugOut(DEBUG_PROC); return; } } if (i > -1) { char tbuf[BUFSIZE]; char *lineend, *linestart = NULL; size_t offset = 0; ssize_t inlength; while ((inlength = read(i, tbuf + offset, sizeof(tbuf) - 1 - offset)) > 0) { inlength += offset; tbuf[inlength] = 0; linestart = tbuf; while ((lineend = strchr(linestart, '\n'))) { *lineend = 0; chomp(linestart); replyf(ctx, "%s-%s\r\n", arg, cook(ctx, linestart, NULL, NULL, 0)); linestart = lineend + 1; } #ifdef README_LOOP /* * Don't allow arbitrary sized README files. Noone's able or willing to * read thousands of lines rushing by. BUFSIZE is our upper limit. For * unlimited file sizes, #define README_LOOP. Yes, that could be made * a configuration option. No, I don't think it makes sense. */ if ((offset = tbuf + inlength - linestart)) memmove(tbuf, linestart, offset); else #endif break; } close(i); } } DebugOut(DEBUG_PROC); }