コード例 #1
0
ファイル: core.c プロジェクト: MiniHero/mapcache
mapcache_http_response *mapcache_core_get_map(mapcache_context *ctx, mapcache_request_get_map *req_map)
{
  mapcache_image_format *format = NULL;
  mapcache_http_response *response;
  mapcache_map *basemap = NULL;
  char *timestr;
#ifdef DEBUG
  if(req_map->nmaps ==0) {
    ctx->set_error(ctx,500,"BUG: get_map called with 0 maps");
    return NULL;
  }
#endif


  if(req_map->getmap_strategy == MAPCACHE_GETMAP_ERROR) {
    ctx->set_error(ctx, 404, "full wms support disabled");
    return NULL;
  }

  format = NULL;
  response = mapcache_http_response_create(ctx->pool);


  if(req_map->getmap_strategy == MAPCACHE_GETMAP_ASSEMBLE) {
    basemap = mapcache_assemble_maps(ctx, req_map->maps, req_map->nmaps, req_map->resample_mode);
    if(GC_HAS_ERROR(ctx)) return NULL;
  } else if(!ctx->config->non_blocking && req_map->getmap_strategy == MAPCACHE_GETMAP_FORWARD) {
    int i;
    basemap = req_map->maps[0];
    for(i=0; i<req_map->nmaps; i++) {
      if(!req_map->maps[i]->tileset->source) {
        ctx->set_error(ctx,404,"cannot forward request for tileset %s: no source configured",
                       req_map->maps[i]->tileset->name);
        return NULL;
      }
    }
    basemap->tileset->source->render_map(ctx, basemap);
    if(GC_HAS_ERROR(ctx)) return NULL;
    if(req_map->nmaps>1) {
      if(!basemap->raw_image) {
        basemap->raw_image = mapcache_imageio_decode(ctx,basemap->encoded_data);
        if(GC_HAS_ERROR(ctx)) return NULL;
      }
      for(i=1; i<req_map->nmaps; i++) {
        mapcache_map *overlaymap = req_map->maps[i];
        overlaymap->tileset->source->render_map(ctx, overlaymap);
        if(GC_HAS_ERROR(ctx)) return NULL;
        if(!overlaymap->raw_image) {
          overlaymap->raw_image = mapcache_imageio_decode(ctx,overlaymap->encoded_data);
          if(GC_HAS_ERROR(ctx)) return NULL;
        }
        if(GC_HAS_ERROR(ctx)) return NULL;
        mapcache_image_merge(ctx,basemap->raw_image,overlaymap->raw_image);
        if(GC_HAS_ERROR(ctx)) return NULL;
        if(!basemap->expires || overlaymap->expires<basemap->expires) basemap->expires = overlaymap->expires;
      }
    }
  } else {
    ctx->set_error(ctx,400,"failed getmap, readonly mode");
    return NULL;
  }

  if(basemap->raw_image) {
    format = req_map->getmap_format; /* always defined, defaults to JPEG */
    response->data = format->write(ctx,basemap->raw_image,format);
    if(GC_HAS_ERROR(ctx)) {
      return NULL;
    }
  } else {
    /* this case happens when we have a forward strategy for a single tileset */
#ifdef DEBUG
    if(!basemap->encoded_data) {
      ctx->set_error(ctx,500,"###BUG### core_get_map failed with null encoded_data");
      return NULL;
    }
#endif
    response->data = basemap->encoded_data;
  }

  /* compute the content-type */
  if(format && format->mime_type) {
    apr_table_set(response->headers,"Content-Type",format->mime_type);
  } else {
    mapcache_image_format_type t = mapcache_imageio_header_sniff(ctx,response->data);
    if(t == GC_PNG)
      apr_table_set(response->headers,"Content-Type","image/png");
    else if(t == GC_JPEG)
      apr_table_set(response->headers,"Content-Type","image/jpeg");
  }

  /* compute expiry headers */
  if(basemap->expires) {
    apr_time_t now = apr_time_now();
    apr_time_t additional = apr_time_from_sec(basemap->expires);
    apr_time_t texpires = now + additional;
    apr_table_set(response->headers, "Cache-Control",
                  apr_psprintf(ctx->pool, "max-age=%d", basemap->expires));
    timestr = apr_palloc(ctx->pool, APR_RFC822_DATE_LEN);
    apr_rfc822_date(timestr, texpires);
    apr_table_setn(response->headers, "Expires", timestr);
  }

  response->mtime = basemap->mtime;
  return response;
}
コード例 #2
0
ファイル: switch_apr.c プロジェクト: gujun/sscore
SWITCH_DECLARE(switch_status_t) switch_rfc822_date(char *date_str, switch_time_t t)
{
	return apr_rfc822_date(date_str, t);
}
コード例 #3
0
ファイル: core.c プロジェクト: MiniHero/mapcache
mapcache_http_response *mapcache_core_get_tile(mapcache_context *ctx, mapcache_request_get_tile *req_tile)
{
  int expires = 0;
  mapcache_http_response *response;
  int i,is_empty=1 /* response image is initially empty */;
  char *timestr;
  mapcache_image *base=NULL;
  mapcache_image_format *format = NULL;

#ifdef DEBUG
  if(req_tile->ntiles ==0) {
    ctx->set_error(ctx,500,"BUG: get_tile called with 0 tiles");
    return NULL;
  }
#endif
  response = mapcache_http_response_create(ctx->pool);


  mapcache_prefetch_tiles(ctx,req_tile->tiles,req_tile->ntiles);
  if(GC_HAS_ERROR(ctx))
    return NULL;

  /* loop through tiles, and eventually merge them vertically together */
  for(i=0; i<req_tile->ntiles; i++) {
    mapcache_tile *tile = req_tile->tiles[i]; /* shortcut */
    if(tile->mtime && (tile->mtime < response->mtime || response->mtime == 0))
      response->mtime = tile->mtime;
    if(tile->expires && (tile->expires < expires || expires == 0)) {
      expires = tile->expires;
    }
    
    if(tile->nodata) {
      /* treat the special case where the cache explicitely stated that the
       tile was empty, and we don't have any vertical merging to do */
      if(tile->encoded_data && req_tile->ntiles == 1) {
        response->data = tile->encoded_data;
        /* we don't touch is_empty, as we have access to the encoded empty image, but the
         resulting tile is empty */
      }
      continue;
    }
    
    /* treat the most common case: 
     - we have a single tile request (i.e. isempty is true)
     - the cache returned the encoded image
     */
    if(is_empty && tile->encoded_data) {
      response->data = tile->encoded_data;
      /* just in case we also have the raw image data available, keep a ref to it
       if we need to merge another tile ontop of it*/
      if(tile->raw_image) {
        base = tile->raw_image;
      }
      is_empty = 0; /* we now know we might need to do some vertical merging */
      continue;
    }

    /* if we're here, either
     * - we need to merge the current tile onto the previous one(s), or
     * - we only have the tile's raw data available
     */

    if(!is_empty) {
      /* we have an existing tile, so we know we need to merge the current one into it */
      if(!base) {
        /* the existing tile has not been decoded yet, but we need the access to the raw pixels*/
        base = mapcache_imageio_decode(ctx, response->data);
        if(!base) return NULL;
      }
      response->data = NULL; /* the encoded data is now obsolete, as we will be merging the current tile */

      /* we need to access the current tile's pixel data */
      if(!tile->raw_image) {
        tile->raw_image = mapcache_imageio_decode(ctx,tile->encoded_data);
        if(!tile->raw_image) return NULL;
      }
      mapcache_image_merge(ctx, base, tile->raw_image);
    } else {
      /* we don't need to merge onto an existing tile and don't have access to the tile's encoded data.
       * 
       * we don't encode the tile's raw image data just yet because we might need to merge another one on top
       * of it later.
       */
      base = tile->raw_image;
      is_empty = 0;
    }
  }

  if(!response->data) {
    /* we need to encode the raw image data*/
    if(base) {
      if(req_tile->format) {
        format = req_tile->format;
      } else {
        format = req_tile->tiles[0]->tileset->format;
        if(!format) {
          format = ctx->config->default_image_format; /* this one is always defined */
        }
      }
      response->data = format->write(ctx, base, format);
      if(GC_HAS_ERROR(ctx)) {
        return NULL;
      }
    } else {
#ifdef DEBUG
      if(!is_empty) {
        ctx->set_error(ctx,500,"BUG: no image data to encode, but tile not marked as empty");
        return NULL;
      }
#endif
      unsigned char empty[5] = {'#',0,0,0,0};
      response->data = mapcache_empty_png_decode(ctx,empty,&is_empty); /* is_empty is unchanged and left to 1 */
      format = mapcache_configuration_get_image_format(ctx->config,"PNG8");
    }
  }
  
  /* compute the content-type */
  mapcache_image_format_type t = mapcache_imageio_header_sniff(ctx,response->data);
  if(t == GC_PNG)
    apr_table_set(response->headers,"Content-Type","image/png");
  else if(t == GC_JPEG)
    apr_table_set(response->headers,"Content-Type","image/jpeg");

  /* compute expiry headers */
  if(expires) {
    apr_time_t now = apr_time_now();
    apr_time_t additional = apr_time_from_sec(expires);
    apr_time_t texpires = now + additional;
    apr_table_set(response->headers, "Cache-Control",apr_psprintf(ctx->pool, "max-age=%d", expires));
    timestr = apr_palloc(ctx->pool, APR_RFC822_DATE_LEN);
    apr_rfc822_date(timestr, texpires);
    apr_table_setn(response->headers, "Expires", timestr);
  }

  return response;
}
コード例 #4
0
ファイル: mod_file_cache.c プロジェクト: pexip/os-apache2
static int file_cache_handler(request_rec *r)
{
    a_file *match;
    int errstatus;
    int rc = OK;

    /* Bail out if r->handler isn't the default value, and doesn't look like a Content-Type
     * XXX: Even though we made the user explicitly list each path to cache?
     */
    if (ap_strcmp_match(r->handler, "*/*") && !AP_IS_DEFAULT_HANDLER_NAME(r->handler)) {
        return DECLINED;
    }

    /* we don't handle anything but GET */
    if (r->method_number != M_GET) return DECLINED;

    /* did xlat phase find the file? */
    match = ap_get_module_config(r->request_config, &file_cache_module);

    if (match == NULL) {
        return DECLINED;
    }

    /* note that we would handle GET on this resource */
    r->allowed |= (AP_METHOD_BIT << M_GET);

    /* This handler has no use for a request body (yet), but we still
     * need to read and discard it if the client sent one.
     */
    if ((errstatus = ap_discard_request_body(r)) != OK)
        return errstatus;

    ap_update_mtime(r, match->finfo.mtime);

    /* ap_set_last_modified() always converts the file mtime to a string
     * which is slow.  Accelerate the common case.
     * ap_set_last_modified(r);
     */
    {
        apr_time_t mod_time;
        char *datestr;

        mod_time = ap_rationalize_mtime(r, r->mtime);
        if (mod_time == match->finfo.mtime)
            datestr = match->mtimestr;
        else {
            datestr = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
            apr_rfc822_date(datestr, mod_time);
        }
        apr_table_setn(r->headers_out, "Last-Modified", datestr);
    }

    /* ap_set_content_length() always converts the same number and never
     * returns an error.  Accelerate it.
     */
    r->clength = match->finfo.size;
    apr_table_setn(r->headers_out, "Content-Length", match->sizestr);

    ap_set_etag(r);
    if ((errstatus = ap_meets_conditions(r)) != OK) {
       return errstatus;
    }

    /* Call appropriate handler */
    if (!r->header_only) {
        if (match->is_mmapped == TRUE)
            rc = mmap_handler(r, match);
        else
            rc = sendfile_handler(r, match);
    }

    return rc;
}
コード例 #5
0
static void ngx_http_mapcache_write_response(mapcache_context *ctx, ngx_http_request_t *r,
      mapcache_http_response *response) {
   if(response->mtime) {
      time_t  if_modified_since;
      if(r->headers_in.if_modified_since) {
         if_modified_since = ngx_http_parse_time(r->headers_in.if_modified_since->value.data,
               r->headers_in.if_modified_since->value.len);
         if (if_modified_since != NGX_ERROR) {
            apr_time_t apr_if_m_s;
            apr_time_ansi_put	(	&apr_if_m_s, if_modified_since);
            if(apr_if_m_s<response->mtime) {
               r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
               ngx_http_send_header(r);
               return;
            }
         }
      }
      char *datestr;
      datestr = apr_palloc(ctx->pool, APR_RFC822_DATE_LEN);
      apr_rfc822_date(datestr, response->mtime);
      apr_table_setn(response->headers,"Last-Modified",datestr);
   }
   if(response->headers && !apr_is_empty_table(response->headers)) {
      const apr_array_header_t *elts = apr_table_elts(response->headers);
      int i;
      for(i=0;i<elts->nelts;i++) {
         apr_table_entry_t entry = APR_ARRAY_IDX(elts,i,apr_table_entry_t);
         if(!strcasecmp(entry.key,"Content-Type")) {
            r->headers_out.content_type.len = strlen(entry.val);
            r->headers_out.content_type.data = (u_char*)entry.val;
         } else {
            ngx_table_elt_t   *h;
            h = ngx_list_push(&r->headers_out.headers);
            if (h == NULL) {
               return;
            }
            h->key.len = strlen(entry.key) ;
            h->key.data = (u_char*)entry.key ;
            h->value.len = strlen(entry.val) ;
            h->value.data = (u_char*)entry.val ;
            h->hash = 1;
         }
      }
   }
   if(response->data) {
      r->headers_out.content_length_n = response->data->size;
   }
   int rc;
   r->headers_out.status = response->code;
   rc = ngx_http_send_header(r);
   if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
      return;
   }

   if(response->data) {
      ngx_buf_t    *b;
      ngx_chain_t   out;
      b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
      if (b == NULL) {
         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 
               "Failed to allocate response buffer.");
         return;
      }

      b->pos = ngx_pcalloc(r->pool,response->data->size);
      memcpy(b->pos,response->data->buf,response->data->size);
      b->last = b->pos + response->data->size;
      b->memory = 1;
      b->last_buf = 1;
      b->flush = 1;
      out.buf = b;
      out.next = NULL;
      ngx_http_output_filter(r, &out);
   }

}
コード例 #6
0
APREQ_DECLARE(int) apreq_cookie_serialize(const apreq_cookie_t *c,
                                          char *buf, apr_size_t len)
{
    /*  The format string must be large enough to accomodate all
     *  of the cookie attributes.  The current attributes sum to
     *  ~90 characters (w/ 6-8 padding chars per attr), so anything
     *  over 100 should be fine.
     */

    unsigned version = apreq_cookie_version(c);
    char format[128] = "%s=%s";
    char *f = format + strlen(format);

    /* XXX protocol enforcement (for debugging, anyway) ??? */

    if (c->v.name == NULL)
        return -1;

#define NULL2EMPTY(attr) (attr ? attr : "")


    if (version == NETSCAPE) {
        char expires[APR_RFC822_DATE_LEN] = {0};

#define ADD_NS_ATTR(name) do {                  \
    if (c->name != NULL)                        \
        strcpy(f, "; " #name "=%s");            \
    else                                        \
        strcpy(f, "%0.s");                      \
    f += strlen(f);                             \
} while (0)

        ADD_NS_ATTR(path);
        ADD_NS_ATTR(domain);

        if (c->max_age != -1) {
            strcpy(f, "; expires=%s");
            apr_rfc822_date(expires, c->max_age + apr_time_now());
            expires[7] = '-';
            expires[11] = '-';
        }
        else
            strcpy(f, "");

        f += strlen(f);

        if (apreq_cookie_is_secure(c))
            strcpy(f, "; secure");

        f += strlen(f);

        if (apreq_cookie_is_httponly(c))
            strcpy(f, "; HttpOnly");

        return apr_snprintf(buf, len, format, c->v.name, c->v.data,
           NULL2EMPTY(c->path), NULL2EMPTY(c->domain), expires);
    }

    /* c->version == RFC */

    strcpy(f,"; Version=%u");
    f += strlen(f);

/* ensure RFC attributes are always quoted */
#define ADD_RFC_ATTR(name) do {                 \
    if (c->name != NULL)                        \
        if (*c->name == '"')                    \
            strcpy(f, "; " #name "=%s");        \
        else                                    \
            strcpy(f, "; " #name "=\"%s\"");    \
    else                                        \
        strcpy(f, "%0.s");                      \
    f += strlen (f);                            \
} while (0)

    ADD_RFC_ATTR(path);
    ADD_RFC_ATTR(domain);
    ADD_RFC_ATTR(port);
    ADD_RFC_ATTR(comment);
    ADD_RFC_ATTR(commentURL);

    strcpy(f, c->max_age != -1 ? "; max-age=%" APR_TIME_T_FMT : "");

    f += strlen(f);

    if (apreq_cookie_is_secure(c))
        strcpy(f, "; secure");

    f += strlen(f);

    if (apreq_cookie_is_httponly(c))
        strcpy(f, "; HttpOnly");

    return apr_snprintf(buf, len, format, c->v.name, c->v.data, version,
                        NULL2EMPTY(c->path), NULL2EMPTY(c->domain),
                        NULL2EMPTY(c->port), NULL2EMPTY(c->comment),
                        NULL2EMPTY(c->commentURL), apr_time_sec(c->max_age));
}
コード例 #7
0
ファイル: mod_file_cache.c プロジェクト: pexip/os-apache2
static void cache_the_file(cmd_parms *cmd, const char *filename, int mmap)
{
    a_server_config *sconf;
    a_file *new_file;
    a_file tmp;
    apr_file_t *fd = NULL;
    apr_status_t rc;
    const char *fspec;

    fspec = ap_server_root_relative(cmd->pool, filename);
    if (!fspec) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, APR_EBADPATH, cmd->server, APLOGNO(00794)
                     "invalid file path "
                     "%s, skipping", filename);
        return;
    }
    if ((rc = apr_stat(&tmp.finfo, fspec, APR_FINFO_MIN,
                                 cmd->temp_pool)) != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server, APLOGNO(00795)
                     "unable to stat(%s), skipping", fspec);
        return;
    }
    if (tmp.finfo.filetype != APR_REG) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, APLOGNO(00796)
                     "%s isn't a regular file, skipping", fspec);
        return;
    }
    if (tmp.finfo.size > AP_MAX_SENDFILE) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, APLOGNO(00797)
                     "%s is too large to cache, skipping", fspec);
        return;
    }

    rc = apr_file_open(&fd, fspec, APR_READ | APR_BINARY | APR_XTHREAD,
                       APR_OS_DEFAULT, cmd->pool);
    if (rc != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server, APLOGNO(00798)
                     "unable to open(%s, O_RDONLY), skipping", fspec);
        return;
    }
    apr_file_inherit_set(fd);

    /* WooHoo, we have a file to put in the cache */
    new_file = apr_pcalloc(cmd->pool, sizeof(a_file));
    new_file->finfo = tmp.finfo;

