Exemple #1
0
void extended_html__block_body(onion_dict *context, onion_response *res){
#line 1
#line 8
  onion_response_write(res, "\n<h1>This is an extended template</h1>\n\n", 40);
#line 8
  {
#line 8
    void (*f)(onion_dict *context, onion_response *res);
#line 8
    f=(void*)onion_dict_get(context, "__block_body_in__");
#line 8
    if (f)
#line 8
      f(context, res);
#line 8
  }
#line 14
  onion_response_write(res, "\n\nIf you see this, <span style=\"color: green;\">OK</span>.\n<br>\nRandom (only at test2): ", 87);
#line 14
  {
#line 14
    const char *tmp;
#line 14
    tmp=onion_dict_get(context, "random");
#line 14
    if (tmp)
#line 14
      onion_response_write0(res, tmp);
#line 14
  }
#line 19
  onion_response_write(res, "\n<br>\n\nUnicode Chars: \342\202\254 \302\241 \303\241 \303\251 \303\255 \303\272 \303\263. \346\261\211\350\257\255/\346\274\242\350\252\236.\n\n", 61);
#line 1
}
Exemple #2
0
/// Gets the output data
int oterm_out(process *o, onion_request *req, onion_response *res){
	pthread_mutex_lock(&o->mutex);
	if (onion_request_get_query(req, "initial")){
		if (o->buffer[BUFFER_SIZE-1]!=0){ // If 0 then never wrote on it. So if not, write from pos to end too, first.
			onion_response_write(res, &o->buffer[o->buffer_pos], BUFFER_SIZE-o->buffer_pos);
		}
		onion_response_write(res, o->buffer, o->buffer_pos);
		onion_response_printf(res, "\033]oterm;%d;", o->buffer_pos);
    onion_response_printf(res, "\033]url;https://localhost:8080/uuid/%s/;", o->uuid);
		pthread_mutex_unlock(&o->mutex);
		return OCS_PROCESSED;
	}
	
	int16_t p=atoi(onion_request_get_queryd(req, "pos", "0")); //o->buffer_pos;
	ONION_DEBUG("Wait for data at %d", p);
	while(p==o->buffer_pos) // We need it to be diferent, if not does not make sense to wake up
		pthread_cond_wait(&o->dataReady, &o->mutex);
	ONION_DEBUG("Data ready at %d (waiting from %d)", o->buffer_pos, p);
	if (o->buffer_pos<p){
		onion_response_write(res, &o->buffer[p], BUFFER_SIZE-p);
		p=0;
	}
	onion_response_write(res, &o->buffer[p], o->buffer_pos-p);
	onion_response_printf(res, "\033]oterm;%d;", o->buffer_pos);
	pthread_mutex_unlock(&o->mutex);
	return OCS_PROCESSED;
}
Exemple #3
0
/*
 Return raw file if found. Security risk?! Check of filename/path required?!
*/
int search_file(onion_dict *context, onion_request *req, onion_response *res){
	//const char* path = onion_request_get_path(req);//empty?!
	const char* path = onion_request_get_fullpath(req);
	printf("Request of %s %i.\n",path, strlen(path));
	char filename[strlen(path)+8];
	//sprintf(filename,"./%s",path);
	sprintf(filename,"./html/%s",path);

		//read file 
	if( FILE *f=fopen(filename,"rb") ){
		fseek(f,0,SEEK_END);
		long len=ftell(f);
		fseek(f,0,SEEK_SET);
		char *data=(char*)malloc(len+1);
		fread(data,1,len,f);
		fclose(f);

		if (context) onion_dict_add(context, "LANG", onion_request_get_language_code(req), OD_FREE_VALUE);
		onion_response_set_length(res, len);
		onion_response_write(res, data, len); 
		if (context) onion_dict_free(context);

		free(data);
	}else{
		onion_response_set_length(res, 24);
		onion_response_write(res, "<h1>File not found</h1>", 24); 
	}
	return OCS_PROCESSED;
}
Exemple #4
0
/**
 * @short Writes all the header to the given response
 * @memberof onion_response_t
 * @ingroup response
 *
 * It writes the headers and depending on the method, return OR_SKIP_CONTENT. this is set when in head mode. Handlers
 * should react to this return by not trying to write more, but if they try this object will just skip those writtings.
 *
 * Explicit calling to this function is not necessary, as as soon as the user calls any write function this will
 * be performed.
 *
 * As soon as the headers are written, any modification on them will be just ignored.
 *
 * @returns 0 if should procced to normal data write, or OR_SKIP_CONTENT if should not write content.
 */
int onion_response_write_headers(onion_response * res) {
  if (!res->request) {
    ONION_ERROR
        ("Bad formed response. Need a request at creation. Will not write headers.");
    return -1;
  }

  res->flags |= OR_HEADER_SENT; // I Set at the begining so I can do normal writing.
  res->request->flags |= OR_HEADER_SENT;
  char chunked = 0;

  if (res->request->flags & OR_HTTP11) {
    onion_response_printf(res, "HTTP/1.1 %d %s\r\n", res->code,
                          onion_response_code_description(res->code));
    //ONION_DEBUG("Response header: HTTP/1.1 %d %s\n",res->code, onion_response_code_description(res->code));
    if (!(res->flags & OR_LENGTH_SET) && onion_request_keep_alive(res->request)) {
      onion_response_write(res, CONNECTION_CHUNK_ENCODING,
                           sizeof(CONNECTION_CHUNK_ENCODING) - 1);
      chunked = 1;
    }
  } else {
    onion_response_printf(res, "HTTP/1.0 %d %s\r\n", res->code,
                          onion_response_code_description(res->code));
    //ONION_DEBUG("Response header: HTTP/1.0 %d %s\n",res->code, onion_response_code_description(res->code));
    if (res->flags & OR_LENGTH_SET)     // On HTTP/1.0, i need to state it. On 1.1 it is default.
      onion_response_write(res, CONNECTION_KEEP_ALIVE,
                           sizeof(CONNECTION_KEEP_ALIVE) - 1);
  }

  if (!(res->flags & OR_LENGTH_SET) && !chunked
      && !(res->flags & OR_CONNECTION_UPGRADE))
    onion_response_write(res, CONNECTION_CLOSE, sizeof(CONNECTION_CLOSE) - 1);

  if (res->flags & OR_CONNECTION_UPGRADE)
    onion_response_write(res, CONNECTION_UPGRADE,
                         sizeof(CONNECTION_UPGRADE) - 1);

  onion_dict_preorder(res->headers, write_header, res);

  if (res->request->session_id && (onion_dict_count(res->request->session) > 0))        // I have session with something, tell user
    onion_response_printf(res, "Set-Cookie: sessionid=%s; httponly; Path=/\n",
                          res->request->session_id);

  onion_response_write(res, "\r\n", 2);

  ONION_DEBUG0("Headers written");
  res->sent_bytes = -res->buffer_pos;   // the header size is not counted here. It will add again so start negative.

  if ((res->request->flags & OR_METHODS) == OR_HEAD) {
    onion_response_flush(res);
    res->flags |= OR_SKIP_CONTENT;
    return OR_SKIP_CONTENT;
  }
  if (chunked) {
    onion_response_flush(res);
    res->flags |= OR_CHUNKED;
  }

  return 0;
}
Exemple #5
0
/**
 * @short Writes some data to the response. Using sprintf format strings. va_list args version
 *
 * @param args va_list of arguments
 * @memberof onion_response_t
 */
