コード例 #1
0
ファイル: io_file.c プロジェクト: 3runo5ouza/rhodes
void
_shttpd_get_file(struct conn *c, struct stat *stp)
{
	char		date[64], lm[64], etag[64], range[64] = "";
	size_t		n, status = 200;
	unsigned long	r1, r2;
	const char	*fmt = "%a, %d %b %Y %H:%M:%S GMT", *msg = "OK";
	big_int_t	cl; /* Content-Length */

	if (c->mime_type.len == 0)
		_shttpd_get_mime_type(c->ctx, c->uri,
		    strlen(c->uri), &c->mime_type); 
	cl = (big_int_t) stp->st_size;

	/* If Range: header specified, act accordingly */
	if (c->ch.range._v.v_vec.len > 0 &&
    (n = sscanf(c->ch.range._v.v_vec.ptr,"bytes=%lu-%lu",&r1, &r2)) > 0) {
		status = 206;
		(void) lseek(c->loc.chan.fd, r1, SEEK_SET);
		cl = n == 2 ? r2 - r1 + 1: cl - r1;
		(void) _shttpd_snprintf(range, sizeof(range),
		    "Content-Range: bytes %lu-%lu/%lu\r\n",
		    r1, r1 + cl - 1, (unsigned long) stp->st_size);
		msg = "Partial Content";
	}

	/* Prepare Etag, Date, Last-Modified headers */
	(void) strftime(date, sizeof(date),
	    fmt, localtime(&_shttpd_current_time));
	(void) strftime(lm, sizeof(lm), fmt, localtime(&stp->st_mtime));
	(void) _shttpd_snprintf(etag, sizeof(etag), "%lx.%lx",
	    (unsigned long) stp->st_mtime, (unsigned long) stp->st_size);

	/*
	 * We do not do io_inc_head here, because it will increase 'total'
	 * member in io. We want 'total' to be equal to the content size,
	 * and exclude the headers length from it.
	 */
	c->loc.io.head = c->loc.headers_len = _shttpd_snprintf(c->loc.io.buf,
	    c->loc.io.size,
	    "HTTP/1.1 %d %s\r\n"
	    "Date: %s\r\n"
	    "Last-Modified: %s\r\n"
	    "Etag: \"%s\"\r\n"
	    "Content-Type: %.*s\r\n"
	    "Content-Length: %lu\r\n"
	    "Accept-Ranges: bytes\r\n"
	    "%s\r\n",
	    status, msg, date, lm, etag,
	    c->mime_type.len, c->mime_type.ptr, cl, range);

	c->status = status;
	c->loc.content_len = cl;
	c->loc.io_class = &_shttpd_io_file;
	c->loc.flags |= FLAG_R | FLAG_ALWAYS_READY;

	if (c->method == METHOD_HEAD)
		_shttpd_stop_stream(&c->loc);
}
コード例 #2
0
ファイル: rdispatcher.c プロジェクト: bijukrishna/rhodes
void* rho_dispatch(struct conn *c, const char* path) {
  RouteRef route;

  if ( _shttpd_match_extension(c->uri,"css,js,html,htm,png,bmp,jpg") )
    return NULL;

  if ((route = _alloc_route(c->uri)) != NULL) {
    if (_parse_route(route)) {
      struct stat	st;
      //is this an actual file or folder
      if (_shttpd_stat(path, &st) != 0)
        return route;      
      //is this a folder
      if (S_ISDIR(st.st_mode)) {
        //check if there is controller.rb to run
        char	filename[FILENAME_MAX];
        int len = strlen(path);
        char* slash = path[len-1] == '\\' || path[len-1] == '/' ? "" : "/";
        _shttpd_snprintf(filename,sizeof(filename),"%s%s%s",path,slash,"controller.iseq");

        if ((_shttpd_stat(filename, &st) == 0)&&(!S_ISDIR(st.st_mode))) {
          printf("Run controller on this url: %s\n", c->uri);
          return route;
        }
      }
    }
    _free_route(route);
  }

  return NULL;
}
コード例 #3
0
static void
systray(void *arg)
{
	WNDCLASS	cls;
	HWND		hWnd;
	MSG		msg;

	(void) memset(&cls, 0, sizeof(cls));

	cls.lpfnWndProc = (WNDPROC) WindowProc; 
	cls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	cls.lpszClassName = "shttpd v." VERSION; 

	if (!RegisterClass(&cls)) 
		_shttpd_elog(E_FATAL, NULL, "RegisterClass: %d", ERRNO);
	else if ((hWnd = CreateWindow(cls.lpszClassName, "",
	    WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, NULL, arg)) == NULL)
		_shttpd_elog(E_FATAL, NULL, "CreateWindow: %d", ERRNO);
	ShowWindow(hWnd, SW_HIDE);
	
	ni.cbSize = sizeof(ni);
	ni.uID = ID_TRAYICON;
	ni.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
	ni.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	ni.hWnd = hWnd;
	_shttpd_snprintf(ni.szTip, sizeof(ni.szTip), "SHTTPD web server");
	ni.uCallbackMessage = WM_USER;
	Shell_NotifyIcon(NIM_ADD, &ni);

	while (GetMessage(&msg, hWnd, 0, 0)) { 
		TranslateMessage(&msg); 
		DispatchMessage(&msg); 
	}
}
コード例 #4
0
DIR *
opendir(const char *name)
{
	DIR		*dir = NULL;
	char		path[FILENAME_MAX];
	wchar_t		wpath[FILENAME_MAX];

	if (name == NULL || name[0] == '\0') {
		errno = EINVAL;
	} else if ((dir = malloc(sizeof(*dir))) == NULL) {
		errno = ENOMEM;
	} else {
		_shttpd_snprintf(path, sizeof(path), "%s/*", name);
		fix_directory_separators(path);
		MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, sizeof(wpath));
		dir->handle = FindFirstFileW(wpath, &dir->info);

		if (dir->handle != INVALID_HANDLE_VALUE) {
			dir->result.d_name[0] = '\0';
		} else {
			free(dir);
			dir = NULL;
		}
	}

	return (dir);
}
コード例 #5
0
ファイル: cgi.c プロジェクト: 3runo5ouza/rhodes
int
_shttpd_run_cgi(struct conn *c, const char *prog)
{
	struct env_block	blk;
	char			dir[FILENAME_MAX], *p;
	int			ret, pair[2];

	prepare_environment(c, prog, &blk);
	pair[0] = pair[1] = -1;

	/* CGI must be executed in its own directory */
	(void) _shttpd_snprintf(dir, sizeof(dir), "%s", prog);
	for (p = dir + strlen(dir) - 1; p > dir; p--)
		if (*p == '/') {
			*p++ = '\0';
			break;
		}
	
	if (shttpd_socketpair(pair) != 0) {
		ret = -1;
	} else if (_shttpd_spawn_process(c,
	    prog, blk.buf, blk.vars, pair[1], dir)) {
		ret = -1;
		(void) closesocket(pair[0]);
		(void) closesocket(pair[1]);
	} else {
		ret = 0;
		c->loc.chan.sock = pair[0];
	}

	return (ret);
}
コード例 #6
0
ファイル: rdispatcher.c プロジェクト: jixc2008/rhodes
char* rho_resolve_url(char* url, const char* root,const char *index_names) {
	char path[URI_MAX];
	struct stat	st;
	char* tmp_url;
	char* ret;
	int full_len;

	char* full_path = strstr(url,"http://");
	if (full_path) {
		return full_path;
	}

	if (strlen(url) + strlen(root) >= sizeof(path)) {
		tmp_url = url;
	} else {
		_shttpd_snprintf(path, sizeof(path), "%s%s", root, url);
		if ( _shttpd_stat(path, &st) == -1 ) {
			tmp_url = url;				
		} else if ( S_ISDIR(st.st_mode) ) {
			tmp_url = _rho_resolve_index(url,path,index_names);
		} else {
			tmp_url = url;				
		}
	}
	
#if defined(__SYMBIAN32__) || defined(OS_WINDOWS) || defined(OS_WINCE)	
	full_len = strlen(get_home_url())+strlen(tmp_url)+1;
	ret = malloc(full_len);
	_shttpd_snprintf(ret, full_len, "%s%s", get_home_url(), tmp_url);	
#else		
	full_len = strlen(localhost)+strlen(tmp_url)+1;
	ret = malloc(full_len);
	_shttpd_snprintf(ret, full_len, "%s%s", localhost, tmp_url);	
#endif	

	free(tmp_url);
	
	return ret;
}
コード例 #7
0
ファイル: rdispatcher.c プロジェクト: jixc2008/rhodes
static char* 
_rho_resolve_index(char* url,char* path,const char *index_names) {
	char filename[FILENAME_MAX];
	struct stat	st;

	//check if there is controller.rb
	int len = strlen(path);
	char* slash = path[len-1] == '\\' || path[len-1] == '/' ? "" : "/";
	_shttpd_snprintf(filename,sizeof(filename),"%s%s%s",path,slash,"controller.iseq");
	if ((_shttpd_stat(filename, &st) == 0)&&(!S_ISDIR(st.st_mode))) {
	  return url;
	}
	
	len = strlen(url);
	if (url[len-1]!='/') {
		char* tmp_url = malloc(len+2);
		_shttpd_snprintf(tmp_url,len+2,"%s/",url);
		free(url);
		return tmp_url;
	} 

	return url;				
}
コード例 #8
0
ファイル: log.c プロジェクト: professor/rhodes
void
_shttpd_log_access(FILE *fp, const struct conn *c)
{
    static const struct vec	dash = {"-", 1};

    const struct vec	*user = &c->ch.user._v.v_vec;
    const struct vec	*referer = &c->ch.referer._v.v_vec;
    const struct vec	*user_agent = &c->ch.useragent._v.v_vec;
    char			date[64], buf[URI_MAX], *q1 = "\"", *q2 = "\"";

    if (user->len == 0)
        user = ‐

    if (referer->len == 0) {
        referer = ‐
        q1 = "";
    }

    if (user_agent->len == 0) {
        user_agent = ‐
        q2 = "";
    }

    (void) strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S",
                    localtime(&c->birth_time));

    (void) _shttpd_snprintf(buf, sizeof(buf),
                            "%s - %.*s [%s %+05d] \"%s\" %d %lu %s%.*s%s %s%.*s%s",
                            inet_ntoa(c->sa.u.sin.sin_addr), user->len, user->ptr,
                            date, _shttpd_tz_offset, c->request ? c->request : "-",
                            c->status, (unsigned long) c->loc.io.total,
                            q1, referer->len, referer->ptr, q1,
                            q2, user_agent->len, user_agent->ptr, q2);

    if (fp != NULL) {
        (void) fprintf(fp, "%s\n", buf);
        (void) fflush(fp);
    }
}
コード例 #9
0
ファイル: log.c プロジェクト: professor/rhodes
/*
 * Log function
 */