#if APR_HAS_MMAP
    if (mmap) {
        /* MMAPFile directive. MMAP'ing the file
         * XXX: APR_HAS_LARGE_FILES issue; need to reject this request if
         * size is greater than MAX(apr_size_t) (perhaps greater than 1M?).
         */
        if ((rc = apr_mmap_create(&new_file->mm, fd, 0,
                                  (apr_size_t)new_file->finfo.size,
                                  APR_MMAP_READ, cmd->pool)) != APR_SUCCESS) {
            apr_file_close(fd);
            ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server, APLOGNO(00799)
                         "unable to mmap %s, skipping", filename);
            return;
        }
        apr_file_close(fd);
        new_file->is_mmapped = TRUE;
    }
#endif
#if APR_HAS_SENDFILE
    if (!mmap) {
        /* CacheFile directive. Caching the file handle */
        new_file->is_mmapped = FALSE;
        new_file->file = fd;
    }
#endif

    new_file->filename = fspec;
    apr_rfc822_date(new_file->mtimestr, new_file->finfo.mtime);
    apr_snprintf(new_file->sizestr, sizeof new_file->sizestr, "%" APR_OFF_T_FMT, new_file->finfo.size);

    sconf = ap_get_module_config(cmd->server->module_config, &file_cache_module);
    apr_hash_set(sconf->fileht, new_file->filename, strlen(new_file->filename), new_file);

}
コード例 #8
0
ファイル: core.c プロジェクト: shigekun/mapcache
mapcache_http_response *mapcache_core_get_tile(mapcache_context *ctx, mapcache_request_get_tile *req_tile)
{
  int expires = 0;
  mapcache_http_response *response;
  int i,first = -1;
  int ntiles_with_data = 0;
  char *timestr;
  mapcache_image *base=NULL,*overlay;
  mapcache_image_format *format = NULL;

#ifdef DEBUG
  if(req_tile->ntiles ==0) {
    ctx->set_error(ctx,500,"BUG: get_tile called with 0 tiles");
    return NULL;
  }
#endif
  expires = 0;
  response = mapcache_http_response_create(ctx->pool);


  mapcache_prefetch_tiles(ctx,req_tile->tiles,req_tile->ntiles);
  if(GC_HAS_ERROR(ctx))
    return NULL;

  /* count how many tiles actually contain data */
  for(i=0; i<req_tile->ntiles; i++) {
    /* add 1 if tile->nodata == 0 */
    ntiles_with_data -= req_tile->tiles[i]->nodata - 1;
  }
  if(ntiles_with_data == 0) {
    ctx->set_error(ctx,404,
                   "no tiles containing image data could be retrieved (not in cache, and read-only tileset or no source configured)");
    return NULL;
  }
  /* this loop retrieves the tiles from the caches, and eventually decodes and merges them together
   * if multiple tiles were asked for */
  for(i=0; i<req_tile->ntiles; i++) {
    mapcache_tile *tile = req_tile->tiles[i];
    if(tile->nodata) continue;
    if(first == -1) {
      first = i;
      response->mtime = tile->mtime;
      expires = tile->expires;
      /* if we have multiple tiles to merge, decode the image data */
      if(ntiles_with_data>1) {
        if(!tile->raw_image) {
          tile->raw_image = mapcache_imageio_decode(ctx, tile->encoded_data);
          if(!tile->raw_image) return NULL;
        }
        base = tile->raw_image;
      }
    } else {
      if(response->mtime < tile->mtime)
        response->mtime = tile->mtime;
      if(tile->expires < expires) {
        expires = tile->expires;
      }
      if(!tile->raw_image) {
        tile->raw_image = mapcache_imageio_decode(ctx, tile->encoded_data);
        if(!tile->raw_image) return NULL;
      }
      overlay = tile->raw_image;
      mapcache_image_merge(ctx, base, overlay);
      if(GC_HAS_ERROR(ctx)) {
        return NULL;
      }
    }
  }
  format = NULL;

  /* if we had more than one tile, we need to encode the raw image data into a mapcache_buffer */
  if(ntiles_with_data > 1) {
    if(req_tile->format) {
      format = req_tile->format;
    } else {
      format = req_tile->tiles[first]->tileset->format;
      if(!format) {
        format = ctx->config->default_image_format; /* this one is always defined */
      }
    }
    response->data = format->write(ctx, base, format);
    if(GC_HAS_ERROR(ctx)) {
      return NULL;
    }
  } else {
    response->data = req_tile->tiles[first]->encoded_data;
    format = req_tile->tiles[first]->tileset->format;
  }

  /* compute the content-type */
  if(format && format->mime_type) {
    apr_table_set(response->headers,"Content-Type",format->mime_type);
  } else {
    mapcache_image_format_type t = mapcache_imageio_header_sniff(ctx,response->data);
    if(t == GC_PNG)
      apr_table_set(response->headers,"Content-Type","image/png");
    else if(t == GC_JPEG)
      apr_table_set(response->headers,"Content-Type","image/jpeg");
  }

  /* compute expiry headers */
  if(expires) {
    apr_time_t now = apr_time_now();
    apr_time_t additional = apr_time_from_sec(expires);
    apr_time_t texpires = now + additional;
    apr_table_set(response->headers, "Cache-Control",apr_psprintf(ctx->pool, "max-age=%d", expires));
    timestr = apr_palloc(ctx->pool, APR_RFC822_DATE_LEN);
    apr_rfc822_date(timestr, texpires);
    apr_table_setn(response->headers, "Expires", timestr);
  }

  return response;
}
コード例 #9
0
ファイル: mod_mediarss.c プロジェクト: st3fan/mod_mediarss
static int mediarss_index_directory(request_rec* r)
{
   apr_status_t status;
   apr_dir_t* dir;
   apr_finfo_t dirent;

   if ((status = apr_dir_open(&dir, r->filename, r->pool)) != APR_SUCCESS) {
      ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, "Can't open directory for index: %s", r->filename);
      return HTTP_FORBIDDEN;
   }

   /* Content header */
   
   char* url;
   url = ap_construct_url(r->pool, r->uri, r);

   ap_set_content_type(r, "text/xml; charset=utf-8");

   ap_rputs("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n", r);
   if (strcmp(r->args, "format=mediarss") == 0) {
      ap_rputs("<rss version=\"2.0\" xmlns:media=\"http://search.yahoo.com/mrss/\">\n", r);
   } else {
      ap_rputs("<rss version=\"2.0\">\n", r);
   }
   ap_rputs("  <channel>\n", r);
   ap_rvputs(r, "    <title>Index of ", url, "</title>\n", NULL);
   ap_rvputs(r, "    <link>", url, "</link>\n", NULL);

   /* Collect information about the files in the directory */
   
   while (1)
   {
      status = apr_dir_read(&dirent, APR_FINFO_MIN | APR_FINFO_NAME, dir);
      if (APR_STATUS_IS_INCOMPLETE(status)) {
         continue; /* ignore un-stat()able files */
      } else if (status != APR_SUCCESS) {
         break;
      }
      
      /* We are only interested in regular files. TODO Deal with symlinks. */
      
      if (dirent.filetype == APR_REG)
      {
         request_rec* rr;
         
         rr = ap_sub_req_lookup_dirent(&dirent, r, AP_SUBREQ_NO_ARGS, NULL);
         if (rr != NULL)
         {
            if (rr->finfo.filetype == APR_REG && rr->status == HTTP_OK)
            {
               /* In case of media rss, only include the item if it is a media type */

               if (strcmp(r->args, "format=mediarss") == 0 && mediarss_is_media_content(rr->content_type) == 0) {
                  continue;
               }

               char size[16];
               snprintf(size, sizeof(size), "%d", dirent.size);
               
               char date[APR_RFC822_DATE_LEN];
               apr_rfc822_date(date, dirent.mtime);
               
               char* guid = ap_md5(r->pool, (unsigned char*) apr_pstrcat(r->pool, url, dirent.name, NULL));
                           
               ap_rputs("    <item>\n", r);
               ap_rvputs(r, "      <guid>", guid, "</guid>\n", NULL);
               ap_rvputs(r, "      <title>", dirent.name, "</title>\n", NULL);
               ap_rvputs(r, "      <pubDate>", date, "</pubDate>\n", NULL);
               ap_rvputs(r, "      <enclosure url=\"", url, dirent.name, "\" length=\"", size, "\"\n", NULL);
               ap_rvputs(r, "        type=\"", rr->content_type, "\"/>\n", NULL);
               if (strcmp(r->args, "format=mediarss") == 0) {
                  ap_rvputs(r, "      <media:content url=\"", url, dirent.name, "\" fileSize=\"", size, "\"\n", NULL);
                  ap_rvputs(r, "        type=\"", rr->content_type, "\"/>\n", NULL);
               }
               ap_rputs("    </item>\n", r);
            }
            ap_destroy_sub_req(rr);
         }
      }
   }

   /* Content footer */

   ap_rputs("  </channel>\n", r);
   ap_rputs("</rss>\n", r);

   apr_dir_close(dir);
   
   return OK;
}
コード例 #10
0
ファイル: verify.c プロジェクト: gavinsharp/mod_authn_persona
/*
 * process an assertion using the hosted verifier.
 *
 * TODO: local verification
 */