ssize_t onion_response_vprintf(onion_response *res, const char *fmt, va_list args)
{
	char temp[512];
	int l;
	l=vsnprintf(temp, sizeof(temp), fmt, args);
	if (l<0) {
		ONION_ERROR("Invalid vprintf fmt");
		return -1;
	}
	else if (l<sizeof(temp)) {
		return onion_response_write(res, temp, l);
	}
	else {
		ssize_t s;
		char*buf = onion_low_scalar_malloc(l+1);
		if (!buf){
		  // this cannot happen, since onion_low_scalar_malloc
		  // handles that error...
			ONION_ERROR("Could not reserve %d bytes", l+1);
			return -1;
		}
		vsnprintf(buf, l, fmt, args);
		s = onion_response_write (res, buf, l);
		onion_low_free (buf);
		return s;
	}
}
Exemple #6
0
/**
 * @short Helper that is called on each header, and writes the header
 * @memberof onion_response_t
 */
static void write_header(onion_response *res, const char *key, const char *value, int flags){
	//ONION_DEBUG0("Response header: %s: %s",key, value);

	onion_response_write0(res, key);
	onion_response_write(res, ": ",2);
	onion_response_write0(res, value);
	onion_response_write(res, "\r\n",2);
}
Exemple #7
0
/*
 Check post values and then return template of index.html.
 (Or use *p for other callbacks (not implemented))
*/
int checkFormularValues(void *p, onion_request *req, onion_response *res){
	int ok = ((OnionServer*)p)->updateSetting(req,res);
	if( ok != 0){
		onion_response_set_length(res, 6);
		onion_response_write(res, "reload", 6); 
	}else{
		onion_response_set_length(res, 2);
		onion_response_write(res, "Ok", 2); 
	}
	return OCS_PROCESSED;
}
void base_html(onion_dict *context, onion_response *res){
#line 1
#line 1
  int has_context=(context!=NULL);
#line 1
  if (!has_context)
#line 1
    context=onion_dict_new();
#line 1
  
#line 1
  base_html_blocks_init(context);
  onion_response_write(res, "<!DOCTYPE html>\n"
      "<html>\n"
      "  <head>\n"
      "    <title>", 43);
#line 4
  {
#line 4
    const char *tmp;
#line 4
    tmp=onion_dict_get(context, "title");
#line 4
    if (tmp)
#line 4
      onion_response_write_html_safe(res, tmp);
#line 4
  }
  onion_response_write(res, "</title>\n"
      "  </head>\n"
      "  <body>\n"
      "", 28);
#line 7
  {
#line 7
    void (*f)(onion_dict *context, onion_response *res);
#line 7
    f=(void*)onion_dict_get(context, "__block_content__");
#line 7
    if (f)
#line 7
      f(context, res);
#line 7
  }
  onion_response_write(res, "  \n"
      "  </body>\n"
      "</html>\n"
      "", 21);
#line 10
  if (!has_context)
#line 10
    onion_dict_free(context);
#line 1
}
Exemple #9
0
/**
 * @short Writes some data to the response. Using sprintf format strings. Max final string size: 1024
 * @memberof onion_response_t
 */
ssize_t onion_response_printf(onion_response *res, const char *fmt, ...){
	char temp[1024];
	va_list ap;
	va_start(ap, fmt);
	int l=vsnprintf(temp, sizeof(temp)-1, fmt, ap);
	va_end(ap);
	return onion_response_write(res, temp, l);
}
Exemple #10
0
onion_connection_status wait_random(void *_, onion_request *req, onion_response *res){
  int ms=105.0 + (float)((200.0 * rand()) / ((float)RAND_MAX));
  ONION_INFO("Wait %.3f seconds", ms/1000.0);
  usleep(ms*1000);

  onion_response_write(res, "OK", 3);

  return OCS_PROCESSED;
}
Exemple #11
0
onion_connection_status random_timeout(void *_, onion_request * req,
                                       onion_response * res) {
  int ms = 2000 * (((float)RAND_MAX) / rand());
  ONION_INFO("Wait %d ms", ms);
  usleep(ms * 1000);
  ONION_INFO("Done");
  onion_response_write(res, "OK", 2);
  return OCS_PROCESSED;
}
Exemple #12
0
/**
 * @short Writes all buffered output waiting for sending.
 * @ingroup response
 *
 * If header has not been sent yet (delayed), it uses a temporary buffer to send it now. This
 * way header can use the buffer_size information to send the proper content-length, even when it
 * wasnt properly set by programmer. Whith this information its possib to keep alive the connection
 * on more cases.
 */
int onion_response_flush(onion_response * res) {
  res->sent_bytes += res->buffer_pos;
  res->sent_bytes_total += res->buffer_pos;
  if (res->buffer_pos == 0)     // Not used.
    return 0;
  if (!(res->flags & OR_HEADER_SENT)) { // Automatic header write
    ONION_DEBUG0
        ("Doing fast header hack: store current buffer, send current headers. Resend buffer.");
    char tmpb[sizeof(res->buffer)];
    int tmpp = res->buffer_pos;
    memcpy(tmpb, res->buffer, res->buffer_pos);
    res->buffer_pos = 0;

    onion_response_write_headers(res);
    onion_response_write(res, tmpb, tmpp);
    return 0;
  }
  if (res->flags & OR_SKIP_CONTENT)     // HEAD request
    return 0;
  ONION_DEBUG0("Flush %d bytes", res->buffer_pos);

  onion_request *req = res->request;
  ssize_t(*write) (onion_request *, const char *data, size_t len);
  write = req->connection.listen_point->write;

  ssize_t w;
  off_t pos = 0;
  //ONION_DEBUG0("Write %d bytes",res->buffer_pos);
  if (res->flags & OR_CHUNKED) {
    char tmp[16];
    snprintf(tmp, sizeof(tmp), "%X\r\n", (unsigned int)res->buffer_pos);
    if ((w = write(req, tmp, strlen(tmp))) <= 0) {
      ONION_WARNING("Error writing chunk encoding length. Aborting write.");
      return OCS_CLOSE_CONNECTION;
    }
    ONION_DEBUG0("Write %d-%d bytes", res->buffer_pos, w);
  }
  while ((w =
          write(req, &res->buffer[pos], res->buffer_pos)) != res->buffer_pos) {
    if (w <= 0 || res->buffer_pos < 0) {
      ONION_ERROR("Error writing %d bytes. Maybe closed connection. Code %d. ",
                  res->buffer_pos, w);
      perror("");
      res->buffer_pos = 0;
      return OCS_CLOSE_CONNECTION;
    }
    pos += w;
    ONION_DEBUG0("Write %d-%d bytes", res->buffer_pos, w);
    res->buffer_pos -= w;
  }
  if (res->flags & OR_CHUNKED) {
    write(req, "\r\n", 2);
  }
  res->buffer_pos = 0;
  return 0;
}
Exemple #13
0
int php_sapi_ponion_ub_write(const char *message, unsigned int length TSRMLS_DC) /* {{{ */
{
	ponion_context_t *context = (ponion_context_t*) SG(server_context);
	if (context) {
		if (onion_response_write(context->res, message, length))
			return SUCCESS;	
	}
	
	return FAILURE;
} /* }}} */
Exemple #14
0
/**
 * @short Performs the real request: set the code and write data
 */