void
_shttpd_elog(int flags, struct conn *c, const char *fmt, ...)
{
    char	date[64], buf[URI_MAX];
    int	len;
    FILE	*fp = c == NULL ? NULL : c->ctx->error_log;
    va_list	ap;

    /* Print to stderr */
    if (c == NULL || !IS_TRUE(c->ctx, OPT_INETD)) {
        va_start(ap, fmt);
        (void) vfprintf(stderr, fmt, ap);
        (void) fputc('\n', stderr);
        va_end(ap);
    }

    strftime(date, sizeof(date), "%a %b %d %H:%M:%S %Y",
             localtime(&_shttpd_current_time));

    len = _shttpd_snprintf(buf, sizeof(buf),
                           "[%s] [error] [client %s] \"%s\" ",
                           date, c ? inet_ntoa(c->sa.u.sin.sin_addr) : "-",
                           c && c->request ? c->request : "-");

    va_start(ap, fmt);
    (void) vsnprintf(buf + len, sizeof(buf) - len, fmt, ap);
    va_end(ap);

    buf[sizeof(buf) - 1] = '\0';

    if (fp != NULL && (flags & (E_FATAL | E_LOG))) {
        (void) fprintf(fp, "%s\n", buf);
        (void) fflush(fp);
    }

    if (flags & E_FATAL)
        exit(EXIT_FAILURE);
}
コード例 #10
0
ファイル: rdispatcher.c プロジェクト: jixc2008/rhodes
void* rho_dispatch(struct conn *c, const char* path) {
  RouteRef route;
  
  if ( _shttpd_match_extension(c->uri,"css,js,html,htm,png,bmp,jpg") )
    return NULL;

#ifdef __SYMBIAN32__
  if ( strstr(_shttpd_known_http_methods[c->method].ptr, "GET" ) )
	  webview_set_current_location(c->uri);
#endif
  
  if ((route = _alloc_route(c->uri)) != NULL) {
    if (_parse_route(route)) {
      struct stat	st;
      //is this an actual file or folder
      if (_shttpd_stat(path, &st) != 0)
        return route;      
      //is this a folder
      if (S_ISDIR(st.st_mode)) {
        //check if there is controller.rb to run
        char	filename[FILENAME_MAX];
        int len = strlen(path);
        char* slash = path[len-1] == '\\' || path[len-1] == '/' ? "" : "/";
        _shttpd_snprintf(filename,sizeof(filename),"%s%s%s",path,slash,"controller.iseq");

        if ((_shttpd_stat(filename, &st) == 0)&&(!S_ISDIR(st.st_mode))) {
          RAWLOG_INFO1("Run controller on this url: %s", c->uri);
          return route;
        }
      }
    }
    _free_route(route);
  }

  return NULL;
}
コード例 #11
0
ファイル: io_file.c プロジェクト: 3runo5ouza/rhodes
static int
write_file(struct stream *stream, const void *buf, size_t len)
{
	struct stat	st;
	struct stream	*rem = &stream->conn->rem;
	int		n, fd = stream->chan.fd;

	assert(fd != -1);
	n = write(fd, buf, len);

	DBG(("put_file(%p, %d): %d bytes", (void *) stream, (int) len, n));

	if (n <= 0 || (rem->io.total >= (big_int_t) rem->content_len)) {
		(void) fstat(fd, &st);
		stream->io.head = stream->headers_len =
		    _shttpd_snprintf(stream->io.buf,
		    stream->io.size, "HTTP/1.1 %d OK\r\n"
		    "Content-Length: %lu\r\nConnection: close\r\n\r\n",
		    stream->conn->status, st.st_size);
		_shttpd_stop_stream(stream);
	}

	return (n);
}
コード例 #12
0
ファイル: io_cgi.c プロジェクト: 3runo5ouza/rhodes
static int
read_cgi(struct stream *stream, void *buf, size_t len)
{
	struct headers	parsed;
	char		status[4];
	int		n;

	assert(stream->chan.sock != -1);
	assert(stream->flags & FLAG_R);

	stream->flags &= ~FLAG_DONT_CLOSE;

	n = recv(stream->chan.sock, buf, len, 0);

	if (stream->flags & FLAG_HEADERS_PARSED)
		return (n);

	if (n <= 0 && ERRNO != EWOULDBLOCK) {
		_shttpd_send_server_error(stream->conn, 500,
		    "Error running CGI");
		return (n);
	}

	/*
	 * CGI script may output Status: and Location: headers, which
	 * may alter the status code. Buffer in headers, parse
	 * them, send correct status code and then forward all data
	 * from CGI script back to the remote end.
	 * Reply line was alredy appended to the IO buffer in
	 * decide_what_to_do(), with blank status code.
	 */

	stream->flags |= FLAG_DONT_CLOSE;
	io_inc_head(&stream->io, n);

	stream->headers_len = _shttpd_get_headers_len(stream->io.buf,
	    stream->io.head);
	if (stream->headers_len < 0) {
		stream->flags &= ~FLAG_DONT_CLOSE;
		_shttpd_send_server_error(stream->conn, 500,
		    "Bad headers sent");
		_shttpd_elog(E_LOG, stream->conn,
		    "CGI script sent invalid headers: "
		    "[%.*s]", stream->io.head - CGI_REPLY_LEN,
		    stream->io.buf + CGI_REPLY_LEN);
		return (0);
	}

	/*
	 * If we did not received full headers yet, we must not send any
	 * data read from the CGI back to the client. Suspend sending by
	 * setting tail = head, which tells that there is no data in IO buffer
	 */

	if (stream->headers_len == 0) {
		stream->io.tail = stream->io.head;
		return (0);
	}

	/* Received all headers. Set status code for the connection. */
	(void) memset(&parsed, 0, sizeof(parsed));
	_shttpd_parse_headers(stream->io.buf, stream->headers_len, &parsed);
	stream->content_len = parsed.cl.v_big_int;
	stream->conn->status = (int) parsed.status.v_big_int;

	/* If script outputs 'Location:' header, set status code to 302 */
	if (parsed.location.v_vec.len > 0)
		stream->conn->status = 302;

	/*
	 * If script did not output neither 'Location:' nor 'Status' headers,
	 * set the default status code 200, which means 'success'.
	 */
	if (stream->conn->status == 0)
		stream->conn->status = 200;

	/* Append the status line to the beginning of the output */
	(void) _shttpd_snprintf(status,
	    sizeof(status), "%3d", stream->conn->status);
	(void) memcpy(stream->io.buf + 9, status, 3);
	DBG(("read_cgi: content len %lu status %s",
	    stream->content_len, status));

	/* Next time, pass output directly back to the client */
	assert((big_int_t) stream->headers_len <= stream->io.total);
	stream->io.total -= stream->headers_len;
	stream->io.tail = 0;
	stream->flags |= FLAG_HEADERS_PARSED;

	/* Return 0 because we've already shifted the head */
	return (0);
}
コード例 #13
0
int
_shttpd_spawn_process(struct conn *c, const char *prog, char *envblk,
		char *envp[], int sock, const char *dir)
{
	HANDLE	a[2], b[2], h[2], me;
	DWORD	flags;
	char	*p, *interp, cmdline[FILENAME_MAX], line[FILENAME_MAX];
	FILE	*fp;
	STARTUPINFOA		si;
	PROCESS_INFORMATION	pi;

	me = GetCurrentProcess();
	flags = DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS;

	/* FIXME add error checking code here */
	CreatePipe(&a[0], &a[1], NULL, 0);
	CreatePipe(&b[0], &b[1], NULL, 0);
	DuplicateHandle(me, a[0], me, &h[0], 0, TRUE, flags);
	DuplicateHandle(me, b[1], me, &h[1], 0, TRUE, flags);
	
	(void) memset(&si, 0, sizeof(si));
	(void) memset(&pi, 0, sizeof(pi));

	/* XXX redirect CGI errors to the error log file */
	si.cb		= sizeof(si);
	si.dwFlags	= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
	si.wShowWindow	= SW_HIDE;
	si.hStdOutput	= h[1];
	si.hStdInput	= h[0];

	/* If CGI file is a script, try to read the interpreter line */
	interp = c->ctx->options[OPT_CGI_INTERPRETER];
	if (interp == NULL) {
		if ((fp = fopen(prog, "r")) != NULL) {
			(void) fgets(line, sizeof(line), fp);
			if (memcmp(line, "#!", 2) != 0)
				line[2] = '\0';
			/* Trim whitespaces from interpreter name */
			for (p = &line[strlen(line) - 1]; p > line &&
			    isspace(*p); p--)
				*p = '\0';
			(void) fclose(fp);
		}
		interp = line + 2;
		(void) _shttpd_snprintf(cmdline, sizeof(cmdline), "%s%s%s",
		    line + 2, line[2] == '\0' ? "" : " ", prog);
	}

	if ((p = strrchr(prog, '/')) != NULL)
		prog = p + 1;

	(void) _shttpd_snprintf(cmdline, sizeof(cmdline), "%s %s", interp, prog);

	(void) _shttpd_snprintf(line, sizeof(line), "%s", dir);
	fix_directory_separators(line);
	fix_directory_separators(cmdline);

	/*
	 * Spawn reader & writer threads before we create CGI process.
	 * Otherwise CGI process may die too quickly, loosing the data
	 */
	spawn_stdio_thread(sock, b[0], stdinput, 0);
	spawn_stdio_thread(sock, a[1], stdoutput, c->rem.content_len);

	if (CreateProcessA(NULL, cmdline, NULL, NULL, TRUE,
	    CREATE_NEW_PROCESS_GROUP, envblk, line, &si, &pi) == 0) {
		_shttpd_elog(E_LOG, c,
		    "redirect: CreateProcess(%s): %d", cmdline, ERRNO);
		return (-1);
	} else {
		CloseHandle(h[0]);
		CloseHandle(h[1]);
		CloseHandle(pi.hThread);
		CloseHandle(pi.hProcess);
	}

	return (0);
}