VerifyResult processAssertion(request_rec *r, const char *verifier_url,
                              const char *assertion)
{
  VerifyResult res = apr_pcalloc(r->pool, sizeof(struct _VerifyResult));
  json_tokener *tok = json_tokener_new();
  json_object *jobj = NULL;
  enum json_tokener_error jerr;

  char *assertionResult =
    verifyAssertionRemote(r, verifier_url, (char *) assertion);

  if (assertionResult) {
    jobj =
      json_tokener_parse_ex(tok, assertionResult, strlen(assertionResult));
    jerr = json_tokener_get_error(tok);

    if (json_tokener_success != jerr) {

      res->errorResponse = apr_psprintf(r->pool, jsonErrorResponse,
                                        "malformed payload",
                                        json_tokener_error_desc(jerr));
      json_tokener_free(tok);
      return res;
    }

    ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r,
                  ERRTAG
                  "Assertion (parsed) recieved is : %s",
                  json_object_to_json_string(jobj));
  }
  else {
    // XXX: verifyAssertionRemote should return specific error message.
    res->errorResponse = apr_psprintf(r->pool, jsonErrorResponse,
                                      "communication error",
                                      "can't contact verification server");
    return res;
  }

  struct json_object_iterator it = json_object_iter_begin(jobj);
  struct json_object_iterator itEnd = json_object_iter_end(jobj);
  const char *reason = NULL;
  const char *status = "unknown";
  int success = 0;

  while (!json_object_iter_equal(&it, &itEnd)) {
    const char *key = json_object_iter_peek_name(&it);
    json_object *val = json_object_iter_peek_value(&it);

    if (strncmp("email", key, 6) == 0) {
      res->verifiedEmail = apr_pstrdup(r->pool, json_object_get_string(val));
    }
    else if (strncmp("issuer", key, 7) == 0) {
      res->identityIssuer = apr_pstrdup(r->pool, json_object_get_string(val));
    }
    else if (strncmp("audience", key, 9) == 0) {
      res->audience = apr_pstrdup(r->pool, json_object_get_string(val));
    }
    else if (strncmp("expires", key, 8) == 0) {
      apr_time_ansi_put(&res->expires, json_object_get_int64(val) / 1000);
    }
    else if (strncmp("reason", key, 7) == 0) {
      reason = json_object_get_string(val);
    }
    else if (strncmp("status", key, 7) == 0) {
      status = json_object_get_string(val);
      if (strncmp("okay", status, 5) == 0) {
        success = 1;
      }
    }
    json_object_iter_next(&it);
  }

  json_tokener_free(tok);

  // XXX: This is bad, doesn't catch multiple missing bits
  if (!res->verifiedEmail) {
    res->errorResponse = apr_pstrdup(r->pool, "Missing e-mail in assertion");
  }
  if (!res->identityIssuer) {
    res->errorResponse = apr_pstrdup(r->pool, "Missing issuer in assertion");
  }
  if (res->audience
      && strncmp(res->audience, r->server->server_hostname,
                 strlen(r->server->server_hostname)) != 0) {
    res->errorResponse =
      apr_psprintf(r->pool, "Audience %s doesn't match %s", res->audience,
                   r->server->server_hostname);
  }

  apr_time_t now = apr_time_now();
  if (res->expires && res->expires <= now) {
    char exp_time[APR_RFC822_DATE_LEN];
    apr_rfc822_date(exp_time, res->expires);
    res->errorResponse =
      apr_psprintf(r->pool, "Assertion expired on %s", exp_time);
  }

  if (!success) {
    if (reason) {
      res->errorResponse = apr_pstrdup(r->pool, reason);
    }
    else {
      res->errorResponse =
        apr_psprintf(r->pool, "Assertion failed with status '%s'", status);
    }
  }

  return res;
}
コード例 #11
0
ファイル: chxj_google.c プロジェクト: atkonn/mod_chxj
static void
s_track_page_view(request_rec *r)
{
  apr_time_t timestamp = apr_time_now();
  char *domain_name = NULL;
  char *document_referer = NULL;
  char *document_path = NULL;
  char *args;
  char *pstate;
  char *vstate;
  char *dates;
  char *account;
  char *user_agent;
  char *pair;
  char *name;
  char *value;
  char *guid_header = NULL;
  char *visitor_id = NULL;
  int utmdebug = 0;
  int ii;
  apr_array_header_t *headers = NULL;
  apr_table_entry_t *hentryp = NULL;
  char *cookie_str = NULL;
  char *utmUrl = NULL;


  DBG(r, "REQ[%X] start %s()", TO_ADDR(r),__func__);

  domain_name = (char *)apr_table_get(r->headers_in, "Host");
  if (domain_name == NULL || *domain_name == '\0') {
    domain_name = "";
  }

  args = r->args ? apr_pstrdup(r->pool, r->args) : "";

  for (;;) {
    char *pair_sv;

    pair = apr_strtok(args, "&", &pstate);
    if (pair == NULL)
      break;

    args = NULL;

    pair_sv = apr_pstrdup(r->pool, pair);

    name  = apr_strtok(pair, "=", &vstate);
    value = apr_strtok(NULL, "=", &vstate);
    if (! name) continue;
    if (STRCASEEQ('u','U',"utmr",name)) {
      if (value && *value && strcmp(value, "0") != 0) {
        document_referer = chxj_url_decode(r->pool, value);
      }
      else {
        document_referer = "-";
      }
    }
    else if (STRCASEEQ('u','U',"utmp",name)) {
      if (value && *value) {
        document_path = chxj_url_decode(r->pool, value);
      }
      else {
        document_path = "";
      }
    }
    else if (STRCASEEQ('u','U',"utmac",name)) {
      if (value && *value) {
        account = value;
      }
      else {
        ERR(r, "why not set account? - [%s]", r->args);
      }
    }
    else if (STRCASEEQ('u','U',"utmdebug",name)) {
      utmdebug = 1;
    }
  }
  user_agent = (char *)apr_table_get(r->headers_in,"User-Agent");
  if (!user_agent || *user_agent == '\0') {
    user_agent = "";
  }

  headers = (apr_array_header_t*)apr_table_elts(r->headers_in);
  hentryp = (apr_table_entry_t*)headers->elts;

  cookie_str = NULL;
  for (ii=0; ii<headers->nelts; ii++) {
    if (strcasecmp(hentryp[ii].key, "Cookie") == 0) {
      DBG(r,"REQ[%X] FOUND Cookie:[%s]",TO_ADDR(r),hentryp[ii].val);
      char *val = hentryp[ii].val;
      for (;;) {
        char *pair_sv = NULL;
        pair = apr_strtok(val, ";", &pstate);
        if (pair == NULL) break;
        val = NULL;
        pair_sv = apr_pstrdup(r->pool, pair);
        name = apr_strtok(pair, "=", &vstate);
        value = apr_strtok(NULL, "=", &vstate);
        if (! name) continue;
        if (strcasecmp(DL_COOKIE_NAME, name) == 0) {
          cookie_str = apr_pstrdup(r->pool, value);
          break;
        }
      }
    }
  }
  
  guid_header = (char *)apr_table_get(r->headers_in, "X-DCMGUID");
  if (!guid_header || *guid_header == 0) {
    guid_header = (char *)apr_table_get(r->headers_in, "X-UP-SUBNO");
  }
  if (!guid_header || *guid_header == 0) {
    guid_header = (char *)apr_table_get(r->headers_in, "X-JPHONE-UID");
  }
  if (!guid_header || *guid_header == 0) {
    guid_header = (char *)apr_table_get(r->headers_in, "X-EM-UID");
  }
  visitor_id = s_get_visitor_id(r, guid_header, account, user_agent, cookie_str);

  dates = apr_pcalloc(r->pool, MAX_STRING_LEN);
  apr_rfc822_date(dates, timestamp + DL_COOKIE_USER_PERSISTENCE);
  apr_table_setn(r->headers_out, "Set-Cookie",apr_psprintf(r->pool, "%s=%s; expires=%s; path=%s", DL_COOKIE_NAME,visitor_id, dates, DL_COOKIE_PATH));


  utmUrl = apr_pstrdup(r->pool, DL_UTM_GIF_LOCATION);
  utmUrl = apr_pstrcat(r->pool, utmUrl, "?", NULL);
  utmUrl = apr_pstrcat(r->pool, utmUrl, "utmwv=", DL_VERSION, NULL);
  srand(time(0));
  utmUrl = apr_pstrcat(r->pool, utmUrl, "&utmn=", apr_psprintf(r->pool, "%d", rand()), NULL);
  utmUrl = apr_pstrcat(r->pool, utmUrl, "&utmhn=", chxj_url_encode(r->pool, domain_name), NULL);
  utmUrl = apr_pstrcat(r->pool, utmUrl, "&utmr=", chxj_url_encode(r->pool, document_referer), NULL);
  utmUrl = apr_pstrcat(r->pool, utmUrl, "&utmp=", chxj_url_encode(r->pool, document_path), NULL);
  utmUrl = apr_pstrcat(r->pool, utmUrl, "&utmac=", account, NULL);
  utmUrl = apr_pstrcat(r->pool, utmUrl, "&utmcc=__utma%3D999.999.999.999.999.1%3B", NULL);
  utmUrl = apr_pstrcat(r->pool, utmUrl, "&utmvid=", visitor_id, NULL);
  utmUrl = apr_pstrcat(r->pool, utmUrl, "&utmip=", s_get_ip(r,r->connection->remote_ip), NULL);

  DBG(r, "REQ[%X] utmUrl:[%s]", TO_ADDR(r), utmUrl);

  s_send_request_to_google_analytics(r, utmUrl);

  if (utmdebug) {
    apr_table_setn(r->headers_out, "X-GA-MOBILE-URL", utmUrl);
  }

  s_write_gif_data(r);
  DBG(r, "REQ[%X] end %s()", TO_ADDR(r),__func__);
}
コード例 #12
0
ファイル: pass_reply.c プロジェクト: asyr625/tinia
int
trell_pass_reply( void*         data,
                  const char*   buffer,
                  const size_t  buffer_bytes,
                  const int     part,
                  const int     more )
{
    tinia_pass_reply_data_t* cbd = (tinia_pass_reply_data_t*)data;
    
    tinia_msg_t* msg = (tinia_msg_t*)buffer;

    size_t offset = 0;
    if( part == 0 ) {
        cbd->bytes_sent = 0;
        
        if( msg->type == TRELL_MESSAGE_OK ) {
            if( cbd->longpolling ) {
                return 1;               // wait for notification.
            }
            else {
                return 0;               // ok
            }
        }
        if( msg->type == TRELL_MESSAGE_OK ) {
            return -1;                  // error
        }
        else if( msg->type == TRELL_MESSAGE_XML ) {
            ap_set_content_type( cbd->r, "application/xml" );
            offset = sizeof(tinia_msg_xml_t);
        }
        else if( msg->type == TRELL_MESSAGE_SCRIPT ) {
            ap_set_content_type( cbd->r, "application/javascript" );
            offset = sizeof(*msg);
        }
        else {
            ap_log_rerror( APLOG_MARK, APLOG_NOTICE, 0, cbd->r,
                           "trell_pass_reply: Unexpected message type %d of size %d (%s).",
                           (int)msg->type, (int)buffer_bytes, cbd->r->path_info );
            return -1;                  // error
        }

        char* datestring = apr_palloc( cbd->r->pool, APR_RFC822_DATE_LEN );
        apr_rfc822_date( datestring, apr_time_now() );
        apr_table_setn( cbd->r->headers_out, "Last-Modified", datestring );
        apr_table_setn( cbd->r->headers_out, "Cache-Control", "no-cache" );
        
        cbd->brigade = apr_brigade_create( cbd->r->pool, cbd->r->connection->bucket_alloc );
    }

    if( offset < buffer_bytes ) {
        size_t payload_bytes = buffer_bytes-offset;
        apr_bucket* b = apr_bucket_transient_create( buffer + offset,
                                                     payload_bytes,
                                                     cbd->brigade->bucket_alloc );
        cbd->bytes_sent += payload_bytes;
        APR_BRIGADE_INSERT_TAIL( cbd->brigade, b );
    }    

    if( !more ) {
        APR_BRIGADE_INSERT_TAIL( cbd->brigade, apr_bucket_eos_create( cbd->brigade->bucket_alloc ) );
    }

    apr_status_t rv = ap_pass_brigade( cbd->r->output_filters, cbd->brigade );
    if( rv != APR_SUCCESS ) {
        ap_log_rerror( APLOG_MARK, APLOG_ERR, rv, cbd->r,
                       "trell_pass_reply: Failed to pass brigade." );
        return -1;                  // error
    }
    
    if( more ) {
        rv = apr_brigade_cleanup( cbd->brigade );
        if( rv != APR_SUCCESS ) {
            ap_log_rerror( APLOG_MARK, APLOG_ERR, rv, cbd->r,
                           "trell_pass_reply: apr_brigade_cleanup failed. " );
            return -1;                  // error
        }
    }
    else {
        rv = apr_brigade_destroy( cbd->brigade );
        if( rv != APR_SUCCESS ) {
            ap_log_rerror( APLOG_MARK, APLOG_ERR, rv, cbd->r,
                           "trell_pass_reply: apr_brigade_destroy failed. " );
            return -1;                  // error
        }
        ap_log_rerror( APLOG_MARK, APLOG_NOTICE, rv, cbd->r,
                       "%s: sent %ld bytes of %s. ", __func__, cbd->bytes_sent, cbd->r->content_type );
    }
    return 0;   // ok
}