int onion_handler_static_handler(onion_handler_static_data *d, onion_request *request, onion_response *res){
	int length=strlen(d->data);
	onion_response_set_length(res, length);
	onion_response_set_code(res, d->code);
	
	onion_response_write_headers(res);
	//fprintf(stderr,"Write %d bytes\n",length);
	onion_response_write(res, d->data, length);

	return OCS_PROCESSED;
}
Exemple #15
0
int onion_handler_auth_pam_handler(onion_handler_auth_pam_data *d, onion_request *request, onion_response *res){
	/// Use session to know if already logged in, so do not mess with PAM so often.
	if (onion_request_get_session(request, "pam_logged_in"))
		return onion_handler_handle(d->inside, request, res);
	
	const char *o=onion_request_get_header(request, "Authorization");
	char *auth=NULL;
	char *username=NULL;
	char *passwd=NULL;
	if (o && strncmp(o,"Basic",5)==0){
		//fprintf(stderr,"auth: '%s'\n",&o[6]);
		auth=onion_base64_decode(&o[6], NULL);
		username=auth;
		int i=0;
		while (auth[i]!='\0' && auth[i]!=':') i++;
		if (auth[i]==':'){
			auth[i]='\0'; // so i have user ready
			passwd=&auth[i+1];
		}
		else
			passwd=NULL;
	}
	
	// I have my data, try to authorize
	if (username && passwd){
		int ok=authorize(d->pamname, username, passwd);
		
		if (ok){ // I save the username at the session, so it can be accessed later.
			onion_dict *session=onion_request_get_session_dict(request);
			onion_dict_lock_write(session);
			onion_dict_add(session, "username", username, OD_REPLACE|OD_DUP_VALUE);
			onion_dict_add(session, "pam_logged_in", username, OD_REPLACE|OD_DUP_VALUE);
			onion_dict_unlock(session);
			
			free(auth);
			return onion_handler_handle(d->inside, request, res);
		}
	}
	if (auth)
		free(auth);

	
	// Not authorized. Ask for it.
	char temp[256];
	sprintf(temp, "Basic realm=\"%s\"",d->realm);
	onion_response_set_header(res, "WWW-Authenticate",temp);
	onion_response_set_code(res, HTTP_UNAUTHORIZED);
	onion_response_set_length(res,sizeof(RESPONSE_UNAUTHORIZED));
	
	onion_response_write(res,RESPONSE_UNAUTHORIZED,sizeof(RESPONSE_UNAUTHORIZED));
	return OCS_PROCESSED;
}
Exemple #16
0
/**
 * @short Handles a propfind
 * 
 * @param path the shared path.
 */
onion_connection_status onion_webdav_propfind(const char *filename, onion_webdav *wd, onion_request* req, onion_response* res){
	// Prepare the basepath, necesary for props.
	char *basepath=NULL;
	int pathlen=0;
	const char *current_path=onion_request_get_path(req);
	const char *fullpath=onion_request_get_fullpath(req);
	pathlen=(current_path-fullpath);
	basepath=alloca(pathlen+1);
	memcpy(basepath, fullpath, pathlen+1);
	ONION_DEBUG0("Pathbase initial <%s> %d", basepath, pathlen); 
	while(basepath[pathlen]=='/' && pathlen>0)
		pathlen--;
	basepath[pathlen+1]=0;
				 
	ONION_DEBUG0("PROPFIND; pathbase %s", basepath);
	int depth;
	{
		const char *depths=onion_request_get_header(req, "Depth");
		if (!depths){
			ONION_ERROR("Missing Depth header on webdav request");
			return OCS_INTERNAL_ERROR;
		}
		if (strcmp(depths,"infinity")==0){
			ONION_ERROR("Infinity depth not supported yet.");
			return OCS_INTERNAL_ERROR;
		}
		depth=atoi(depths);
	}

	int props=onion_webdav_parse_propfind(onion_request_get_data(req));
	ONION_DEBUG("Asking for props %08X, depth %d", props, depth);
	
	onion_block *block=onion_webdav_write_propfind(basepath, filename, onion_request_get_path(req), depth, props);
	
	if (!block) // No block, resource does not exist
		return onion_shortcut_response("Not found", HTTP_NOT_FOUND, req, res);
		
	ONION_DEBUG0("Printing block %s", onion_block_data(block));
	
	onion_response_set_header(res, "Content-Type", "text/xml; charset=\"utf-8\"");
	onion_response_set_length(res, onion_block_size(block));
	onion_response_set_code(res, HTTP_MULTI_STATUS);
	onion_response_write_headers(res);
	onion_response_flush(res);
	
	onion_response_write(res, onion_block_data(block), onion_block_size(block));
	
	onion_block_free(block);
	
	return OCS_PROCESSED;
}
Exemple #17
0
void external_html(onion_dict *context, onion_response *res){
#line 1
#line 1
  int has_context=(context!=NULL);
#line 1
  if (!has_context)
#line 1
    context=onion_dict_new();
#line 1
  
#line 1
  external_html_blocks_init(context);
#line 2
  onion_response_write(res, "This code is in an external html.\n", 34);
#line 2
  if (!has_context)
#line 2
    onion_dict_free(context);
#line 1
}
Exemple #18
0
/**
 * @short Shortcut for fast responses, like errors, with extra headers
 * 
 * Prepares a fast response. You pass only the request, the text and the code, and it do the full response
 * object and sends the data.
 * 
 * On this version you also pass a NULL terminated list of headers, in key, value pairs.
 */
onion_connection_status onion_shortcut_response_extra_headers(const char* response, int code, onion_request* req, onion_response *res, ... ){
	unsigned int l=strlen(response);
	const char *key, *value;
	
	onion_response_set_length(res,l);
	onion_response_set_code(res,code);
	
	va_list ap;
	va_start(ap, res);
	while ( (key=va_arg(ap, const char *)) ){
		value=va_arg(ap, const char *);
		if (key && value)
			onion_response_set_header(res, key, value);
		else
			break;
	}
	va_end(ap);

	onion_response_write_headers(res);
	
	onion_response_write(res,response,l);
	return OCS_PROCESSED;
}
Exemple #19
0
/**
 * @short Handles a propfind
 * 
 * @param path the shared path.
 */
onion_connection_status onion_webdav_propfind(const char *filename, onion_webdav *wd, onion_request* req, onion_response* res){
	ONION_DEBUG0("PROPFIND");
	int depth;
	{
		const char *depths=onion_request_get_header(req, "Depth");
		if (!depths){
			ONION_ERROR("Missing Depth header on webdav request");
			return OCS_INTERNAL_ERROR;
		}
		if (strcmp(depths,"infinity")==0){
			ONION_ERROR("Infinity depth not supported yet.");
			return OCS_INTERNAL_ERROR;
		}
		depth=atoi(depths);
	}

	int props=onion_webdav_parse_propfind(onion_request_get_data(req));
	ONION_DEBUG("Asking for props %08X, depth %d", props, depth);
	
	onion_block *block=onion_webdav_write_propfind(filename, onion_request_get_path(req), depth, props);
	
	if (!block) // No block, resource does not exist
		return onion_shortcut_response("Not found", HTTP_NOT_FOUND, req, res);
		
	ONION_DEBUG0("Printing block %s", onion_block_data(block));
	
	onion_response_set_header(res, "Content-Type", "text/xml; charset=\"utf-8\"");
	onion_response_set_length(res, onion_block_size(block));
	onion_response_set_code(res, HTTP_MULTI_STATUS);
	
	onion_response_write(res, onion_block_data(block), onion_block_size(block));
	
	onion_block_free(block);
	
	return OCS_PROCESSED;
}
Exemple #20
0
/**
 * @short Default error printer. 
 * @memberof onion_server_t
 * 
 * Ugly errors, that can be reimplemented setting a handler with onion_server_set_internal_error_handler.
 */
static int onion_default_error(void *handler, onion_request *req, onion_response *res){
	const char *msg;
	int l;
	int code;
	switch(req->flags&0x0F000){
		case OR_INTERNAL_ERROR:
			msg=ERROR_500;
			l=sizeof(ERROR_500)-1;
			code=HTTP_INTERNAL_ERROR;
			break;
		case OR_NOT_IMPLEMENTED:
			msg=ERROR_505;
			l=sizeof(ERROR_505)-1;
			code=HTTP_NOT_IMPLEMENTED;
			break;
    case OR_FORBIDDEN:
      msg=ERROR_403;
      l=sizeof(ERROR_403)-1;
      code=HTTP_FORBIDDEN;
      break;
		default:
			msg=ERROR_404;
			l=sizeof(ERROR_404)-1;
			code=HTTP_NOT_FOUND;
			break;
	}
	
	ONION_DEBUG0("Internally managed error: %s, code %d.", msg, code);
	
	onion_response_set_code(res,code);
	onion_response_set_length(res, l);
	onion_response_write_headers(res);
	
	onion_response_write(res,msg,l);
	return OCS_PROCESSED;
}
Exemple #21
0
 int write(const char *data, int len){
   return onion_response_write(ptr, data, len);
 }
Exemple #22
0
/// Writes a 0-ended string to the response.
ssize_t onion_response_write0(onion_response *res, const char *data){
	return onion_response_write(res, data, strlen(data));
}
Exemple #23
0
void extended_html__block_body_in(onion_dict *context, onion_response *res){
#line 1
#line 10
  onion_response_write(res, "\nMore text.\n", 12);
#line 1
}
Exemple #24
0
onion_connection_status opack_index_html(void *_, onion_request *req, onion_response *res){
  char data[]={
0x3C, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0A, 0x20, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x3E, 
0x0A, 0x20, 0x20, 0x3C, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x3E, 0x4F, 0x6E, 0x69, 0x6F, 0x6E, 0x20, 
0x54, 0x6F, 0x70, 0x3C, 0x2F, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x20, 0x3C, 0x73, 
0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x73, 0x72, 0x63, 0x3D, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3A, 
0x2F, 0x2F, 0x63, 0x6F, 0x64, 0x65, 0x2E, 0x6A, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2E, 0x63, 0x6F, 
0x6D, 0x2F, 0x6A, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2D, 0x31, 0x2E, 0x34, 0x2E, 0x33, 0x2E, 0x6D, 
0x69, 0x6E, 0x2E, 0x6A, 0x73, 0x22, 0x3E, 0x3C, 0x2F, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 
0x0A, 0x3C, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x3E, 0x0A, 0x62, 0x6F, 0x64, 0x79, 0x7B, 0x0A, 0x09, 
0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 0x20, 0x23, 0x66, 0x65, 0x66, 
0x65, 0x66, 0x65, 0x3B, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x66, 0x61, 0x6D, 0x69, 0x6C, 
0x79, 0x3A, 0x20, 0x73, 0x61, 0x6E, 0x73, 0x2D, 0x73, 0x65, 0x72, 0x69, 0x66, 0x3B, 0x0A, 0x7D, 
0x0A, 0x0A, 0x68, 0x31, 0x7B, 0x0A, 0x09, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20, 0x62, 0x6C, 
0x61, 0x63, 0x6B, 0x3B, 0x0A, 0x09, 0x74, 0x65, 0x78, 0x74, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 
0x3A, 0x20, 0x63, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x3B, 0x0A, 0x7D, 0x0A, 0x0A, 0x23, 0x70, 0x72, 
0x6F, 0x63, 0x65, 0x73, 0x73, 0x7B, 0x0A, 0x09, 0x6F, 0x76, 0x65, 0x72, 0x66, 0x6C, 0x6F, 0x77, 
0x3A, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6E, 0x3B, 0x0A, 0x7D, 0x0A, 0x0A, 0x74, 0x61, 0x62, 
0x6C, 0x65, 0x7B, 0x0A, 0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 
0x3B, 0x0A, 0x09, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 0x20, 0x31, 0x70, 0x78, 0x20, 0x73, 
0x6F, 0x6C, 0x69, 0x64, 0x20, 0x23, 0x61, 0x61, 0x61, 0x3B, 0x20, 0x0A, 0x09, 0x62, 0x61, 0x63, 
0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x3B, 0x0A, 
0x09, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 
0x35, 0x70, 0x78, 0x3B, 0x0A, 0x09, 0x2D, 0x6D, 0x6F, 0x7A, 0x2D, 0x62, 0x6F, 0x72, 0x64, 0x65, 
0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B, 0x0A, 0x7D, 
0x0A, 0x0A, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x74, 0x68, 0x7B, 0x0A, 0x09, 0x62, 0x61, 0x63, 
0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 0x20, 0x23, 0x65, 0x65, 0x65, 0x3B, 0x0A, 0x7D, 
0x0A, 0x0A, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x74, 0x68, 0x2C, 0x20, 0x74, 0x61, 0x62, 0x6C, 
0x65, 0x20, 0x74, 0x64, 0x7B, 0x0A, 0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x31, 0x30, 
0x65, 0x6D, 0x3B, 0x0A, 0x7D, 0x0A, 0x0A, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x2E, 0x75, 0x69, 
0x64, 0x7B, 0x0A, 0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x31, 0x35, 0x65, 0x6D, 0x3B, 
0x0A, 0x7D, 0x0A, 0x0A, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x74, 0x68, 0x65, 0x61, 0x64, 0x7B, 
0x0A, 0x09, 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 
0x3B, 0x0A, 0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0A, 
0x7D, 0x0A, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x74, 0x62, 0x6F, 0x64, 0x79, 0x7B, 0x0A, 0x09, 
0x6F, 0x76, 0x65, 0x72, 0x66, 0x6C, 0x6F, 0x77, 0x3A, 0x20, 0x61, 0x75, 0x74, 0x6F, 0x3B, 0x0A, 
0x09, 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x3B, 
0x0A, 0x7D, 0x0A, 0x0A, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x74, 0x62, 0x6F, 0x64, 0x79, 0x20, 
0x74, 0x72, 0x2E, 0x72, 0x65, 0x6D, 0x6F, 0x76, 0x65, 0x64, 0x7B, 0x0A, 0x09, 0x62, 0x61, 0x63, 
0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 0x20, 0x72, 0x65, 0x64, 0x3B, 0x0A, 0x7D, 0x0A, 
0x0A, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x74, 0x62, 0x6F, 0x64, 0x79, 0x20, 0x74, 0x72, 0x2E, 
0x6E, 0x65, 0x77, 0x7B, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 
0x3A, 0x20, 0x67, 0x72, 0x65, 0x65, 0x6E, 0x3B, 0x0A, 0x7D, 0x0A, 0x0A, 0x74, 0x61, 0x62, 0x6C, 
0x65, 0x20, 0x74, 0x62, 0x6F, 0x64, 0x79, 0x20, 0x74, 0x72, 0x3A, 0x68, 0x6F, 0x76, 0x65, 0x72, 
0x7B, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 0x20, 0x79, 
0x65, 0x6C, 0x6C, 0x6F, 0x77, 0x3B, 0x0A, 0x7D, 0x0A, 0x0A, 0x0A, 0x3C, 0x2F, 0x73, 0x74, 0x79, 
0x6C, 0x65, 0x3E, 0x0A, 0x20, 0x3C, 0x2F, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x3E, 0x0A, 0x3C, 
0x62, 0x6F, 0x64, 0x79, 0x3E, 0x0A, 0x3C, 0x68, 0x31, 0x3E, 0x4F, 0x6E, 0x69, 0x6F, 0x6E, 0x20, 
0x54, 0x6F, 0x70, 0x3C, 0x2F, 0x68, 0x31, 0x3E, 0x0A, 0x0A, 0x3C, 0x64, 0x69, 0x76, 0x20, 0x69, 
0x64, 0x3D, 0x22, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x22, 0x3E, 0x0A, 0x3C, 0x74, 0x61, 
0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x3C, 0x74, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x0A, 0x3C, 0x74, 0x72, 
0x3E, 0x3C, 0x74, 0x68, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x70, 0x69, 0x64, 0x22, 
0x3E, 0x50, 0x49, 0x44, 0x3C, 0x2F, 0x74, 0x68, 0x3E, 0x3C, 0x74, 0x68, 0x20, 0x63, 0x6C, 0x61, 
0x73, 0x73, 0x3D, 0x22, 0x6E, 0x61, 0x6D, 0x65, 0x22, 0x3E, 0x43, 0x6F, 0x6D, 0x6D, 0x61, 0x6E, 
0x64, 0x3C, 0x2F, 0x74, 0x68, 0x3E, 0x3C, 0x74, 0x68, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 
0x22, 0x75, 0x69, 0x64, 0x22, 0x3E, 0x55, 0x69, 0x64, 0x3C, 0x2F, 0x74, 0x68, 0x3E, 0x3C, 0x74, 
0x68, 0x3E, 0x50, 0x50, 0x69, 0x64, 0x3C, 0x2F, 0x74, 0x68, 0x3E, 0x3C, 0x74, 0x68, 0x3E, 0x52, 
0x53, 0x53, 0x3C, 0x2F, 0x74, 0x68, 0x3E, 0x3C, 0x74, 0x68, 0x3E, 0x44, 0x61, 0x74, 0x61, 0x3C, 
0x2F, 0x74, 0x68, 0x3E, 0x3C, 0x74, 0x68, 0x3E, 0x4C, 0x69, 0x62, 0x3C, 0x2F, 0x74, 0x68, 0x3E, 
0x3C, 0x74, 0x64, 0x3E, 0x3C, 0x2F, 0x74, 0x72, 0x3E, 0x0A, 0x3C, 0x2F, 0x74, 0x68, 0x65, 0x61, 
0x64, 0x3E, 0x0A, 0x3C, 0x74, 0x62, 0x6F, 0x64, 0x79, 0x3E, 0x0A, 0x3C, 0x2F, 0x74, 0x62, 0x6F, 
0x64, 0x79, 0x3E, 0x0A, 0x3C, 0x2F, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x3C, 0x2F, 0x64, 
0x69, 0x76, 0x3E, 0x0A, 0x0A, 0x3C, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 0x0A, 0x24, 0x28, 
0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x29, 0x2E, 0x72, 0x65, 0x61, 0x64, 0x79, 0x28, 
0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x28, 0x29, 0x7B, 0x0A, 0x09, 0x75, 0x70, 0x64, 
0x61, 0x74, 0x65, 0x54, 0x6F, 0x70, 0x28, 0x29, 0x0A, 0x7D, 0x29, 0x0A, 0x0A, 0x2F, 0x2A, 0x2A, 
0x0A, 0x20, 0x2A, 0x20, 0x40, 0x73, 0x68, 0x6F, 0x72, 0x74, 0x20, 0x55, 0x70, 0x64, 0x61, 0x74, 
0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x6F, 0x70, 0x20, 0x6C, 0x69, 0x73, 0x74, 0x2E, 
0x0A, 0x20, 0x2A, 0x2F, 0x0A, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x6F, 0x70, 0x20, 0x3D, 
0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x28, 0x29, 0x7B, 0x0A, 0x09, 0x76, 0x61, 
0x72, 0x20, 0x70, 0x3D, 0x24, 0x28, 0x27, 0x23, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x20, 
0x74, 0x62, 0x6F, 0x64, 0x79, 0x27, 0x29, 0x0A, 0x09, 0x76, 0x61, 0x72, 0x20, 0x58, 0x3D, 0x77, 
0x69, 0x6E, 0x64, 0x6F, 0x77, 0x2E, 0x70, 0x61, 0x67, 0x65, 0x58, 0x4F, 0x66, 0x66, 0x73, 0x65, 
0x74, 0x0A, 0x09, 0x76, 0x61, 0x72, 0x20, 0x59, 0x3D, 0x77, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x2E, 
0x70, 0x61, 0x67, 0x65, 0x59, 0x4F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x0A, 0x09, 0x24, 0x2E, 0x67, 
0x65, 0x74, 0x28, 0x27, 0x2F, 0x70, 0x73, 0x2F, 0x27, 0x2C, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 
0x69, 0x6F, 0x6E, 0x28, 0x6F, 0x72, 0x69, 0x67, 0x29, 0x7B, 0x0A, 0x09, 0x09, 0x6F, 0x3D, 0x6F, 
0x72, 0x69, 0x67, 0x0A, 0x09, 0x09, 0x64, 0x3D, 0x24, 0x2E, 0x70, 0x61, 0x72, 0x73, 0x65, 0x4A, 
0x53, 0x4F, 0x4E, 0x28, 0x6F, 0x72, 0x69, 0x67, 0x29, 0x0A, 0x09, 0x09, 0x24, 0x28, 0x27, 0x74, 
0x72, 0x2E, 0x72, 0x65, 0x6D, 0x6F, 0x76, 0x65, 0x64, 0x27, 0x29, 0x2E, 0x72, 0x65, 0x6D, 0x6F, 
0x76, 0x65, 0x28, 0x29, 0x0A, 0x09, 0x09, 0x76, 0x61, 0x72, 0x20, 0x6C, 0x69, 0x6E, 0x65, 0x73, 
0x3D, 0x70, 0x2E, 0x63, 0x68, 0x69, 0x6C, 0x64, 0x72, 0x65, 0x6E, 0x28, 0x27, 0x74, 0x72, 0x27, 
0x29, 0x0A, 0x09, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x73, 0x2E, 0x72, 0x65, 0x6D, 0x6F, 0x76, 0x65, 
0x43, 0x6C, 0x61, 0x73, 0x73, 0x28, 0x27, 0x6E, 0x65, 0x77, 0x27, 0x2C, 0x27, 0x73, 0x6C, 0x6F, 
0x77, 0x27, 0x29, 0x0A, 0x0A, 0x09, 0x09, 0x66, 0x6F, 0x72, 0x28, 0x6B, 0x20, 0x69, 0x6E, 0x20, 
0x64, 0x29, 0x7B, 0x0A, 0x09, 0x09, 0x09, 0x76, 0x61, 0x72, 0x20, 0x6C, 0x3D, 0x64, 0x5B, 0x6B, 
0x5D, 0x0A, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x6B, 0x21, 0x3D, 0x2D, 0x31, 0x29, 0x7B, 
0x0A, 0x09, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x6C, 0x69, 0x6E, 0x65, 0x73, 0x2E, 0x66, 
0x69, 0x6C, 0x74, 0x65, 0x72, 0x28, 0x27, 0x23, 0x27, 0x2B, 0x6B, 0x29, 0x2E, 0x6C, 0x65, 0x6E, 
0x67, 0x74, 0x68, 0x29, 0x7B, 0x20, 0x2F, 0x2F, 0x20, 0x61, 0x6C, 0x72, 0x65, 0x61, 0x64, 0x79, 
0x20, 0x68, 0x65, 0x72, 0x65, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x73, 
0x3D, 0x6C, 0x69, 0x6E, 0x65, 0x73, 0x2E, 0x6E, 0x6F, 0x74, 0x28, 0x27, 0x23, 0x27, 0x2B, 0x6B, 
0x29, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x7D, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x65, 0x6C, 0x73, 0x65, 
0x7B, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x76, 0x61, 0x72, 0x20, 0x74, 0x72, 0x3D, 0x24, 0x28, 
0x27, 0x3C, 0x74, 0x72, 0x3E, 0x27, 0x29, 0x2E, 0x61, 0x74, 0x74, 0x72, 0x28, 0x27, 0x69, 0x64, 
0x27, 0x2C, 0x6B, 0x29, 0x2E, 0x61, 0x64, 0x64, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x28, 0x27, 0x6E, 
0x65, 0x77, 0x27, 0x29, 0x2E, 0x66, 0x61, 0x64, 0x65, 0x49, 0x6E, 0x28, 0x27, 0x73, 0x6C, 0x6F, 
0x77, 0x27, 0x29, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x74, 0x72, 0x2E, 0x61, 0x70, 0x70, 0x65, 
0x6E, 0x64, 0x28, 0x24, 0x28, 0x27, 0x3C, 0x74, 0x64, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 
0x22, 0x70, 0x69, 0x64, 0x22, 0x3E, 0x27, 0x29, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x28, 0x6B, 0x29, 
0x29, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x74, 0x72, 0x2E, 0x61, 0x70, 0x70, 0x65, 0x6E, 0x64, 
0x28, 0x24, 0x28, 0x27, 0x3C, 0x74, 0x64, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x6E, 
0x61, 0x6D, 0x65, 0x22, 0x3E, 0x27, 0x29, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x28, 0x6C, 0x5B, 0x27, 
0x4E, 0x61, 0x6D, 0x65, 0x27, 0x5D, 0x29, 0x29, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x74, 0x72, 
0x2E, 0x61, 0x70, 0x70, 0x65, 0x6E, 0x64, 0x28, 0x24, 0x28, 0x27, 0x3C, 0x74, 0x64, 0x20, 0x63, 
0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x75, 0x69, 0x64, 0x22, 0x3E, 0x27, 0x29, 0x2E, 0x74, 0x65, 
0x78, 0x74, 0x28, 0x6C, 0x5B, 0x27, 0x55, 0x69, 0x64, 0x27, 0x5D, 0x29, 0x29, 0x0A, 0x09, 0x09, 
0x09, 0x09, 0x09, 0x74, 0x72, 0x2E, 0x61, 0x70, 0x70, 0x65, 0x6E, 0x64, 0x28, 0x24, 0x28, 0x27, 
0x3C, 0x74, 0x64, 0x3E, 0x27, 0x29, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x28, 0x6C, 0x5B, 0x27, 0x50, 
0x50, 0x69, 0x64, 0x27, 0x5D, 0x29, 0x29, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x74, 0x72, 0x2E, 
0x61, 0x70, 0x70, 0x65, 0x6E, 0x64, 0x28, 0x24, 0x28, 0x27, 0x3C, 0x74, 0x64, 0x3E, 0x27, 0x29, 
0x2E, 0x74, 0x65, 0x78, 0x74, 0x28, 0x6C, 0x5B, 0x27, 0x56, 0x6D, 0x52, 0x53, 0x53, 0x27, 0x5D, 
0x29, 0x29, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x74, 0x72, 0x2E, 0x61, 0x70, 0x70, 0x65, 0x6E, 
0x64, 0x28, 0x24, 0x28, 0x27, 0x3C, 0x74, 0x64, 0x3E, 0x27, 0x29, 0x2E, 0x74, 0x65, 0x78, 0x74, 
0x28, 0x6C, 0x5B, 0x27, 0x56, 0x6D, 0x44, 0x61, 0x74, 0x61, 0x27, 0x5D, 0x29, 0x29, 0x0A, 0x09, 
0x09, 0x09, 0x09, 0x09, 0x74, 0x72, 0x2E, 0x61, 0x70, 0x70, 0x65, 0x6E, 0x64, 0x28, 0x24, 0x28, 
0x27, 0x3C, 0x74, 0x64, 0x3E, 0x27, 0x29, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x28, 0x6C, 0x5B, 0x27, 
0x56, 0x6D, 0x4C, 0x69, 0x62, 0x27, 0x5D, 0x29, 0x29, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x70, 
0x2E, 0x61, 0x70, 0x70, 0x65, 0x6E, 0x64, 0x28, 0x74, 0x72, 0x29, 0x0A, 0x09, 0x09, 0x09, 0x09, 
0x7D, 0x0A, 0x09, 0x09, 0x09, 0x7D, 0x0A, 0x09, 0x09, 0x7D, 0x0A, 0x0A, 0x09, 0x09, 0x6C, 0x69, 
0x6E, 0x65, 0x73, 0x2E, 0x61, 0x64, 0x64, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x28, 0x27, 0x72, 0x65, 
0x6D, 0x6F, 0x76, 0x65, 0x64, 0x27, 0x29, 0x2E, 0x66, 0x61, 0x64, 0x65, 0x4F, 0x75, 0x74, 0x28, 
0x27, 0x73, 0x6C, 0x6F, 0x77, 0x27, 0x29, 0x0A, 0x0A, 0x09, 0x09, 0x2F, 0x2F, 0x20, 0x63, 0x6F, 
0x70, 0x79, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x64, 
0x65, 0x72, 0x2E, 0x0A, 0x09, 0x09, 0x24, 0x28, 0x27, 0x23, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 
0x73, 0x20, 0x74, 0x62, 0x6F, 0x64, 0x79, 0x20, 0x74, 0x64, 0x27, 0x29, 0x2E, 0x77, 0x69, 0x64, 
0x74, 0x68, 0x28, 0x24, 0x28, 0x27, 0x23, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x20, 0x74, 
0x68, 0x2E, 0x70, 0x69, 0x64, 0x27, 0x29, 0x2E, 0x77, 0x69, 0x64, 0x74, 0x68, 0x28, 0x29, 0x2B, 
0x33, 0x29, 0x0A, 0x09, 0x09, 0x24, 0x28, 0x27, 0x23, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 
0x20, 0x74, 0x62, 0x6F, 0x64, 0x79, 0x20, 0x74, 0x64, 0x2E, 0x75, 0x69, 0x64, 0x27, 0x29, 0x2E, 
0x77, 0x69, 0x64, 0x74, 0x68, 0x28, 0x24, 0x28, 0x27, 0x23, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 
0x73, 0x20, 0x74, 0x68, 0x2E, 0x75, 0x69, 0x64, 0x27, 0x29, 0x2E, 0x77, 0x69, 0x64, 0x74, 0x68, 
0x28, 0x29, 0x29, 0x0A, 0x09, 0x09, 0x24, 0x28, 0x27, 0x23, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 
0x73, 0x20, 0x74, 0x62, 0x6F, 0x64, 0x79, 0x20, 0x2E, 0x6E, 0x61, 0x6D, 0x65, 0x27, 0x29, 0x2E, 
0x77, 0x69, 0x64, 0x74, 0x68, 0x28, 0x24, 0x28, 0x27, 0x23, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 
0x73, 0x20, 0x74, 0x68, 0x65, 0x61, 0x64, 0x20, 0x2E, 0x6E, 0x61, 0x6D, 0x65, 0x27, 0x29, 0x2E, 
0x77, 0x69, 0x64, 0x74, 0x68, 0x28, 0x29, 0x29, 0x0A, 0x09, 0x7D, 0x2C, 0x27, 0x70, 0x6C, 0x61, 
0x69, 0x6E, 0x27, 0x29, 0x0A, 0x09, 0x0A, 0x09, 0x63, 0x68, 0x65, 0x63, 0x6B, 0x53, 0x69, 0x7A, 
0x65, 0x28, 0x29, 0x3B, 0x0A, 0x09, 0x24, 0x28, 0x77, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x29, 0x2E, 
0x72, 0x65, 0x73, 0x69, 0x7A, 0x65, 0x28, 0x63, 0x68, 0x65, 0x63, 0x6B, 0x53, 0x69, 0x7A, 0x65, 
0x29, 0x0A, 0x0A, 0x09, 0x77, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x2E, 0x73, 0x63, 0x72, 0x6F, 0x6C, 
0x6C, 0x54, 0x6F, 0x28, 0x58, 0x2C, 0x59, 0x29, 0x0A, 0x09, 0x73, 0x65, 0x74, 0x54, 0x69, 0x6D, 
0x65, 0x6F, 0x75, 0x74, 0x28, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x6F, 0x70, 0x2C, 0x32, 
0x2A, 0x31, 0x30, 0x30, 0x30, 0x29, 0x0A, 0x7D, 0x0A, 0x0A, 0x63, 0x68, 0x65, 0x63, 0x6B, 0x53, 
0x69, 0x7A, 0x65, 0x20, 0x3D, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x28, 0x29, 
0x7B, 0x0A, 0x09, 0x2F, 0x2F, 0x24, 0x28, 0x27, 0x23, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 
0x27, 0x29, 0x2E, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x28, 0x77, 0x69, 0x6E, 0x64, 0x6F, 0x77, 
0x2E, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x2D, 0x31, 0x30, 0x30, 
0x29, 0x3B, 0x0A, 0x09, 0x24, 0x28, 0x27, 0x23, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x20, 
0x74, 0x62, 0x6F, 0x64, 0x79, 0x27, 0x29, 0x2E, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x28, 0x77, 
0x69, 0x6E, 0x64, 0x6F, 0x77, 0x2E, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x48, 0x65, 0x69, 0x67, 0x68, 
0x74, 0x2D, 0x24, 0x28, 0x27, 0x2E, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x43, 0x6F, 0x6E, 0x74, 0x61, 
0x69, 0x6E, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x61, 0x64, 0x27, 0x29, 0x2E, 0x68, 0x65, 0x69, 
0x67, 0x68, 0x74, 0x28, 0x29, 0x2D, 0x31, 0x31, 0x35, 0x29, 0x3B, 0x0A, 0x09, 0x24, 0x28, 0x27, 
0x23, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x61, 0x64, 0x20, 0x2E, 
0x6E, 0x61, 0x6D, 0x65, 0x27, 0x29, 0x2E, 0x77, 0x69, 0x64, 0x74, 0x68, 0x28, 0x24, 0x28, 0x27, 
0x23, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x27, 0x29, 0x2E, 0x77, 0x69, 0x64, 0x74, 0x68, 
0x28, 0x29, 0x29, 0x0A, 0x0A, 0x7D, 0x0A, 0x0A, 0x3C, 0x2F, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 
0x3E, 0x0A, 0x0A, 0x3C, 0x2F, 0x62, 0x6F, 0x64, 0x79, 0x3E, 0x0A, };
  onion_response_set_length(res, 2507);
  return onion_response_write(res, data, sizeof(data));
}
Exemple #25
0
void extended_html__block_title(onion_dict *context, onion_response *res){
#line 1
#line 3
  onion_response_write(res, "Extended", 8);
#line 1
}
Exemple #26
0
// Writes the data to the response
static void onion_png_write(png_struct *p, png_bytep data, size_t l){
	onion_png_data *d=(onion_png_data*)png_get_io_ptr(p);
	onion_response_write(d->res, (const char *)data, l);
	//ONION_DEBUG("Write");
}
void base_html__block_content(onion_dict *context, onion_response *res){
#line 1
  onion_response_write(res, "No content", 10);
#line 1
}
Exemple #28
0
/**
 * @short This shortcut returns the given file contents. 
 * 
 * It sets all the compilant headers (TODO), cache and so on.
 * 
 * This is the recomended way to send static files; it even can use sendfile Linux call 
 * if suitable (TODO).
 * 
 * It does no security checks, so caller must be security aware.
 */
onion_connection_status onion_shortcut_response_file(const char *filename, onion_request *request, onion_response *res){
	int fd=open(filename,O_RDONLY|O_CLOEXEC);
	
	if (fd<0)
		return OCS_NOT_PROCESSED;

	if(O_CLOEXEC == 0) { // Good compiler know how to cut this out
		int flags=fcntl(fd, F_GETFD);
		if (flags==-1){
			ONION_ERROR("Retrieving flags from file descriptor");
		}
		flags|=FD_CLOEXEC;
		if (fcntl(fd, F_SETFD, flags)==-1){
			ONION_ERROR("Setting O_CLOEXEC to file descriptor");
		}
	}
	
	struct stat st;
	if (stat(filename, &st)!=0){
		ONION_WARNING("File does not exist: %s",filename);
		close(fd);
		return OCS_NOT_PROCESSED;
	}
	
	if (S_ISDIR(st.st_mode)){
		close(fd);
		return OCS_NOT_PROCESSED;
	}
	
	size_t length=st.st_size;
	
	char etag[64];
	onion_shortcut_etag(&st, etag);
		
	const char *range=onion_request_get_header(request, "Range");
	if (range){
		strncat(etag,range,sizeof(etag)-1);
	}
	onion_response_set_header(res, "Etag", etag);
	
	if (range && strncmp(range,"bytes=",6)==0){
		onion_response_set_code(res, HTTP_PARTIAL_CONTENT);
		//ONION_DEBUG("Need just a range: %s",range);
		char tmp[1024];
		strncpy(tmp, range+6, 1024);
		char *start=tmp;
		char *end=tmp;
		while (*end!='-' && *end) end++;
		if (*end=='-'){
			*end='\0';
			end++;
			
			//ONION_DEBUG("Start %s, end %s",start,end);
			size_t ends, starts;
			if (*end)
				ends=atol(end);
			else
				ends=length;
			starts=atol(start);
			length=ends-starts+1;
			lseek(fd, starts, SEEK_SET);
			snprintf(tmp,sizeof(tmp),"bytes %d-%d/%d",(unsigned int)starts, (unsigned int)ends, (unsigned int)st.st_size);
			//onion_response_set_header(res, "Accept-Ranges","bytes");
			onion_response_set_header(res, "Content-Range",tmp);
		}
	}
	
	onion_response_set_length(res, length);
	onion_response_set_header(res, "Content-Type", onion_mime_get(filename) );
	ONION_DEBUG("Mime type is %s",onion_mime_get(filename));

  ONION_DEBUG0("Etag %s", etag);
  const char *prev_etag=onion_request_get_header(request, "If-None-Match");
  if (prev_etag && (strcmp(prev_etag, etag)==0)){
    ONION_DEBUG0("Not modified");
    onion_response_set_length(res, 0);
    onion_response_set_code(res, HTTP_NOT_MODIFIED);
    onion_response_write_headers(res);
    close(fd);
    return OCS_PROCESSED;
  }
	onion_response_write_headers(res);
	if ((onion_request_get_flags(request)&OR_HEAD) == OR_HEAD){ // Just head.
		length=0;
	}
	
	if (length){
#ifdef USE_SENDFILE
		if (request->connection.listen_point->write==(void*)onion_http_write){ // Lets have a house party! I can use sendfile!
			onion_response_write(res,NULL,0);
			ONION_DEBUG("Using sendfile");
			int r=sendfile(request->connection.fd, fd, NULL, length);
			ONION_DEBUG("Wrote %d, should be %d (%s)", r, length, r==length ? "ok" : "nok");
			if (r!=length || r<0){
				ONION_ERROR("Could not send all file (%s)", strerror(errno));
				close(fd);
				return OCS_INTERNAL_ERROR;
			}
			res->sent_bytes+=length;
			res->sent_bytes_total+=length;
		}
		else
#endif
		{ // Ok, no I cant, do it as always.
			int r=0,w;
			size_t tr=0;
			char tmp[4046];
			if (length>sizeof(tmp)){
				size_t max=length-sizeof(tmp);
				while( tr<max ){
					r=read(fd,tmp,sizeof(tmp));
					tr+=r;
					if (r<0)
						break;
					w=onion_response_write(res, tmp, r);
					if (w!=r){
						ONION_ERROR("Wrote less than read: write %d, read %d. Quite probably closed connection.",w,r);
						break;
					}
				}
			}
			if (sizeof(tmp) >= (length-tr)){
				r=read(fd, tmp, length-tr);
				w=onion_response_write(res, tmp, r);
				if (w!=r){
					ONION_ERROR("Wrote less than read: write %d, read %d. Quite probably closed connection.",w,r);
				}
			}
		}
	}
	close(fd);
	return OCS_PROCESSED;
}