Ejemplo n.º 1
0
svn_error_t *
svn_sqlite__open(svn_sqlite__db_t **db, const char *path,
                 svn_sqlite__mode_t mode, const char * const statements[],
                 int unused1, const char * const *unused2,
                 apr_pool_t *result_pool, apr_pool_t *scratch_pool)
{
  SVN_ERR(svn_atomic__init_once(&sqlite_init_state,
                                init_sqlite, NULL, scratch_pool));

  *db = apr_pcalloc(result_pool, sizeof(**db));

  SVN_ERR(internal_open(&(*db)->db3, path, mode, scratch_pool));

#ifdef SQLITE3_DEBUG
  sqlite3_trace((*db)->db3, sqlite_tracer, (*db)->db3);
#endif
#ifdef SQLITE3_PROFILE
  sqlite3_profile((*db)->db3, sqlite_profiler, (*db)->db3);
#endif

  /* Work around a bug in SQLite 3.7.7.  The bug was fixed in SQLite 3.7.7.1.

     See:

       Date: Sun, 26 Jun 2011 18:52:14 -0400
       From: Richard Hipp <*****@*****.**>
       To: General Discussion of SQLite Database <*****@*****.**>
       Cc: [email protected]
       Subject: Re: [sqlite] PRAGMA bug in 3.7.7 (but fine in 3.7.6.3)
       Message-ID: <*****@*****.**>
   */
  {
    int ignored_err = SQLITE_OK;
#if !SQLITE_VERSION_AT_LEAST(3,7,8) && defined(SQLITE_SCHEMA)
    if (!strcmp(sqlite3_libversion(), "3.7.7"))
      ignored_err = SQLITE_SCHEMA;
#endif

    SVN_ERR(exec_sql2(*db, "PRAGMA case_sensitive_like=1;", ignored_err));
  }

  SVN_ERR(exec_sql(*db,
              /* Disable synchronization to disable the explicit disk flushes
                 that make Sqlite up to 50 times slower; especially on small
                 transactions.

                 This removes some stability guarantees on specific hardware
                 and power failures, but still guarantees atomic commits on
                 application crashes. With our dependency on external data
                 like pristine files (Wc) and revision files (repository),
                 we can't keep up these additional guarantees anyway.

                 ### Maybe switch to NORMAL(1) when we use larger transaction
                     scopes */
              "PRAGMA synchronous=OFF;"
              /* Enable recursive triggers so that a user trigger will fire
                 in the deletion phase of an INSERT OR REPLACE statement.
                 Requires SQLite >= 3.6.18  */
              "PRAGMA recursive_triggers=ON;"));

#if SQLITE_VERSION_AT_LEAST(3,6,19) && defined(SVN_DEBUG)
  /* When running in debug mode, enable the checking of foreign key
     constraints.  This has possible performance implications, so we don't
     bother to do it for production...for now. */
  SVN_ERR(exec_sql(*db, "PRAGMA foreign_keys=ON;"));
#endif

  /* Store temporary tables in RAM instead of in temporary files, but don't
     fail on this if this option is disabled in the sqlite compilation by
     setting SQLITE_TEMP_STORE to 0 (always to disk) */
  svn_error_clear(exec_sql(*db, "PRAGMA temp_store = MEMORY;"));

  /* Store the provided statements. */
  if (statements)
    {
      (*db)->statement_strings = statements;
      (*db)->nbr_statements = 0;
      while (*statements != NULL)
        {
          statements++;
          (*db)->nbr_statements++;
        }
      (*db)->prepared_stmts = apr_pcalloc(result_pool, (*db)->nbr_statements
                                                * sizeof(svn_sqlite__stmt_t *));
    }
  else
    (*db)->nbr_statements = 0;

  (*db)->state_pool = result_pool;
  apr_pool_cleanup_register(result_pool, *db, close_apr, apr_pool_cleanup_null);

  return SVN_NO_ERROR;
}
Ejemplo n.º 2
0
svn_error_t *
svn_repos_get_commit_editor5(const svn_delta_editor_t **editor,
                             void **edit_baton,
                             svn_repos_t *repos,
                             svn_fs_txn_t *txn,
                             const char *repos_url_decoded,
                             const char *base_path,
                             apr_hash_t *revprop_table,
                             svn_commit_callback2_t commit_callback,
                             void *commit_baton,
                             svn_repos_authz_callback_t authz_callback,
                             void *authz_baton,
                             apr_pool_t *pool)
{
  svn_delta_editor_t *e;
  apr_pool_t *subpool = svn_pool_create(pool);
  struct edit_baton *eb;
  svn_delta_shim_callbacks_t *shim_callbacks =
                                    svn_delta_shim_callbacks_default(pool);
  const char *repos_url = svn_path_uri_encode(repos_url_decoded, pool);

  /* Do a global authz access lookup.  Users with no write access
     whatsoever to the repository don't get a commit editor. */
  if (authz_callback)
    {
      svn_boolean_t allowed;

      SVN_ERR(authz_callback(svn_authz_write, &allowed, NULL, NULL,
                             authz_baton, pool));
      if (!allowed)
        return svn_error_create(SVN_ERR_AUTHZ_UNWRITABLE, NULL,
                                "Not authorized to open a commit editor.");
    }

  /* Allocate the structures. */
  e = svn_delta_default_editor(pool);
  eb = apr_pcalloc(subpool, sizeof(*eb));

  /* Set up the editor. */
  e->open_root         = open_root;
  e->delete_entry      = delete_entry;
  e->add_directory     = add_directory;
  e->open_directory    = open_directory;
  e->change_dir_prop   = change_dir_prop;
  e->add_file          = add_file;
  e->open_file         = open_file;
  e->close_file        = close_file;
  e->apply_textdelta   = apply_textdelta;
  e->change_file_prop  = change_file_prop;
  e->close_edit        = close_edit;
  e->abort_edit        = abort_edit;

  /* Set up the edit baton. */
  eb->pool = subpool;
  eb->revprop_table = svn_prop_hash_dup(revprop_table, subpool);
  eb->commit_callback = commit_callback;
  eb->commit_callback_baton = commit_baton;
  eb->authz_callback = authz_callback;
  eb->authz_baton = authz_baton;
  eb->base_path = svn_fspath__canonicalize(base_path, subpool);
  eb->repos = repos;
  eb->repos_url_decoded = repos_url_decoded;
  eb->repos_name = svn_dirent_basename(svn_repos_path(repos, subpool),
                                       subpool);
  eb->fs = svn_repos_fs(repos);
  eb->txn = txn;
  eb->txn_owner = txn == NULL;

  *edit_baton = eb;
  *editor = e;

  shim_callbacks->fetch_props_func = fetch_props_func;
  shim_callbacks->fetch_kind_func = fetch_kind_func;
  shim_callbacks->fetch_base_func = fetch_base_func;
  shim_callbacks->fetch_baton = eb;

  SVN_ERR(svn_editor__insert_shims(editor, edit_baton, *editor, *edit_baton,
                                   repos_url, eb->base_path,
                                   shim_callbacks, pool, pool));

  return SVN_NO_ERROR;
}
Ejemplo n.º 3
0
DAV_DECLARE_NONSTD(void) dav_prop_exec(dav_prop_ctx *ctx)
{
    dav_propdb *propdb = ctx->propdb;
    dav_error *err = NULL;
    dav_elem_private *priv = ctx->prop->priv;

    ctx->rollback = apr_pcalloc(propdb->p, sizeof(*ctx->rollback));

    if (ctx->is_liveprop) {
        err = (*priv->provider->patch_exec)(propdb->resource,
                                            ctx->prop, ctx->operation,
                                            ctx->liveprop_ctx,
                                            &ctx->rollback->liveprop);
    }
    else {
        dav_prop_name name;

        if (ctx->prop->ns == APR_XML_NS_NONE)
            name.ns = "";
        else
            name.ns = APR_XML_GET_URI_ITEM(propdb->ns_xlate, ctx->prop->ns);
        name.name = ctx->prop->name;

        /* save the old value so that we can do a rollback. */
        if ((err = (*propdb->db_hooks
                    ->get_rollback)(propdb->db, &name,
                                    &ctx->rollback->deadprop)) != NULL)
            goto error;

        if (ctx->operation == DAV_PROP_OP_SET) {

            /* Note: propdb->mapping was set in dav_prop_validate() */
            err = (*propdb->db_hooks->store)(propdb->db, &name, ctx->prop,
                                             propdb->mapping);

            /*
            ** If an error occurred, then assume that we didn't change the
            ** value. Remove the rollback item so that we don't try to set
            ** its value during the rollback.
            */
            /* ### euh... where is the removal? */
        }
        else if (ctx->operation == DAV_PROP_OP_DELETE) {

            /*
            ** Delete the property. Ignore errors -- the property is there, or
            ** we are deleting it for a second time.
            */
            /* ### but what about other errors? */
            (void) (*propdb->db_hooks->remove)(propdb->db, &name);
        }
    }

  error:
    /* push a more specific error here */
    if (err != NULL) {
        /*
        ** Use HTTP_INTERNAL_SERVER_ERROR because we shouldn't have seen
        ** any errors at this point.
        */
        ctx->err = dav_push_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR,
                                  DAV_ERR_PROP_EXEC,
                                  "Could not execute PROPPATCH.", err);
    }
}
Ejemplo n.º 4
0
void _mapcache_imageio_png_decode_to_image(mapcache_context *ctx, mapcache_buffer *buffer,
      mapcache_image *img) {
   int bit_depth,color_type,i;
   unsigned char **row_pointers;
   png_structp png_ptr = NULL;
   png_infop info_ptr = NULL;
   _mapcache_buffer_closure b;
   b.buffer = buffer;
   b.ptr = buffer->buf;
   png_uint_32 width, height;


   /* could pass pointers to user-defined error handlers instead of NULLs: */
   png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
   if (!png_ptr) {
      ctx->set_error(ctx, 500, "failed to allocate png_struct structure");
      return;
   }

   info_ptr = png_create_info_struct(png_ptr);
   if (!info_ptr)
   {
      png_destroy_read_struct(&png_ptr, NULL, NULL);
      ctx->set_error(ctx, 500, "failed to allocate png_info structure");
      return;
   }

   if (setjmp(png_jmpbuf(png_ptr)))
   {
      ctx->set_error(ctx, 500, "failed to setjmp(png_jmpbuf(png_ptr))");
      png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
      return;
   }
   png_set_read_fn(png_ptr,&b,_mapcache_imageio_png_read_func);

   png_read_info(png_ptr,info_ptr);
   if(!png_get_IHDR(png_ptr, info_ptr, &width, &height,&bit_depth, &color_type,NULL,NULL,NULL)) {
      ctx->set_error(ctx, 500, "failed to read png header");
      return;
   }

   img->w = width;
   img->h = height;
   if(!img->data) {
      img->data = calloc(1,img->w*img->h*4*sizeof(unsigned char));
      apr_pool_cleanup_register(ctx->pool, img->data, (void*)free, apr_pool_cleanup_null) ;
      img->stride = img->w * 4;
   }
   row_pointers = apr_pcalloc(ctx->pool,img->h * sizeof(unsigned char*));

   unsigned char *rowptr = img->data;
   for(i=0;i<img->h;i++) {
      row_pointers[i] = rowptr;
      rowptr += img->stride;
   }


   png_set_expand(png_ptr);
   png_set_strip_16(png_ptr);
   png_set_gray_to_rgb(png_ptr);
   png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);
   
   png_read_update_info(png_ptr, info_ptr);

   png_read_image(png_ptr, row_pointers);
   
   png_read_end(png_ptr,NULL);
   png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
}
Ejemplo n.º 5
0
void child_main(apr_pool_t *pconf)
{
    apr_status_t status;
    apr_hash_t *ht;
    ap_listen_rec *lr;
    HANDLE child_events[2];
    HANDLE *child_handles;
    int listener_started = 0;
    int threads_created = 0;
    int watch_thread;
    int time_remains;
    int cld;
    DWORD tid;
    int rv;
    int i;

    apr_pool_create(&pchild, pconf);
    apr_pool_tag(pchild, "pchild");

    ap_run_child_init(pchild, ap_server_conf);
    ht = apr_hash_make(pchild);

    /* Initialize the child_events */
    max_requests_per_child_event = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (!max_requests_per_child_event) {
        ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf, APLOGNO(00350)
                     "Child: Failed to create a max_requests event.");
        exit(APEXIT_CHILDINIT);
    }
    child_events[0] = exit_event;
    child_events[1] = max_requests_per_child_event;

    /*
     * Wait until we have permission to start accepting connections.
     * start_mutex is used to ensure that only one child ever
     * goes into the listen/accept loop at once.
     */
    status = apr_proc_mutex_lock(start_mutex);
    if (status != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_ERR, status, ap_server_conf, APLOGNO(00351)
                     "Child: Failed to acquire the start_mutex. "
                     "Process will exit.");
        exit(APEXIT_CHILDINIT);
    }
    ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ap_server_conf, APLOGNO(00352)
                 "Child: Acquired the start mutex.");

    /*
     * Create the worker thread dispatch IOCompletionPort
     */
    /* Create the worker thread dispatch IOCP */
    ThreadDispatchIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE,
                                                NULL, 0, 0);
    apr_thread_mutex_create(&qlock, APR_THREAD_MUTEX_DEFAULT, pchild);
    qwait_event = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (!qwait_event) {
        ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(),
                     ap_server_conf, APLOGNO(00353)
                     "Child: Failed to create a qwait event.");
        exit(APEXIT_CHILDINIT);
    }

    /*
     * Create the pool of worker threads
     */
    ap_log_error(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS, ap_server_conf, APLOGNO(00354)
                 "Child: Starting %d worker threads.", ap_threads_per_child);
    child_handles = (HANDLE) apr_pcalloc(pchild, ap_threads_per_child
                                                  * sizeof(HANDLE));
    apr_thread_mutex_create(&child_lock, APR_THREAD_MUTEX_DEFAULT, pchild);

    while (1) {
        for (i = 0; i < ap_threads_per_child; i++) {
            int *score_idx;
            int status = ap_scoreboard_image->servers[0][i].status;
            if (status != SERVER_GRACEFUL && status != SERVER_DEAD) {
                continue;
            }
            ap_update_child_status_from_indexes(0, i, SERVER_STARTING, NULL);

            child_handles[i] = CreateThread(NULL, ap_thread_stacksize,
                                            worker_main, (void *) i,
                                            stack_res_flag, &tid);
            if (child_handles[i] == 0) {
                ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(),
                             ap_server_conf, APLOGNO(00355)
                             "Child: CreateThread failed. Unable to "
                             "create all worker threads. Created %d of the %d "
                             "threads requested with the ThreadsPerChild "
                             "configuration directive.",
                             threads_created, ap_threads_per_child);
                ap_signal_parent(SIGNAL_PARENT_SHUTDOWN);
                goto shutdown;
            }
            threads_created++;
            /* Save the score board index in ht keyed to the thread handle.
             * We need this when cleaning up threads down below...
             */
            apr_thread_mutex_lock(child_lock);
            score_idx = apr_pcalloc(pchild, sizeof(int));
            *score_idx = i;
            apr_hash_set(ht, &child_handles[i], sizeof(HANDLE), score_idx);
            apr_thread_mutex_unlock(child_lock);
        }
        /* Start the listener only when workers are available */
        if (!listener_started && threads_created) {
            create_listener_thread();
            listener_started = 1;
            winnt_mpm_state = AP_MPMQ_RUNNING;
        }
        if (threads_created == ap_threads_per_child) {
            break;
        }
        /* Check to see if the child has been told to exit */
        if (WaitForSingleObject(exit_event, 0) != WAIT_TIMEOUT) {
            break;
        }
        /* wait for previous generation to clean up an entry in the scoreboard
         */
        apr_sleep(1 * APR_USEC_PER_SEC);
    }

    /* Wait for one of three events:
     * exit_event:
     *    The exit_event is signaled by the parent process to notify
     *    the child that it is time to exit.
     *
     * max_requests_per_child_event:
     *    This event is signaled by the worker threads to indicate that
     *    the process has handled MaxConnectionsPerChild connections.
     *
     * TIMEOUT:
     *    To do periodic maintenance on the server (check for thread exits,
     *    number of completion contexts, etc.)
     *
     * XXX: thread exits *aren't* being checked.
     *
     * XXX: other_child - we need the process handles to the other children
     *      in order to map them to apr_proc_other_child_read (which is not
     *      named well, it's more like a_p_o_c_died.)
     *
     * XXX: however - if we get a_p_o_c handle inheritance working, and
     *      the parent process creates other children and passes the pipes
     *      to our worker processes, then we have no business doing such
     *      things in the child_main loop, but should happen in master_main.
     */
    while (1) {
#if !APR_HAS_OTHER_CHILD
        rv = WaitForMultipleObjects(2, (HANDLE *)child_events, FALSE, INFINITE);
        cld = rv - WAIT_OBJECT_0;
#else
        rv = WaitForMultipleObjects(2, (HANDLE *)child_events, FALSE, 1000);
        cld = rv - WAIT_OBJECT_0;
        if (rv == WAIT_TIMEOUT) {
            apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING);
        }
        else
#endif
            if (rv == WAIT_FAILED) {
            /* Something serious is wrong */
            ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(),
                         ap_server_conf, APLOGNO(00356)
                         "Child: WAIT_FAILED -- shutting down server");
            break;
        }
        else if (cld == 0) {
            /* Exit event was signaled */
            ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ap_server_conf, APLOGNO(00357)
                         "Child: Exit event signaled. Child process is "
                         "ending.");
            break;
        }
        else {
            /* MaxConnectionsPerChild event set by the worker threads.
             * Signal the parent to restart
             */
            ap_log_error(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS, ap_server_conf, APLOGNO(00358)
                         "Child: Process exiting because it reached "
                         "MaxConnectionsPerChild. Signaling the parent to "
                         "restart a new child process.");
            ap_signal_parent(SIGNAL_PARENT_RESTART);
            break;
        }
    }

    /*
     * Time to shutdown the child process
     */

 shutdown:

    winnt_mpm_state = AP_MPMQ_STOPPING;

    /* Close the listening sockets. Note, we must close the listeners
     * before closing any accept sockets pending in AcceptEx to prevent
     * memory leaks in the kernel.
     */
    for (lr = ap_listeners; lr ; lr = lr->next) {
        apr_socket_close(lr->sd);
    }

    /* Shutdown listener threads and pending AcceptEx sockets
     * but allow the worker threads to continue consuming from
     * the queue of accepted connections.
     */
    shutdown_in_progress = 1;

    Sleep(1000);

    /* Tell the worker threads to exit */
    workers_may_exit = 1;

    /* Release the start_mutex to let the new process (in the restart
     * scenario) a chance to begin accepting and servicing requests
     */
    rv = apr_proc_mutex_unlock(start_mutex);
    if (rv == APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, ap_server_conf, APLOGNO(00359)
                     "Child: Released the start mutex");
    }
    else {
        ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(00360)
                     "Child: Failure releasing the start mutex");
    }

    /* Shutdown the worker threads
     * Post worker threads blocked on the ThreadDispatch IOCompletion port
     */
    while (g_blocked_threads > 0) {
        ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ap_server_conf, APLOGNO(00361)
                     "Child: %d threads blocked on the completion port",
                     g_blocked_threads);
        for (i=g_blocked_threads; i > 0; i--) {
            PostQueuedCompletionStatus(ThreadDispatchIOCP, 0,
                                       IOCP_SHUTDOWN, NULL);
        }
        Sleep(1000);
    }
    /* Empty the accept queue of completion contexts */
    apr_thread_mutex_lock(qlock);
    while (qhead) {
        CloseHandle(qhead->overlapped.hEvent);
        closesocket(qhead->accept_socket);
        qhead = qhead->next;
    }
    apr_thread_mutex_unlock(qlock);

    /* Give busy threads a chance to service their connections
     * (no more than the global server timeout period which
     * we track in msec remaining).
     */
    watch_thread = 0;
    time_remains = (int)(ap_server_conf->timeout / APR_TIME_C(1000));

    while (threads_created)
    {
        int nFailsafe = MAXIMUM_WAIT_OBJECTS;
        DWORD dwRet;

        /* Every time we roll over to wait on the first group
         * of MAXIMUM_WAIT_OBJECTS threads, take a breather,
         * and infrequently update the error log.
         */
        if (watch_thread >= threads_created) {
            if ((time_remains -= 100) < 0)
                break;

            /* Every 30 seconds give an update */
            if ((time_remains % 30000) == 0) {
                ap_log_error(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS,
                             ap_server_conf, APLOGNO(00362)
                             "Child: Waiting %d more seconds "
                             "for %d worker threads to finish.",
                             time_remains / 1000, threads_created);
            }
            /* We'll poll from the top, 10 times per second */
            Sleep(100);
            watch_thread = 0;
        }

        /* Fairness, on each iteration we will pick up with the thread
         * after the one we just removed, even if it's a single thread.
         * We don't block here.
         */
        dwRet = WaitForMultipleObjects(min(threads_created - watch_thread,
                                           MAXIMUM_WAIT_OBJECTS),
                                       child_handles + watch_thread, 0, 0);

        if (dwRet == WAIT_FAILED) {
            break;
        }
        if (dwRet == WAIT_TIMEOUT) {
            /* none ready */
            watch_thread += MAXIMUM_WAIT_OBJECTS;
            continue;
        }
        else if (dwRet >= WAIT_ABANDONED_0) {
            /* We just got the ownership of the object, which
             * should happen at most MAXIMUM_WAIT_OBJECTS times.
             * It does NOT mean that the object is signaled.
             */
            if ((nFailsafe--) < 1)
                break;
        }
        else {
            watch_thread += (dwRet - WAIT_OBJECT_0);
            if (watch_thread >= threads_created)
                break;
            cleanup_thread(child_handles, &threads_created, watch_thread);
        }
    }

    /* Kill remaining threads off the hard way */
    if (threads_created) {
        ap_log_error(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS, ap_server_conf, APLOGNO(00363)
                     "Child: Terminating %d threads that failed to exit.",
                     threads_created);
    }
    for (i = 0; i < threads_created; i++) {
        int *score_idx;
        TerminateThread(child_handles[i], 1);
        CloseHandle(child_handles[i]);
        /* Reset the scoreboard entry for the thread we just whacked */
        score_idx = apr_hash_get(ht, &child_handles[i], sizeof(HANDLE));
        if (score_idx) {
            ap_update_child_status_from_indexes(0, *score_idx, SERVER_DEAD, NULL);
        }
    }
    ap_log_error(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS, ap_server_conf, APLOGNO(00364)
                 "Child: All worker threads have exited.");

    apr_thread_mutex_destroy(child_lock);
    apr_thread_mutex_destroy(qlock);
    CloseHandle(qwait_event);

    apr_pool_destroy(pchild);
    CloseHandle(exit_event);
}
static dav_error * dav_generic_append_locks(dav_lockdb *lockdb,
                                            const dav_resource *resource,
                                            int make_indirect,
                                            const dav_lock *lock)
{
    apr_pool_t *p = lockdb->info->pool;
    dav_error *err;
    dav_lock_indirect *ip;
    dav_lock_discovery *dp;
    apr_datum_t key;

    key = dav_generic_build_key(lockdb->info->pool, resource);

    err = dav_generic_load_lock_record(lockdb, key, 0, &dp, &ip);
    if (err != NULL) {
        /* ### maybe add in a higher-level description */
        return err;
    }

    /*
     * ### when we store the lock more directly, we need to update
     * ### lock->rectype and lock->is_locknull
     */

    if (make_indirect) {
        for (; lock != NULL; lock = lock->next) {

            /* ### this works for any <lock> rectype */
            dav_lock_indirect *newi = apr_pcalloc(p, sizeof(*newi));

            /* ### shut off the const warning for now */
            newi->locktoken = (dav_locktoken *)lock->locktoken;
            newi->timeout   = lock->timeout;
            newi->key       = lock->info->key;
            newi->next      = ip;
            ip              = newi;
        }
    }
    else {
        for (; lock != NULL; lock = lock->next) {
            /* create and link in the right kind of lock */

            if (lock->rectype == DAV_LOCKREC_DIRECT) {
                dav_lock_discovery *newd = apr_pcalloc(p, sizeof(*newd));

                newd->f.scope = lock->scope;
                newd->f.type = lock->type;
                newd->f.depth = lock->depth;
                newd->f.timeout = lock->timeout;
                /* ### shut off the const warning for now */
                newd->locktoken = (dav_locktoken *)lock->locktoken;
                newd->owner = lock->owner;
                newd->auth_user = lock->auth_user;
                newd->next = dp;
                dp = newd;
            }
            else {
                /* DAV_LOCKREC_INDIRECT(_PARTIAL) */

                dav_lock_indirect *newi = apr_pcalloc(p, sizeof(*newi));

                /* ### shut off the const warning for now */
                newi->locktoken = (dav_locktoken *)lock->locktoken;
                newi->key       = lock->info->key;
                newi->next      = ip;
                ip              = newi;
            }
        }
    }

    if ((err = dav_generic_save_lock_record(lockdb, key, dp, ip)) != NULL) {
        /* ### maybe add a higher-level description */
        return err;
    }

    return NULL;
}
Ejemplo n.º 7
0
/**
 * This is the KEEP_BODY_INPUT filter for HTTP requests, for times when the
 * body should be set aside for future use by other modules.
 */
static apr_status_t keep_body_filter(ap_filter_t *f, apr_bucket_brigade *b,
                                     ap_input_mode_t mode,
                                     apr_read_type_e block,
                                     apr_off_t readbytes)
{
    apr_bucket *e;
    keep_body_ctx_t *ctx = f->ctx;
    apr_status_t rv;
    apr_bucket *bucket;
    apr_off_t len = 0;


    if (!ctx) {
        const char *lenp;
        char *endstr = NULL;
        request_dir_conf *dconf = ap_get_module_config(f->r->per_dir_config,
                                                       &request_module);

        /* must we step out of the way? */
        if (!dconf->keep_body || f->r->kept_body) {
            ap_remove_input_filter(f);
            return ap_get_brigade(f->next, b, mode, block, readbytes);
        }

        f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx));

        /* fail fast if the content length exceeds keep body */
        lenp = apr_table_get(f->r->headers_in, "Content-Length");
        if (lenp) {

            /* Protects against over/underflow, non-digit chars in the
             * string (excluding leading space) (the endstr checks)
             * and a negative number. */
            if (apr_strtoff(&ctx->remaining, lenp, &endstr, 10)
                || endstr == lenp || *endstr || ctx->remaining < 0) {

                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, APLOGNO(01411)
                              "Invalid Content-Length");

                ap_remove_input_filter(f);
                return bail_out_on_error(b, f, HTTP_REQUEST_ENTITY_TOO_LARGE);
            }

            /* If we have a limit in effect and we know the C-L ahead of
             * time, stop it here if it is invalid.
             */
            if (dconf->keep_body < ctx->remaining) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, APLOGNO(01412)
                          "Requested content-length of %" APR_OFF_T_FMT
                          " is larger than the configured limit"
                          " of %" APR_OFF_T_FMT, ctx->remaining, dconf->keep_body);
                ap_remove_input_filter(f);
                return bail_out_on_error(b, f, HTTP_REQUEST_ENTITY_TOO_LARGE);
            }

        }

        f->r->kept_body = apr_brigade_create(f->r->pool, f->r->connection->bucket_alloc);
        ctx->remaining = dconf->keep_body;

    }

    /* get the brigade from upstream, and read it in to get its length */
    rv = ap_get_brigade(f->next, b, mode, block, readbytes);
    if (rv == APR_SUCCESS) {
        rv = apr_brigade_length(b, 1, &len);
    }

    /* does the length take us over the limit? */
    if (APR_SUCCESS == rv && len > ctx->remaining) {
        if (f->r->kept_body) {
            apr_brigade_cleanup(f->r->kept_body);
            f->r->kept_body = NULL;
        }
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, APLOGNO(01413)
                      "Requested content-length of %" APR_OFF_T_FMT
                      " is larger than the configured limit"
                      " of %" APR_OFF_T_FMT, len, ctx->keep_body);
        return bail_out_on_error(b, f, HTTP_REQUEST_ENTITY_TOO_LARGE);
    }
    ctx->remaining -= len;

    /* pass any errors downstream */
    if (rv != APR_SUCCESS) {
        if (f->r->kept_body) {
            apr_brigade_cleanup(f->r->kept_body);
            f->r->kept_body = NULL;
        }
        return rv;
    }

    /* all is well, set aside the buckets */
    for (bucket = APR_BRIGADE_FIRST(b);
         bucket != APR_BRIGADE_SENTINEL(b);
         bucket = APR_BUCKET_NEXT(bucket))
    {
        apr_bucket_copy(bucket, &e);
        APR_BRIGADE_INSERT_TAIL(f->r->kept_body, e);
    }

    return APR_SUCCESS;
}
Ejemplo n.º 8
0
static void *authz_dbd_cr_cfg(apr_pool_t *pool, char *dummy)
{
    authz_dbd_cfg *ret = apr_pcalloc(pool, sizeof(authz_dbd_cfg));
    ret->redirect = -1;
    return ret;
}
Ejemplo n.º 9
0
static void *NonceFilterCreateServerConfig(apr_pool_t *p,server_rec *s)
{
	NonceFilterConfig *pConfig=apr_pcalloc(p,sizeof *pConfig);
	return pConfig;
}
/* retrieve ssl server CA failure overrides (if any) from servers
   config */
static svn_error_t *
ssl_server_trust_file_first_credentials(void **credentials,
                                        void **iter_baton,
                                        void *provider_baton,
                                        apr_hash_t *parameters,
                                        const char *realmstring,
                                        apr_pool_t *pool)
{
  apr_uint32_t *failures = apr_hash_get(parameters,
                                        SVN_AUTH_PARAM_SSL_SERVER_FAILURES,
                                        APR_HASH_KEY_STRING);
  const svn_auth_ssl_server_cert_info_t *cert_info =
    apr_hash_get(parameters,
                 SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO,
                 APR_HASH_KEY_STRING);
  apr_hash_t *creds_hash = NULL;
  const char *config_dir;
  svn_error_t *error = SVN_NO_ERROR;

  *credentials = NULL;
  *iter_baton = NULL;

  /* Check if this is a permanently accepted certificate */
  config_dir = apr_hash_get(parameters,
                            SVN_AUTH_PARAM_CONFIG_DIR,
                            APR_HASH_KEY_STRING);
  error =
    svn_config_read_auth_data(&creds_hash, SVN_AUTH_CRED_SSL_SERVER_TRUST,
                              realmstring, config_dir, pool);
  svn_error_clear(error);
  if (! error && creds_hash)
    {
      svn_string_t *trusted_cert, *this_cert, *failstr;
      apr_uint32_t last_failures = 0;

      trusted_cert = apr_hash_get(creds_hash, AUTHN_ASCII_CERT_KEY,
                                  APR_HASH_KEY_STRING);
      this_cert = svn_string_create(cert_info->ascii_cert, pool);
      failstr = apr_hash_get(creds_hash, AUTHN_FAILURES_KEY,
                             APR_HASH_KEY_STRING);

      if (failstr)
        {
          char *endptr;
          unsigned long tmp_ulong = strtoul(failstr->data, &endptr, 10);

          if (*endptr == '\0')
            last_failures = (apr_uint32_t) tmp_ulong;
        }

      /* If the cert is trusted and there are no new failures, we
       * accept it by clearing all failures. */
      if (trusted_cert &&
          svn_string_compare(this_cert, trusted_cert) &&
          (*failures & ~last_failures) == 0)
        {
          *failures = 0;
        }
    }

  /* If all failures are cleared now, we return the creds */
  if (! *failures)
    {
      svn_auth_cred_ssl_server_trust_t *creds =
        apr_pcalloc(pool, sizeof(*creds));
      creds->may_save = FALSE; /* No need to save it again... */
      *credentials = creds;
    }

  return SVN_NO_ERROR;
}
Ejemplo n.º 11
0
/* Recursively opens directories on the stack in EB, until LOCAL_ABSPATH
   is reached. If RECURSIVE_SKIP is TRUE, don't open LOCAL_ABSPATH itself,
   but create it marked with skip+skip_children.
 */
static svn_error_t *
ensure_state(struct diff_baton *eb,
             const char *local_abspath,
             svn_boolean_t recursive_skip,
             apr_pool_t *scratch_pool)
{
  struct node_state_t *ns;
  apr_pool_t *ns_pool;
  if (!eb->cur)
    {
      if (!svn_dirent_is_ancestor(eb->anchor_abspath, local_abspath))
        return SVN_NO_ERROR;

      SVN_ERR(ensure_state(eb,
                           svn_dirent_dirname(local_abspath,scratch_pool),
                           FALSE,
                           scratch_pool));
    }
  else if (svn_dirent_is_child(eb->cur->local_abspath, local_abspath, NULL))
    SVN_ERR(ensure_state(eb, svn_dirent_dirname(local_abspath,scratch_pool),
                         FALSE,
                         scratch_pool));
  else
    return SVN_NO_ERROR;

  if (eb->cur && eb->cur->skip_children)
    return SVN_NO_ERROR;

  ns_pool = svn_pool_create(eb->cur ? eb->cur->pool : eb->pool);
  ns = apr_pcalloc(ns_pool, sizeof(*ns));

  ns->pool = ns_pool;
  ns->local_abspath = apr_pstrdup(ns_pool, local_abspath);
  ns->relpath = svn_dirent_skip_ancestor(eb->anchor_abspath, ns->local_abspath);
  ns->parent = eb->cur;
  eb->cur = ns;

  if (recursive_skip)
    {
      ns->skip = TRUE;
      ns->skip_children = TRUE;
      return SVN_NO_ERROR;
    }

  {
    svn_revnum_t revision;
    svn_error_t *err;

    err = svn_wc__db_base_get_info(NULL, NULL, &revision, NULL, NULL, NULL,
                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                                   NULL, NULL, NULL,
                                   eb->db, local_abspath,
                                   scratch_pool, scratch_pool);

    if (err)
      {
        if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
          return svn_error_trace(err);
        svn_error_clear(err);

        revision = 0; /* Use original revision? */
      }
    ns->left_src = svn_diff__source_create(revision, ns->pool);
    ns->right_src = svn_diff__source_create(SVN_INVALID_REVNUM, ns->pool);

    SVN_ERR(eb->processor->dir_opened(&ns->baton, &ns->skip,
                                      &ns->skip_children,
                                      ns->relpath,
                                      ns->left_src,
                                      ns->right_src,
                                      NULL /* copyfrom_source */,
                                      ns->parent ? ns->parent->baton : NULL,
                                      eb->processor,
                                      ns->pool, scratch_pool));
  }

  return SVN_NO_ERROR;
}
Ejemplo n.º 12
0
static void *
create_server_config(apr_pool_t *p, server_rec *s)
{
  return apr_pcalloc(p, sizeof(server_conf_t));
}
Ejemplo n.º 13
0
static svn_error_t *
open_tunnel(svn_stream_t **request, svn_stream_t **response,
            svn_ra_close_tunnel_func_t *close_func, void **close_baton,
            void *tunnel_baton,
            const char *tunnel_name, const char *user,
            const char *hostname, int port,
            svn_cancel_func_t cancel_func, void *cancel_baton,
            apr_pool_t *pool)
{
  svn_node_kind_t kind;
  apr_proc_t *proc;
  apr_procattr_t *attr;
  apr_status_t status;
  const char *args[] = { "svnserve", "-t", "-r", ".", NULL };
  const char *svnserve;
  tunnel_baton_t *b = tunnel_baton;
  close_baton_t *cb;

  SVN_TEST_ASSERT(b->magic == TUNNEL_MAGIC);

  SVN_ERR(svn_dirent_get_absolute(&svnserve, "../../svnserve/svnserve", pool));
#ifdef WIN32
  svnserve = apr_pstrcat(pool, svnserve, ".exe", SVN_VA_NULL);
#endif
  SVN_ERR(svn_io_check_path(svnserve, &kind, pool));
  if (kind != svn_node_file)
    return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
                             "Could not find svnserve at %s",
                             svn_dirent_local_style(svnserve, pool));

  status = apr_procattr_create(&attr, pool);
  if (status == APR_SUCCESS)
    status = apr_procattr_io_set(attr, 1, 1, 0);
  if (status == APR_SUCCESS)
    status = apr_procattr_cmdtype_set(attr, APR_PROGRAM);
  proc = apr_palloc(pool, sizeof(*proc));
  if (status == APR_SUCCESS)
    status = apr_proc_create(proc,
                             svn_dirent_local_style(svnserve, pool),
                             args, NULL, attr, pool);
  if (status != APR_SUCCESS)
    return svn_error_wrap_apr(status, "Could not run svnserve");
  apr_pool_note_subprocess(pool, proc, APR_KILL_NEVER);

  /* APR pipe objects inherit by default.  But we don't want the
   * tunnel agent's pipes held open by future child processes
   * (such as other ra_svn sessions), so turn that off. */
  apr_file_inherit_unset(proc->in);
  apr_file_inherit_unset(proc->out);

  cb = apr_pcalloc(pool, sizeof(*cb));
  cb->magic = CLOSE_MAGIC;
  cb->tb = b;
  cb->proc = proc;

  *request = svn_stream_from_aprfile2(proc->in, FALSE, pool);
  *response = svn_stream_from_aprfile2(proc->out, FALSE, pool);
  *close_func = close_tunnel;
  *close_baton = cb;
  ++b->open_count;
  return SVN_NO_ERROR;
}
Ejemplo n.º 14
0
/* Depending on CREATE, create or open the environment and databases
   for filesystem FS in PATH. Use POOL for temporary allocations. */
static svn_error_t *
open_databases(svn_fs_t *fs,
               svn_boolean_t create,
               int format,
               const char *path,
               apr_pool_t *pool)
{
  base_fs_data_t *bfd;

  SVN_ERR(svn_fs__check_fs(fs, FALSE));

  bfd = apr_pcalloc(fs->pool, sizeof(*bfd));
  fs->vtable = &fs_vtable;
  fs->fsap_data = bfd;

  /* Initialize the fs's path. */
  fs->path = apr_pstrdup(fs->pool, path);

  if (create)
    SVN_ERR(bdb_write_config(fs));

  /* Create the Berkeley DB environment.  */
  {
    svn_error_t *err = svn_fs_bdb__open(&(bfd->bdb), path,
                                        SVN_BDB_STANDARD_ENV_FLAGS,
                                        0666, fs->pool);
    if (err)
      {
        if (create)
          return svn_error_createf
            (err->apr_err, err,
             _("Berkeley DB error for filesystem '%s'"
               " while creating environment:\n"),
             fs->path);
        else
          return svn_error_createf
            (err->apr_err, err,
             _("Berkeley DB error for filesystem '%s'"
               " while opening environment:\n"),
             fs->path);
      }
  }

  /* We must register the FS cleanup function *after* opening the
     environment, so that it's run before the environment baton
     cleanup. */
  apr_pool_cleanup_register(fs->pool, fs, cleanup_fs_apr,
                            apr_pool_cleanup_null);


  /* Create the databases in the environment.  */
  SVN_ERR(BDB_WRAP(fs, (create
                        ? "creating 'nodes' table"
                        : "opening 'nodes' table"),
                   svn_fs_bdb__open_nodes_table(&bfd->nodes,
                                                bfd->bdb->env,
                                                create)));
  SVN_ERR(BDB_WRAP(fs, (create
                        ? "creating 'revisions' table"
                        : "opening 'revisions' table"),
                   svn_fs_bdb__open_revisions_table(&bfd->revisions,
                                                    bfd->bdb->env,
                                                    create)));
  SVN_ERR(BDB_WRAP(fs, (create
                        ? "creating 'transactions' table"
                        : "opening 'transactions' table"),
                   svn_fs_bdb__open_transactions_table(&bfd->transactions,
                                                       bfd->bdb->env,
                                                       create)));
  SVN_ERR(BDB_WRAP(fs, (create
                        ? "creating 'copies' table"
                        : "opening 'copies' table"),
                   svn_fs_bdb__open_copies_table(&bfd->copies,
                                                 bfd->bdb->env,
                                                 create)));
  SVN_ERR(BDB_WRAP(fs, (create
                        ? "creating 'changes' table"
                        : "opening 'changes' table"),
                   svn_fs_bdb__open_changes_table(&bfd->changes,
                                                  bfd->bdb->env,
                                                  create)));
  SVN_ERR(BDB_WRAP(fs, (create
                        ? "creating 'representations' table"
                        : "opening 'representations' table"),
                   svn_fs_bdb__open_reps_table(&bfd->representations,
                                               bfd->bdb->env,
                                               create)));
  SVN_ERR(BDB_WRAP(fs, (create
                        ? "creating 'strings' table"
                        : "opening 'strings' table"),
                   svn_fs_bdb__open_strings_table(&bfd->strings,
                                                  bfd->bdb->env,
                                                  create)));
  SVN_ERR(BDB_WRAP(fs, (create
                        ? "creating 'uuids' table"
                        : "opening 'uuids' table"),
                   svn_fs_bdb__open_uuids_table(&bfd->uuids,
                                                bfd->bdb->env,
                                                create)));
  SVN_ERR(BDB_WRAP(fs, (create
                        ? "creating 'locks' table"
                        : "opening 'locks' table"),
                   svn_fs_bdb__open_locks_table(&bfd->locks,
                                                bfd->bdb->env,
                                                create)));
  SVN_ERR(BDB_WRAP(fs, (create
                        ? "creating 'lock-tokens' table"
                        : "opening 'lock-tokens' table"),
                   svn_fs_bdb__open_lock_tokens_table(&bfd->lock_tokens,
                                                      bfd->bdb->env,
                                                      create)));

  if (format >= SVN_FS_BASE__MIN_NODE_ORIGINS_FORMAT)
    {
      SVN_ERR(BDB_WRAP(fs, (create
                            ? "creating 'node-origins' table"
                            : "opening 'node-origins' table"),
                       svn_fs_bdb__open_node_origins_table(&bfd->node_origins,
                                                           bfd->bdb->env,
                                                           create)));
    }

  if (format >= SVN_FS_BASE__MIN_MISCELLANY_FORMAT)
    {
      SVN_ERR(BDB_WRAP(fs, (create
                            ? "creating 'miscellaneous' table"
                            : "opening 'miscellaneous' table"),
                       svn_fs_bdb__open_miscellaneous_table(&bfd->miscellaneous,
                                                            bfd->bdb->env,
                                                            create)));
    }

  if (format >= SVN_FS_BASE__MIN_REP_SHARING_FORMAT)
    {
      SVN_ERR(BDB_WRAP(fs, (create
                            ? "creating 'checksum-reps' table"
                            : "opening 'checksum-reps' table"),
                       svn_fs_bdb__open_checksum_reps_table(&bfd->checksum_reps,
                                                            bfd->bdb->env,
                                                            create)));
    }

  return SVN_NO_ERROR;
}
/*
 * dav_generic_save_lock_record:  Saves the lock information specified in the
 *    direct and indirect lock lists about path into the lock database.
 *    If direct and indirect == NULL, the key is removed.
 */
static dav_error * dav_generic_save_lock_record(dav_lockdb *lockdb,
                                                apr_datum_t key,
                                                dav_lock_discovery *direct,
                                                dav_lock_indirect *indirect)
{
    dav_error *err;
    apr_status_t status;
    apr_datum_t val = { 0 };
    char *ptr;
    dav_lock_discovery *dp = direct;
    dav_lock_indirect *ip = indirect;

#if DAV_DEBUG
    if (lockdb->ro) {
        return dav_new_error(lockdb->info->pool,
                             HTTP_INTERNAL_SERVER_ERROR, 0, 0,
                             "INTERNAL DESIGN ERROR: the lockdb was opened "
                             "readonly, but an attempt to save locks was "
                             "performed.");
    }
#endif

    if ((err = dav_generic_really_open_lockdb(lockdb)) != NULL) {
        /* ### add a higher-level error? */
        return err;
    }

    /* If nothing to save, delete key */
    if (dp == NULL && ip == NULL) {
        /* don't fail if the key is not present */
        /* ### but what about other errors? */
        apr_dbm_delete(lockdb->info->db, key);
        return NULL;
    }

    while(dp) {
        val.dsize += dav_size_direct(dp);
        dp = dp->next;
    }
    while(ip) {
        val.dsize += dav_size_indirect(ip);
        ip = ip->next;
    }

    /* ### can this be apr_palloc() ? */
    /* ### hmmm.... investigate the use of a buffer here */
    ptr = val.dptr = apr_pcalloc(lockdb->info->pool, val.dsize);
    dp  = direct;
    ip  = indirect;

    while(dp) {
        /* Direct lock - lock_discovery struct follows */
        *ptr++ = DAV_LOCK_DIRECT;
        memcpy(ptr, dp, sizeof(dp->f));        /* Fixed portion of struct */
        ptr += sizeof(dp->f);
        memcpy(ptr, dp->locktoken, sizeof(*dp->locktoken));
        ptr += sizeof(*dp->locktoken);
        if (dp->owner == NULL) {
            *ptr++ = '\0';
        }
        else {
            memcpy(ptr, dp->owner, strlen(dp->owner) + 1);
            ptr += strlen(dp->owner) + 1;
        }
        if (dp->auth_user == NULL) {
            *ptr++ = '\0';
        }
        else {
            memcpy(ptr, dp->auth_user, strlen(dp->auth_user) + 1);
            ptr += strlen(dp->auth_user) + 1;
        }

        dp = dp->next;
    }

    while(ip) {
        /* Indirect lock prefix */
        *ptr++ = DAV_LOCK_INDIRECT;

        memcpy(ptr, ip->locktoken, sizeof(*ip->locktoken));
        ptr += sizeof(*ip->locktoken);

        memcpy(ptr, &ip->timeout, sizeof(ip->timeout));
        ptr += sizeof(ip->timeout);

        memcpy(ptr, &ip->key.dsize, sizeof(ip->key.dsize));
        ptr += sizeof(ip->key.dsize);

        memcpy(ptr, ip->key.dptr, ip->key.dsize);
        ptr += ip->key.dsize;

        ip = ip->next;
    }

    if ((status = apr_dbm_store(lockdb->info->db, key, val)) != APR_SUCCESS) {
        /* ### more details? add an error_id? */
        err = dav_generic_dbm_new_error(lockdb->info->db, lockdb->info->pool,
                                        status);
        return dav_push_error(lockdb->info->pool,
                              HTTP_INTERNAL_SERVER_ERROR,
                              DAV_ERR_LOCK_SAVE_LOCK,
                              "Could not save lock information.",
                              err);
    }

    return NULL;
}
Ejemplo n.º 16
0
static svn_error_t *
inprocess_cache_set_internal(inprocess_cache_t *cache,
                             const void *key,
                             void *value,
                             apr_pool_t *scratch_pool)
{
  struct cache_entry *existing_entry;

  existing_entry = apr_hash_get(cache->hash, key, cache->klen);

  /* Is it already here, but we can do the one-item-per-page
   * optimization? */
  if (existing_entry && cache->items_per_page == 1)
    {
      /* Special case!  ENTRY is the *only* entry on this page, so
       * why not wipe it (so as not to leak the previous value).
       */
      struct cache_page *page = existing_entry->page;

      /* This can't be the partial page: items_per_page == 1
       * *never* has a partial page (except for in the temporary state
       * that we're about to fake). */
      SVN_ERR_ASSERT(page->next != NULL);
      SVN_ERR_ASSERT(cache->partial_page == NULL);

      erase_page(cache, page);
      existing_entry = NULL;
    }

  /* Is it already here, and we just have to leak the old value? */
  if (existing_entry)
    {
      struct cache_page *page = existing_entry->page;

      SVN_ERR(move_page_to_front(cache, page));
      cache->data_size -= existing_entry->size;
      if (value)
        {
          SVN_ERR(cache->serialize_func(&existing_entry->value,
                                        &existing_entry->size,
                                        value,
                                        page->page_pool));
          cache->data_size += existing_entry->size;
          if (existing_entry->size == 0)
            existing_entry->value = NULL;
        }
      else
        {
          existing_entry->value = NULL;
          existing_entry->size = 0;
        }

      return SVN_NO_ERROR;
    }

  /* Do we not have a partial page to put it on, but we are allowed to
   * allocate more? */
  if (cache->partial_page == NULL && cache->unallocated_pages > 0)
    {
      cache->partial_page = apr_pcalloc(cache->cache_pool,
                                        sizeof(*(cache->partial_page)));
      cache->partial_page->page_pool = svn_pool_create(cache->cache_pool);
      cache->partial_page_number_filled = 0;
      (cache->unallocated_pages)--;
    }

  /* Do we really not have a partial page to put it on, even after the
   * one-item-per-page optimization and checking the unallocated page
   * count? */
  if (cache->partial_page == NULL)
    {
      struct cache_page *oldest_page = cache->sentinel->prev;

      SVN_ERR_ASSERT(oldest_page != cache->sentinel);

      /* Erase the page and put it in cache->partial_page. */
      erase_page(cache, oldest_page);
    }

  SVN_ERR_ASSERT(cache->partial_page != NULL);

  {
    struct cache_page *page = cache->partial_page;
    struct cache_entry *new_entry = apr_pcalloc(page->page_pool,
                                                sizeof(*new_entry));

    /* Copy the key and value into the page's pool.  */
    new_entry->key = duplicate_key(cache, key, page->page_pool);
    if (value)
      {
        SVN_ERR(cache->serialize_func(&new_entry->value,
                                      &new_entry->size,
                                      value,
                                      page->page_pool));
        cache->data_size += new_entry->size;
        if (new_entry->size == 0)
          new_entry->value = NULL;
      }
    else
      {
        new_entry->value = NULL;
        new_entry->size = 0;
      }

    /* Add the entry to the page's list. */
    new_entry->page = page;
    new_entry->next_entry = page->first_entry;
    page->first_entry = new_entry;

    /* Add the entry to the hash, using the *entry's* copy of the
     * key. */
    apr_hash_set(cache->hash, new_entry->key, cache->klen, new_entry);

    /* We've added something else to the partial page. */
    (cache->partial_page_number_filled)++;

    /* Is it full? */
    if (cache->partial_page_number_filled >= cache->items_per_page)
      {
        insert_page(cache, page);
        cache->partial_page = NULL;
      }
  }

  return SVN_NO_ERROR;
}
/*
 * dav_load_lock_record:  Reads lock information about key from lock db;
 *    creates linked lists of the direct and indirect locks.
 *
 *    If add_method = DAV_APPEND_LIST, the result will be appended to the
 *    head of the direct and indirect lists supplied.
 *
 *    Passive lock removal:  If lock has timed out, it will not be returned.
 *    ### How much "logging" does RFC 2518 require?
 */
static dav_error * dav_generic_load_lock_record(dav_lockdb *lockdb,
                                                apr_datum_t key,
                                                int add_method,
                                                dav_lock_discovery **direct,
                                                dav_lock_indirect **indirect)
{
    apr_pool_t *p = lockdb->info->pool;
    dav_error *err;
    apr_status_t status;
    apr_size_t offset = 0;
    int need_save = DAV_FALSE;
    apr_datum_t val = { 0 };
    dav_lock_discovery *dp;
    dav_lock_indirect *ip;

    if (add_method != DAV_APPEND_LIST) {
        *direct = NULL;
        *indirect = NULL;
    }

    if ((err = dav_generic_really_open_lockdb(lockdb)) != NULL) {
        /* ### add a higher-level error? */
        return err;
    }

    /*
     * If we opened readonly and the db wasn't there, then there are no
     * locks for this resource. Just exit.
     */
    if (lockdb->info->db == NULL) {
        return NULL;
    }

    if ((status = apr_dbm_fetch(lockdb->info->db, key, &val)) != APR_SUCCESS) {
        return dav_generic_dbm_new_error(lockdb->info->db, p, status);
    }

    if (!val.dsize) {
        return NULL;
    }

    while (offset < val.dsize) {
        switch (*(val.dptr + offset++)) {
        case DAV_LOCK_DIRECT:
            /* Create and fill a dav_lock_discovery structure */

            dp = apr_pcalloc(p, sizeof(*dp));

            /* Copy the dav_lock_discovery_fixed portion */
            memcpy(dp, val.dptr + offset, sizeof(dp->f));
            offset += sizeof(dp->f);

            /* Copy the lock token. */
            dp->locktoken = apr_pmemdup(p, val.dptr + offset, sizeof(*dp->locktoken));
            offset += sizeof(*dp->locktoken);

            /* Do we have an owner field? */
            if (*(val.dptr + offset) == '\0') {
                ++offset;
            }
            else {
                apr_size_t len = strlen(val.dptr + offset);
                dp->owner = apr_pstrmemdup(p, val.dptr + offset, len);
                offset += len + 1;
            }

            if (*(val.dptr + offset) == '\0') {
                ++offset;
            }
            else {
                apr_size_t len = strlen(val.dptr + offset);
                dp->auth_user = apr_pstrmemdup(p, val.dptr + offset, len);
                offset += len + 1;
            }

            if (!dav_generic_lock_expired(dp->f.timeout)) {
                dp->next = *direct;
                *direct = dp;
            }
            else {
                need_save = DAV_TRUE;
            }
            break;

        case DAV_LOCK_INDIRECT:
            /* Create and fill a dav_lock_indirect structure */

            ip = apr_pcalloc(p, sizeof(*ip));
            ip->locktoken = apr_pmemdup(p, val.dptr + offset, sizeof(*ip->locktoken));
            offset += sizeof(*ip->locktoken);
            memcpy(&ip->timeout, val.dptr + offset, sizeof(ip->timeout));
            offset += sizeof(ip->timeout);
            /* length of datum */
            ip->key.dsize = *((int *) (val.dptr + offset));
            offset += sizeof(ip->key.dsize);
            ip->key.dptr = apr_pmemdup(p, val.dptr + offset, ip->key.dsize);
            offset += ip->key.dsize;

            if (!dav_generic_lock_expired(ip->timeout)) {
                ip->next = *indirect;
                *indirect = ip;
            }
            else {
                need_save = DAV_TRUE;
            }

            break;

        default:
            apr_dbm_freedatum(lockdb->info->db, val);

            /* ### should use a computed_desc and insert corrupt token data */
            --offset;
            return dav_new_error(p,
                                 HTTP_INTERNAL_SERVER_ERROR,
                                 DAV_ERR_LOCK_CORRUPT_DB, 0,
                                 apr_psprintf(p,
                                             "The lock database was found to "
                                             "be corrupt. offset %"
                                             APR_SIZE_T_FMT ", c=%02x",
                                             offset, val.dptr[offset]));
        }
    }

    apr_dbm_freedatum(lockdb->info->db, val);

    /* Clean up this record if we found expired locks */
    /*
     * ### shouldn't do this if we've been opened READONLY. elide the
     * ### timed-out locks from the response, but don't save that info back
     */
    if (need_save == DAV_TRUE) {
        return dav_generic_save_lock_record(lockdb, key, *direct, *indirect);
    }

    return NULL;
}
Ejemplo n.º 18
0
static dav_error *
dav_rawx_get_resource(request_rec *r, const char *root_dir, const char *label,
	int use_checked_in, dav_resource **result_resource)
{
	(void) use_checked_in;
	*result_resource = NULL;

	dav_rawx_server_conf *conf = request_get_server_config(r);

	/* Check if client allowed to work with us */
	if (conf->enabled_acl) {
#if MODULE_MAGIC_COOKIE == 0x41503234UL /* "AP24" */
		if (!authorized_personal_only(r->connection->client_ip, conf->rawx_conf->acl))
#else
		if (!authorized_personal_only(r->connection->remote_ip, conf->rawx_conf->acl))
#endif
		{
			return server_create_and_stat_error(conf, r->pool,
					HTTP_UNAUTHORIZED, 0, "Permission Denied (APO)");
		}
	}

	/* Create private resource context descriptor */
	dav_resource_private ctx = {0};
	ctx.pool = r->pool;
	ctx.request = r;

	dav_error *e = rawx_repo_check_request(r, root_dir, label, use_checked_in,
			&ctx, result_resource);
	/* Return in case we have an error or
	 * if result_resource != null because it was an info request */
	if (e || *result_resource) {
		return e;
	}

	/* Build the hashed path */
	if (conf->hash_width <= 0 || conf->hash_depth <= 0) {
		apr_snprintf(ctx.dirname, sizeof(ctx.dirname),
			"%.*s", (int)sizeof(conf->docroot), conf->docroot);
	} else {
		e = rawx_repo_configure_hash_dir(r, &ctx);
		if ( NULL != e) {
			return e;
		}
	}
	DAV_DEBUG_REQ(r, 0, "Hashed directory: %.*s", (int)sizeof(ctx.dirname), ctx.dirname);

	/* All the checks on the URL have passed, now build a resource */
	dav_resource *resource = apr_pcalloc(r->pool, sizeof(*resource));
	resource->type = DAV_RESOURCE_TYPE_REGULAR;
	resource->info = apr_pcalloc(r->pool, sizeof(ctx));;
	memcpy(resource->info, &ctx, sizeof(ctx));
	resource->hooks = &dav_hooks_repository_rawx;
	resource->pool = r->pool;
	memset(&(resource->info->comp_ctx), 0, sizeof(struct compression_ctx_s));

	resource->info->fullpath = apr_pstrcat(resource->pool,
		resource->info->dirname, resource->info->hex_chunkid,
		resource->info->file_extension,
		NULL);

	/* init compression context structure if we are in get method */
	if (r->method_number == M_GET && !ctx.update_only) {
		resource_init_decompression(resource, conf);
	}

	/* Check the chunk's existence */
	int flags = (r->method_number == M_GET ||
			r->method_number == M_OPTIONS ||
			r->method_number == M_DELETE)?
				 RESOURCE_STAT_CHUNK_READ_ATTRS : 0;
	if (r->method_number == M_PUT || r->method_number == M_POST)
		flags |= RESOURCE_STAT_CHUNK_PENDING;

	resource_stat_chunk(resource, flags);

	if (r->method_number == M_PUT || r->method_number == M_POST ||
			r->method_number == M_MOVE ||
			(r->method_number == M_GET && ctx.update_only)) {
		request_load_chunk_info_from_headers(r, &(resource->info->chunk));
		const char *missing = check_chunk_info(&resource->info->chunk);
		if (missing != NULL) {
			return server_create_and_stat_error(request_get_server_config(r), r->pool,
				HTTP_BAD_REQUEST, 0, apr_pstrcat(r->pool, "missing or invalid header ", missing, NULL));
		}
	}

	if (r->method_number == M_POST || r->method_number == M_PUT) {
		if (resource->info->chunk.chunk_id) {
			if (0 != apr_strnatcasecmp(resource->info->chunk.chunk_id, resource->info->hex_chunkid))
				return server_create_and_stat_error(request_get_server_config(r), r->pool,
						HTTP_BAD_REQUEST, 0, "chunk-id mismatch");
		}
		if (resource->exists)
			return server_create_and_stat_error(request_get_server_config(r), r->pool,
				HTTP_CONFLICT, 0, "Resource busy or already exists");
		request_parse_query(r, resource);
	}

	*result_resource = resource;
	return NULL;
}
Ejemplo n.º 19
0
/* TODO: cleanup ctx */
static apr_status_t
zlibdict_output_filter(ap_filter_t *f, apr_bucket_brigade *bb)
{
    apr_bucket *b;
    zlibdict_ctx_t *ctx = f->ctx;
    request_rec *r = f->r;
    const char *client_accepts;
    apr_status_t status = APR_SUCCESS;
    apr_pool_t *subpool;
    int zerr;

    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r,
                  "triggered zlibdict_output_filter");

    /* Do nothing if asked to filter nothing. */
    if (APR_BRIGADE_EMPTY(bb)) {
        return APR_SUCCESS;
    }

    /* First time we are called for this response? */
    if (!ctx) {
        client_accepts = apr_table_get(r->headers_in, "Accept-Encoding");
        if (client_accepts == NULL ||
            zlibdict__header_contains(r->pool, client_accepts)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                          "Not compressing (no Accept-Encoding: zlibdict)");
            ap_remove_output_filter(f);
            return ap_pass_brigade(f->next, bb);
        }

        ctx = f->ctx = apr_pcalloc(r->pool, sizeof(*ctx));
        ctx->bb = apr_brigade_create(r->pool, f->c->bucket_alloc);
        ctx->buf = apr_palloc(r->pool, DEFAULT_BUFFERSIZE);

        /* zstream must be NULL'd out. */
        memset(&ctx->zstr, 0, sizeof(z_stream));
        zerr = deflateInit2(&ctx->zstr, DEFAULT_COMPRESSION,
                            Z_DEFLATED,
                            DEFAULT_WINDOWSIZE, DEFAULT_MEMLEVEL,
                            Z_DEFAULT_STRATEGY);

        deflateSetDictionary(&ctx->zstr, (Bytef *)propfind_dictionary,
                             strlen(propfind_dictionary));

        /* Set Content-Encoding header so our client knows how to handle 
           this data. */
        apr_table_mergen(r->headers_out, "Content-Encoding", "zlibdict");
    }

    /* Read the data from the handler and compress it with a dictionary. */
    for (b = APR_BRIGADE_FIRST(bb);
         b != APR_BRIGADE_SENTINEL(bb);
         b = APR_BUCKET_NEXT(b)) {

        const char *data;
        void *write_buf;
        size_t len;
        size_t buf_size, write_len;

        if (APR_BUCKET_IS_EOS(b)) {
            deflateEnd(&ctx->zstr);

            /* Remove EOS from the old list, and insert into the new. */
            APR_BUCKET_REMOVE(b);
            APR_BRIGADE_INSERT_TAIL(ctx->bb, b);

            return ap_pass_brigade(f->next, ctx->bb);
        }

        if (APR_BUCKET_IS_METADATA(b))
            continue;

        status = apr_bucket_read(b, &data, &len, APR_BLOCK_READ);
        if (status != APR_SUCCESS)
            break;

        /* The largest buffer we should need is 0.1% larger than the
         compressed data, + 12 bytes. This info comes from zlib.h.  */
        buf_size = len + (len / 1000) + 13;
        apr_pool_create(&subpool, r->pool);
        write_buf = apr_palloc(subpool, buf_size);
        
        ctx->zstr.next_in = (Bytef *)data;  /* Casting away const! */
        ctx->zstr.avail_in = (uInt) len;

        zerr = Z_OK;
        while (ctx->zstr.avail_in > 0 && zerr != Z_STREAM_END)
        {
            ctx->zstr.next_out = write_buf;
            ctx->zstr.avail_out = (uInt) buf_size;

            zerr = deflate(&ctx->zstr, Z_FINISH);
            if (zerr < 0)
                return -1; /* TODO: fix error */
            write_len = buf_size - ctx->zstr.avail_out;
            if (write_len > 0) {
                apr_bucket *b_out;

                b_out = apr_bucket_heap_create(write_buf, len,
                                               NULL, f->c->bucket_alloc);
                APR_BRIGADE_INSERT_TAIL(ctx->bb, b_out);
                /* Send what we have right now to the next filter. */
                status = ap_pass_brigade(f->next, ctx->bb);
                if (status != APR_SUCCESS) {
                    apr_pool_destroy(subpool);
                    return status;
                }
            }

            apr_pool_destroy(subpool);
        }
    }
    
    return status;
}
Ejemplo n.º 20
0
static dav_error *
dav_rawx_write_stream(dav_stream *stream, const void *buf, apr_size_t bufsize)
{
	DAV_XDEBUG_POOL(stream->p, 0, "%s(%s)", __FUNCTION__, stream->pathname);

	guint written = 0;
	gulong checksum = stream->compress_checksum;

	while (written < bufsize) {
		memcpy(stream->buffer + stream->bufsize, buf + written, MIN(bufsize - written, stream->blocksize - stream->bufsize));
		guint tmp = MIN(bufsize - written, stream->blocksize - stream->bufsize);
		written += tmp;
		stream->bufsize += tmp;

		/* If buffer full, compress if needed and write to distant file */
		if (stream->blocksize - stream->bufsize <=0){
			gsize nb_write = 0;
			if (!stream->compression) {
				nb_write = fwrite(stream->buffer, stream->bufsize, 1, stream->f);
				if (nb_write != 1) {
					/* ### use something besides 500? */
					return server_create_and_stat_error(resource_get_server_config(stream->r), stream->p,
							HTTP_INTERNAL_SERVER_ERROR, 0,
							"An error occurred while writing to a "
							"resource.");
				}
			} else {
				GByteArray *gba = g_byte_array_new();
				if (stream->comp_ctx.data_compressor(stream->buffer, stream->bufsize, gba,
							&checksum)!=0) {
					if (gba)
						g_byte_array_free(gba, TRUE);
					/* ### use something besides 500? */
					return server_create_and_stat_error(resource_get_server_config(stream->r), stream->p,
							HTTP_INTERNAL_SERVER_ERROR, 0,
							"An error occurred while compressing data.");
				}
				nb_write = fwrite(gba->data, gba->len, 1, stream->f);
				if (nb_write != 1) {
					if (gba)
						g_byte_array_free(gba, TRUE);
					/* ### use something besides 500? */
					return server_create_and_stat_error(resource_get_server_config(stream->r), stream->p,
							HTTP_INTERNAL_SERVER_ERROR, 0,
							"An error occurred while writing to a "
							"resource.");
				}
				stream->compressed_size += gba->len;
				if (gba)
					g_byte_array_free(gba, TRUE);
			}

			stream->buffer = apr_pcalloc(stream->p, stream->blocksize);
			stream->bufsize = 0;
		}
	}

	stream->compress_checksum = checksum;

	/* update the hash and the stats */
	g_checksum_update(stream->md5, buf, bufsize);
	/* update total_size */
	stream->total_size += bufsize;
	return NULL;
}
Ejemplo n.º 21
0
/* Simple parser for the Sqlite textual explanation into an explanation_item.
   Writes "DBG:" lines when sqlite produces unexpected results. When no
   valid explanation_item can be parsed sets *PARSED_ITEM to NULL, otherwise
   to a valid result. */
static svn_error_t *
parse_explanation_item(struct explanation_item **parsed_item,
                       const char *text,
                       apr_pool_t *result_pool)
{
  struct explanation_item *item = apr_pcalloc(result_pool, sizeof(*item));
  char *token;
  char *last;
  char *tmp = apr_pstrdup(result_pool, text);
  const char *tmp_end = &tmp[strlen(tmp)];

  *parsed_item = NULL;

  item->operation = apr_strtok(tmp, " ", &last);

  if (!item->operation)
    {
      return SVN_NO_ERROR;
    }

  item->scan = MATCH_TOKEN(item->operation, "SCAN");

  if (item->scan || MATCH_TOKEN(item->operation, "SEARCH"))
    {
      item->search = TRUE; /* Search or scan */
      token = apr_strtok(NULL, " ", &last);

      if (MATCH_TOKEN(token, "TABLE"))
        {
          item->table = apr_strtok(NULL, " ", &last);
        }
      else if (MATCH_TOKEN(token, "SUBQUERY"))
        {
          item->table = apr_psprintf(result_pool, "SUBQUERY-%s",
                                     apr_strtok(NULL, " ", &last));
        }
      else
        {
          printf("DBG: Expected 'TABLE', got '%s' in '%s'\n", token, text);
          return SVN_NO_ERROR; /* Nothing to parse */
        }

      token = apr_strtok(NULL, " ", &last);

      /* Skip alias */
      if (MATCH_TOKEN(token, "AS"))
        {
          item->alias = apr_strtok(NULL, " ", &last);
          token = apr_strtok(NULL, " ", &last);
        }

      if (MATCH_TOKEN(token, "USING"))
        {
          token = apr_strtok(NULL, " ", &last);

          if (MATCH_TOKEN(token, "AUTOMATIC"))
            {
              /* Pain: A temporary index is created */
              item->automatic_index = TRUE;
              token = apr_strtok(NULL, " ", &last);
            }

          /* Handle COVERING */
          if (MATCH_TOKEN(token, "COVERING"))
            {
              /* Bonus: Query will be answered by just using the index */
              item->covered_by_index = TRUE;
              token = apr_strtok(NULL, " ", &last);
           }

          if (MATCH_TOKEN(token, "INDEX"))
            {
              item->index = apr_strtok(NULL, " ", &last);
            }
          else if (MATCH_TOKEN(token, "INTEGER"))
            {
              token = apr_strtok(NULL, " ", &last);
              if (!MATCH_TOKEN(token, "PRIMARY"))
                {
                  printf("DBG: Expected 'PRIMARY', got '%s' in '%s'\n",
                         token, text);
                  return SVN_NO_ERROR;
                }

              token = apr_strtok(NULL, " ", &last);
              if (!MATCH_TOKEN(token, "KEY"))
                {
                  printf("DBG: Expected 'KEY', got '%s' in '%s'\n",
                         token, text);
                  return SVN_NO_ERROR;
                }

              item->primary_key = TRUE;
            }
          else
            {
              printf("DBG: Expected 'INDEX' or 'PRIMARY', got '%s' in '%s'\n",
                     token, text);
              return SVN_NO_ERROR;
            }

          token = apr_strtok(NULL, " ", &last);
        }

      if (token && token[0] == '(' && token[1] != '~')
        {
          /* Undo the tokenization to switch parser rules */
          size_t token_len = strlen(token);

          if (token + token_len < tmp_end)
            token[token_len] = ' ';

          if (token[token_len] == '\0')
            last[-1] = ' ';

          token++; /* Skip the '(' */

          item->expressions = apr_strtok(token, ")", &last);
          token = apr_strtok(NULL, " ", &last);
        }

      if (token && *token == '(' && token[1] == '~')
        {
          /* Undo the tokenization to switch parser rules */
          size_t token_len = strlen(token);

          if (token + token_len < tmp_end)
            token[token_len] = ' ';

          if (token[token_len] == '\0')
            last[-1] = ' ';

          token += 2; /* Skip "(~" */

          item->expected = apr_strtok(token, ")", &last);
          token = apr_strtok(NULL, " ", &last);
        }

      if (token)
        {
          printf("DBG: Unexpected token '%s' in '%s'\n",
                 token, text);
          return SVN_NO_ERROR;
        }

      /* Parsing successful */
    }
  else if (MATCH_TOKEN(item->operation, "EXECUTE"))
    {
      /* Subquery handling */
      return SVN_NO_ERROR;
    }
  else if (MATCH_TOKEN(item->operation, "COMPOUND"))
    {
      /* Handling temporary table (E.g. UNION) */

      token = apr_strtok(NULL, " ", &last);
      if (!MATCH_TOKEN(token, "SUBQUERIES"))
        {
          printf("DBG: Expected 'SUBQUERIES', got '%s' in '%s'\n", token,
                 text);
          return SVN_NO_ERROR;
        }

      item->compound_left = apr_strtok(NULL, " ", &last);
      token = apr_strtok(NULL, " ", &last);

      if (!MATCH_TOKEN(token, "AND"))
        {
          printf("DBG: Expected 'AND', got '%s' in '%s'\n", token, text);
          return SVN_NO_ERROR;
        }

      item->compound_right = apr_strtok(NULL, " ", &last);

      token = apr_strtok(NULL, " ", &last);
      if (MATCH_TOKEN(token, "USING"))
        {
          token = apr_strtok(NULL, " ", &last);
          if (!MATCH_TOKEN(token, "TEMP"))
            {
              printf("DBG: Expected 'TEMP', got '%s' in '%s'\n", token, text);
            }
          token = apr_strtok(NULL, " ", &last);
          if (!MATCH_TOKEN(token, "B-TREE"))
            {
              printf("DBG: Expected 'B-TREE', got '%s' in '%s'\n", token,
                     text);
            }
          item->create_btree = TRUE;
        }
    }
  else if (MATCH_TOKEN(item->operation, "USE"))
    {
      /* Using a temporary table for ordering results */
      /* ### Need parsing */
      item->create_btree = TRUE;
    }
  else
    {
      printf("DBG: Unhandled sqlite operation '%s' in explanation\n", item->operation);
      return SVN_NO_ERROR;
    }

  if (item->expressions)
    {
      const char *p;

      for (p = item->expressions; *p; p++)
        {
          if (*p == '?')
            item->expression_vars++;
        }
    }
  if (item->expected)
    {
      item->expected_rows = atoi(item->expected);
    }

  *parsed_item = item;
  return SVN_NO_ERROR;
}
Ejemplo n.º 22
0
static dav_error *
dav_rawx_deliver(const dav_resource *resource, ap_filter_t *output)
{
	dav_rawx_server_conf *conf;
	apr_pool_t *pool;
	apr_bucket_brigade *bb = NULL;
	apr_status_t status;
	apr_bucket *bkt = NULL;
	dav_resource_private *ctx;
	dav_error *e = NULL;

	apr_finfo_t info;

	DAV_XDEBUG_RES(resource, 0, "%s(%s)", __FUNCTION__, resource_get_pathname(resource));

	pool = resource->pool;
	conf = resource_get_server_config(resource);

	/* Check resource type */
	if (DAV_RESOURCE_TYPE_REGULAR != resource->type) {
		e = server_create_and_stat_error(conf, pool, HTTP_CONFLICT, 0, "Cannot GET this type of resource.");
		goto end_deliver;
	}

	if (resource->collection) {
		e = server_create_and_stat_error(conf, pool, HTTP_CONFLICT, 0, "No GET on collections");
		goto end_deliver;
	}

	ctx = resource->info;

	if (ctx->update_only) {
		/* Check if it is not a busy file. We accept reads during
		 * compression but not attr updates. */
		char *pending_file = apr_pstrcat(pool,
				resource_get_pathname(resource), ".pending", NULL);
		status = apr_stat(&info, pending_file, APR_FINFO_ATIME, pool);
		if (status == APR_SUCCESS) {
			e = server_create_and_stat_error(conf, pool, HTTP_FORBIDDEN,
					0, "File in pending mode.");
			goto end_deliver;
		}

		GError *error_local = NULL;
		/* UPDATE chunk attributes and go on */
		const char *path = resource_get_pathname(resource);
		FILE *f = NULL;
		f = fopen(path, "r");
		/* Try to open the file but forbids a creation */
		if (!set_rawx_info_to_fd(fileno(f), &error_local, &(ctx->chunk))) {
			fclose(f);
			e = server_create_and_stat_error(conf, pool,
					HTTP_FORBIDDEN, 0, apr_pstrdup(pool, gerror_get_message(error_local)));
			g_clear_error(&error_local);
			goto end_deliver;
		}
		fclose(f);
	} else {
		bb = apr_brigade_create(pool, output->c->bucket_alloc);

		if (!ctx->compression){
			apr_file_t *fd = NULL;

			/* Try to open the file but forbids a creation */
			status = apr_file_open(&fd, resource_get_pathname(resource),
					APR_READ|APR_BINARY|APR_BUFFERED, 0, pool);
			if (APR_SUCCESS != status) {
				e = server_create_and_stat_error(conf, pool, HTTP_FORBIDDEN,
						0, "File permissions deny server access.");
				goto end_deliver;
			}

			/* FIXME this does not handle large files. but this is test code anyway */
			bkt = apr_bucket_file_create(fd, 0,
					(apr_size_t)resource->info->finfo.size,
					pool, output->c->bucket_alloc);
		}
		else {
			DAV_DEBUG_RES(resource, 0, "Building a compressed resource bucket");
			gint i64;

			i64 = g_ascii_strtoll(ctx->cp_chunk.uncompressed_size, NULL, 10);

			/* creation of compression specific bucket */
			bkt = apr_pcalloc(pool, sizeof(struct apr_bucket));
			bkt->type = &chunk_bucket_type;
			bkt->length = i64;
			bkt->start = 0;
			bkt->data = ctx;
			bkt->free = chunk_bucket_free_noop;
			bkt->list = output->c->bucket_alloc;
		}

		APR_BRIGADE_INSERT_TAIL(bb, bkt);

		/* as soon as the chunk has been sent, end of stream!*/
		bkt = apr_bucket_eos_create(output->c->bucket_alloc);
		APR_BRIGADE_INSERT_TAIL(bb, bkt);

		if ((status = ap_pass_brigade(output, bb)) != APR_SUCCESS){
			e = server_create_and_stat_error(conf, pool, HTTP_FORBIDDEN, 0, "Could not write contents to filter.");
			/* close file */
			if (ctx->cp_chunk.fd) {
				fclose(ctx->cp_chunk.fd);
			}
			goto end_deliver;
		}
		if (ctx->cp_chunk.buf){
			g_free(ctx->cp_chunk.buf);
			ctx->cp_chunk.buf = NULL;
		}
		if (ctx->cp_chunk.uncompressed_size){
			g_free(ctx->cp_chunk.uncompressed_size);
			ctx->cp_chunk.uncompressed_size = NULL;
		}

		/* close file */
		if (ctx->cp_chunk.fd) {
			fclose(ctx->cp_chunk.fd);
		}

		server_inc_stat(conf, RAWX_STATNAME_REP_2XX, 0);
		server_add_stat(conf, RAWX_STATNAME_REP_BWRITTEN, resource->info->finfo.size, 0);
	}

end_deliver:

	if (bb) {
		apr_brigade_destroy(bb);
		bb = NULL;
	}

	/* Now we pass here even if an error occured, for process request duration */
	server_inc_request_stat(resource_get_server_config(resource), RAWX_STATNAME_REQ_CHUNKGET,
			request_get_duration(resource->info->request));

	return e;
}
Ejemplo n.º 23
0
static winnt_conn_ctx_t *mpm_get_completion_context(int *timeout)
{
    apr_status_t rv;
    winnt_conn_ctx_t *context = NULL;

    *timeout = 0;
    while (1) {
        /* Grab a context off the queue */
        apr_thread_mutex_lock(qlock);
        if (qhead) {
            context = qhead;
            qhead = qhead->next;
            if (!qhead)
                qtail = NULL;
        } else {
            ResetEvent(qwait_event);
        }
        apr_thread_mutex_unlock(qlock);

        if (!context) {
            /* We failed to grab a context off the queue, consider allocating
             * a new one out of the child pool. There may be up to
             * (ap_threads_per_child + num_listeners) contexts in the system
             * at once.
             */
            if (num_completion_contexts >= max_num_completion_contexts) {
                /* All workers are busy, need to wait for one */
                static int reported = 0;
                if (!reported) {
                    ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(00326)
                                 "Server ran out of threads to serve "
                                 "requests. Consider raising the "
                                 "ThreadsPerChild setting");
                    reported = 1;
                }

                /* Wait for a worker to free a context. Once per second, give
                 * the caller a chance to check for shutdown. If the wait
                 * succeeds, get the context off the queue. It must be
                 * available, since there's only one consumer.
                 */
                rv = WaitForSingleObject(qwait_event, 1000);
                if (rv == WAIT_OBJECT_0)
                    continue;
                else {
                    if (rv == WAIT_TIMEOUT) {
                        /* somewhat-normal condition where threads are busy */
                        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00327)
                                     "mpm_get_completion_context: Failed to get a "
                                     "free context within 1 second");
                        *timeout = 1;
                    }
                    else {
                        /* should be the unexpected, generic WAIT_FAILED */
                        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                                     ap_server_conf, APLOGNO(00328)
                                     "mpm_get_completion_context: "
                                     "WaitForSingleObject failed to get free context");
                    }
                    return NULL;
                }
            } else {
                /* Allocate another context.
                 * Note: Multiple failures in the next two steps will cause
                 * the pchild pool to 'leak' storage. I don't think this
                 * is worth fixing...
                 */
                apr_allocator_t *allocator;

                apr_thread_mutex_lock(child_lock);
                context = (winnt_conn_ctx_t *)apr_pcalloc(pchild,
                                                     sizeof(winnt_conn_ctx_t));


                context->overlapped.hEvent = CreateEvent(NULL, TRUE,
                                                         FALSE, NULL);
                if (context->overlapped.hEvent == NULL) {
                    /* Hopefully this is a temporary condition ... */
                    ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                                 ap_server_conf, APLOGNO(00329)
                                 "mpm_get_completion_context: "
                                 "CreateEvent failed.");

                    apr_thread_mutex_unlock(child_lock);
                    return NULL;
                }

                /* Create the transaction pool */
                apr_allocator_create(&allocator);
                apr_allocator_max_free_set(allocator, ap_max_mem_free);
                rv = apr_pool_create_ex(&context->ptrans, pchild, NULL,
                                        allocator);
                if (rv != APR_SUCCESS) {
                    ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, APLOGNO(00330)
                                 "mpm_get_completion_context: Failed "
                                 "to create the transaction pool.");
                    CloseHandle(context->overlapped.hEvent);

                    apr_thread_mutex_unlock(child_lock);
                    return NULL;
                }
                apr_allocator_owner_set(allocator, context->ptrans);
                apr_pool_tag(context->ptrans, "transaction");

                context->accept_socket = INVALID_SOCKET;
                context->ba = apr_bucket_alloc_create(context->ptrans);
                apr_atomic_inc32(&num_completion_contexts);

                apr_thread_mutex_unlock(child_lock);
                break;
            }
        } else {
            /* Got a context from the queue */
            break;
        }
    }

    return context;
}
Ejemplo n.º 24
0
int
Ganglia_metadata_send_real( Ganglia_metric gmetric, Ganglia_udp_send_channels send_channels, char *override_string )
{
  int len, i;
  XDR x;
  char gmetricmsg[GANGLIA_MAX_MESSAGE_LEN];
  Ganglia_metadata_msg msg;
  const apr_array_header_t *arr;
  const apr_table_entry_t *elts;
  const char *spoof = SPOOF;
  apr_pool_t *gm_pool=(apr_pool_t*)gmetric->pool;

  if (myhost[0] == '\0') 
      apr_gethostname( (char*)myhost, APRMAXHOSTLEN+1, gm_pool);

  msg.id = gmetadata_full;
  memcpy( &(msg.Ganglia_metadata_msg_u.gfull.metric), gmetric->msg, sizeof(Ganglia_metadata_message));
  msg.Ganglia_metadata_msg_u.gfull.metric_id.name = apr_pstrdup (gm_pool, gmetric->msg->name);
  debug_msg("  msg.Ganglia_metadata_msg_u.gfull.metric_id.name: %s\n", msg.Ganglia_metadata_msg_u.gfull.metric_id.name);
  if ( override_string != NULL )
    {
      msg.Ganglia_metadata_msg_u.gfull.metric_id.host = apr_pstrdup (gm_pool, (char*)override_string);
      debug_msg("  msg.Ganglia_metadata_msg_u.gfull.metric_id.host: %s\n", msg.Ganglia_metadata_msg_u.gfull.metric_id.host);
      msg.Ganglia_metadata_msg_u.gfull.metric_id.spoof = TRUE;
    }
    else
    {
      msg.Ganglia_metadata_msg_u.gfull.metric_id.host = apr_pstrdup (gm_pool, (char*)myhost);
      debug_msg("  msg.Ganglia_metadata_msg_u.gfull.metric_id.host: %s\n", msg.Ganglia_metadata_msg_u.gfull.metric_id.host);
      msg.Ganglia_metadata_msg_u.gfull.metric_id.spoof = FALSE;
    }

  arr = apr_table_elts(gmetric->extra);
  elts = (const apr_table_entry_t *)arr->elts;
  msg.Ganglia_metadata_msg_u.gfull.metric.metadata.metadata_len = arr->nelts;
  msg.Ganglia_metadata_msg_u.gfull.metric.metadata.metadata_val = 
      (Ganglia_extra_data*)apr_pcalloc(gm_pool, sizeof(Ganglia_extra_data)*arr->nelts);

  /* add all of the metadata to the packet */
  for (i = 0; i < arr->nelts; ++i) {
      if (elts[i].key == NULL)
          continue;

      /* Replace the host name with the spoof host if it exists in the metadata */
      if ((apr_toupper(elts[i].key[0]) == spoof[0]) && strcasecmp(SPOOF_HOST, elts[i].key) == 0) 
        {
          msg.Ganglia_metadata_msg_u.gfull.metric_id.host = apr_pstrdup (gm_pool, elts[i].val);
          msg.Ganglia_metadata_msg_u.gfull.metric_id.spoof = TRUE;
        }
      if ((apr_toupper(elts[i].key[0]) == spoof[0]) && strcasecmp(SPOOF_HEARTBEAT, elts[i].key) == 0) 
        {
          msg.Ganglia_metadata_msg_u.gfull.metric_id.name = apr_pstrdup (gm_pool, "heartbeat");
          msg.Ganglia_metadata_msg_u.gfull.metric.name = msg.Ganglia_metadata_msg_u.gfull.metric_id.name;
          msg.Ganglia_metadata_msg_u.gfull.metric_id.spoof = TRUE;
        }

      msg.Ganglia_metadata_msg_u.gfull.metric.metadata.metadata_val[i].name = 
          apr_pstrdup(gm_pool, elts[i].key);
      msg.Ganglia_metadata_msg_u.gfull.metric.metadata.metadata_val[i].data = 
          apr_pstrdup(gm_pool, elts[i].val);
  }

  /* Send the message */
  xdrmem_create(&x, gmetricmsg, GANGLIA_MAX_MESSAGE_LEN, XDR_ENCODE);
  if(!xdr_Ganglia_metadata_msg(&x, &msg))
    {
      return 1;
    }
  len = xdr_getpos(&x); 
  /* Send the encoded data along...*/
  return Ganglia_udp_send_message( send_channels, gmetricmsg, len);
}
Ejemplo n.º 25
0
/* This function is the shared guts of add_file() and add_directory(),
   which see for the meanings of the parameters.  The only extra
   parameter here is IS_DIR, which is TRUE when adding a directory,
   and FALSE when adding a file.

   COPY_PATH must be a full URL, not a relative path. */
static svn_error_t *
add_file_or_directory(const char *path,
                      void *parent_baton,
                      const char *copy_path,
                      svn_revnum_t copy_revision,
                      svn_boolean_t is_dir,
                      apr_pool_t *pool,
                      void **return_baton)
{
  struct dir_baton *pb = parent_baton;
  struct edit_baton *eb = pb->edit_baton;
  apr_pool_t *subpool = svn_pool_create(pool);
  svn_boolean_t was_copied = FALSE;
  const char *full_path;

  /* Reject paths which contain control characters (related to issue #4340). */
  SVN_ERR(svn_path_check_valid(path, pool));

  full_path = svn_fspath__join(eb->base_path,
                               svn_relpath_canonicalize(path, pool), pool);

  /* Sanity check. */
  if (copy_path && (! SVN_IS_VALID_REVNUM(copy_revision)))
    return svn_error_createf
      (SVN_ERR_FS_GENERAL, NULL,
       _("Got source path but no source revision for '%s'"), full_path);

  if (copy_path)
    {
      const char *fs_path;
      svn_fs_root_t *copy_root;
      svn_node_kind_t kind;
      size_t repos_url_len;
      svn_repos_authz_access_t required;

      /* Copy requires recursive write access to the destination path
         and write access to the parent path. */
      required = svn_authz_write | (is_dir ? svn_authz_recursive : 0);
      SVN_ERR(check_authz(eb, full_path, eb->txn_root,
                          required, subpool));
      SVN_ERR(check_authz(eb, pb->path, eb->txn_root,
                          svn_authz_write, subpool));

      /* Check PATH in our transaction.  Make sure it does not exist
         unless its parent directory was copied (in which case, the
         thing might have been copied in as well), else return an
         out-of-dateness error. */
      SVN_ERR(svn_fs_check_path(&kind, eb->txn_root, full_path, subpool));
      if ((kind != svn_node_none) && (! pb->was_copied))
        return svn_error_trace(out_of_date(full_path, kind));

      /* For now, require that the url come from the same repository
         that this commit is operating on. */
      copy_path = svn_path_uri_decode(copy_path, subpool);
      repos_url_len = strlen(eb->repos_url_decoded);
      if (strncmp(copy_path, eb->repos_url_decoded, repos_url_len) != 0)
        return svn_error_createf
          (SVN_ERR_FS_GENERAL, NULL,
           _("Source url '%s' is from different repository"), copy_path);

      fs_path = apr_pstrdup(subpool, copy_path + repos_url_len);

      /* Now use the "fs_path" as an absolute path within the
         repository to make the copy from. */
      SVN_ERR(svn_fs_revision_root(&copy_root, eb->fs,
                                   copy_revision, subpool));

      /* Copy also requires (recursive) read access to the source */
      required = svn_authz_read | (is_dir ? svn_authz_recursive : 0);
      SVN_ERR(check_authz(eb, fs_path, copy_root, required, subpool));

      SVN_ERR(svn_fs_copy(copy_root, fs_path,
                          eb->txn_root, full_path, subpool));
      was_copied = TRUE;
    }
  else
    {
      /* No ancestry given, just make a new directory or empty file.
         Note that we don't perform an existence check here like the
         copy-from case does -- that's because svn_fs_make_*()
         already errors out if the file already exists.  Verify write
         access to the full path and to the parent. */
      SVN_ERR(check_authz(eb, full_path, eb->txn_root,
                          svn_authz_write, subpool));
      SVN_ERR(check_authz(eb, pb->path, eb->txn_root,
                          svn_authz_write, subpool));
      if (is_dir)
        SVN_ERR(svn_fs_make_dir(eb->txn_root, full_path, subpool));
      else
        SVN_ERR(svn_fs_make_file(eb->txn_root, full_path, subpool));
    }

  /* Cleanup our temporary subpool. */
  svn_pool_destroy(subpool);

  /* Build a new child baton. */
  if (is_dir)
    {
      *return_baton = make_dir_baton(eb, pb, full_path, was_copied,
                                     SVN_INVALID_REVNUM, pool);
    }
  else
    {
      struct file_baton *new_fb = apr_pcalloc(pool, sizeof(*new_fb));
      new_fb->edit_baton = eb;
      new_fb->path = full_path;
      *return_baton = new_fb;
    }

  return SVN_NO_ERROR;
}
Ejemplo n.º 26
0
/*
** dav_add_lock:  Add a direct lock for resource, and indirect locks for
**    all children, bounded by depth.
**    ### assume request only contains one lock
*/
DAV_DECLARE(dav_error *) dav_add_lock(request_rec *r,
                                      const dav_resource *resource,
                                      dav_lockdb *lockdb, dav_lock *lock,
                                      dav_response **response)
{
    dav_error *err;
    int depth = lock->depth;

    *response = NULL;

    /* Requested lock can be:
     *   Depth: 0   for null resource, existing resource, or existing collection
     *   Depth: Inf for existing collection
     */

    /*
    ** 2518 9.2 says to ignore depth if target is not a collection (it has
    **   no internal children); pretend the client gave the correct depth.
    */
    if (!resource->collection) {
        depth = 0;
    }

    /* In all cases, first add direct entry in lockdb */

    /*
    ** Append the new (direct) lock to the resource's existing locks.
    **
    ** Note: this also handles locknull resources
    */
    if ((err = (*lockdb->hooks->append_locks)(lockdb, resource, 0,
                                              lock)) != NULL) {
        /* ### maybe add a higher-level description */
        return err;
    }

    if (depth > 0) {
        /* Walk existing collection and set indirect locks */
        dav_walker_ctx ctx = { { 0 } };
        dav_response *multi_status;

        ctx.w.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_IGNORE_BINDS;
        ctx.w.func = dav_lock_walker;
        ctx.w.walk_ctx = &ctx;
        ctx.w.pool = r->pool;
        ctx.w.root = resource;
        ctx.w.lockdb = lockdb;

        ctx.r = r;
        ctx.lock = lock;

        err = (*resource->hooks->walk)(&ctx.w, DAV_INFINITY, &multi_status);
        if (err != NULL) {
            /* implies a 5xx status code occurred. screw the multistatus */
            return err;
        }

        if (multi_status != NULL) {
            /* Add a 424 for the Request-URI */
            dav_response *resp = apr_pcalloc(r->pool, sizeof(*resp));
            resp->href = apr_pstrdup(r->pool, resource->uri);
            resp->status = HTTP_FAILED_DEPENDENCY;
            resp->next = multi_status;

            *response = resp;
            /* manufacture a 207 error for the multistatus response */
            return dav_new_error(r->pool, HTTP_MULTI_STATUS, 0,
                                 "Error(s) occurred on resources during the "
                                 "addition of a depth lock.");
        }
    }

    return NULL;
}
Ejemplo n.º 27
0
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__);
}
Ejemplo n.º 28
0
svn_diff__lcs_t *
svn_diff__lcs(svn_diff__position_t *position_list1, /* pointer to tail (ring) */
              svn_diff__position_t *position_list2, /* pointer to tail (ring) */
              apr_pool_t *pool)
{
  int idx;
  apr_off_t length[2];
  svn_diff__snake_t *fp;
  apr_off_t d;
  apr_off_t k;
  apr_off_t p = 0;
  svn_diff__lcs_t *lcs, *lcs_freelist = NULL;

  svn_diff__position_t sentinel_position[2];

  /* Since EOF is always a sync point we tack on an EOF link
   * with sentinel positions
   */
  lcs = apr_palloc(pool, sizeof(*lcs));
  lcs->position[0] = apr_pcalloc(pool, sizeof(*lcs->position[0]));
  lcs->position[0]->offset = position_list1 ? position_list1->offset + 1 : 1;
  lcs->position[1] = apr_pcalloc(pool, sizeof(*lcs->position[1]));
  lcs->position[1]->offset = position_list2 ? position_list2->offset + 1 : 1;
  lcs->length = 0;
  lcs->refcount = 1;
  lcs->next = NULL;

  if (position_list1 == NULL || position_list2 == NULL)
    return lcs;

  /* Calculate length of both sequences to be compared */
  length[0] = position_list1->offset - position_list1->next->offset + 1;
  length[1] = position_list2->offset - position_list2->next->offset + 1;
  idx = length[0] > length[1] ? 1 : 0;

  /* strikerXXX: here we allocate the furthest point array, which is
   * strikerXXX: sized M + N + 3 (!)
   */
  fp = apr_pcalloc(pool,
                   sizeof(*fp) * (apr_size_t)(length[0] + length[1] + 3));
  fp += length[idx] + 1;

  sentinel_position[idx].next = position_list1->next;
  position_list1->next = &sentinel_position[idx];
  sentinel_position[idx].offset = position_list1->offset + 1;

  sentinel_position[abs(1 - idx)].next = position_list2->next;
  position_list2->next = &sentinel_position[abs(1 - idx)];
  sentinel_position[abs(1 - idx)].offset = position_list2->offset + 1;

  /* These are never dereferenced, only compared by value, so we
   * can safely fake these up and the void* cast is OK.
   */
  sentinel_position[0].node = (void*)&sentinel_position[0];
  sentinel_position[1].node = (void*)&sentinel_position[1];

  d = length[abs(1 - idx)] - length[idx];

  /* k = -1 will be the first to be used to get previous
   * position information from, make sure it holds sane
   * data
   */
  fp[-1].position[0] = sentinel_position[0].next;
  fp[-1].position[1] = &sentinel_position[1];

  p = 0;
  do
    {
      /* Forward */
      for (k = -p; k < d; k++)
        {
          svn_diff__snake(k, fp, idx, &lcs_freelist, pool);
        }

      for (k = d + p; k >= d; k--)
        {
          svn_diff__snake(k, fp, idx, &lcs_freelist, pool);
        }

      p++;
    }
  while (fp[d].position[1] != &sentinel_position[1]);

  lcs->next = fp[d].lcs;
  lcs = svn_diff__lcs_reverse(lcs);

  position_list1->next = sentinel_position[idx].next;
  position_list2->next = sentinel_position[abs(1 - idx)].next;

  return lcs;
}
Ejemplo n.º 29
0
DAV_DECLARE(dav_get_props_result) dav_get_props(dav_propdb *propdb,
                                                apr_xml_doc *doc)
{
    const dav_hooks_db *db_hooks = propdb->db_hooks;
    apr_xml_elem *elem = dav_find_child(doc->root, "prop");
    apr_text_header hdr_good = { 0 };
    apr_text_header hdr_bad = { 0 };
    apr_text_header hdr_ns = { 0 };
    int have_good = 0;
    dav_get_props_result result = { 0 };
    char *marks_liveprop;
    dav_xmlns_info *xi;
    int xi_filled = 0;

    /* ### NOTE: we should pass in TWO buffers -- one for keys, one for
       the marks */

    /* we will ALWAYS provide a "good" result, even if it is EMPTY */
    apr_text_append(propdb->p, &hdr_good,
                   "<D:propstat>" DEBUG_CR
                   "<D:prop>" DEBUG_CR);

    /* ### the marks should be in a buffer! */
    /* allocate zeroed-memory for the marks. These marks indicate which
       liveprop namespaces we've generated into the output xmlns buffer */

    /* same for the liveprops */
    marks_liveprop = apr_pcalloc(propdb->p, dav_get_liveprop_ns_count() + 1);

    xi = dav_xmlns_create(propdb->p);

    for (elem = elem->first_child; elem; elem = elem->next) {
        dav_elem_private *priv;
        dav_error *err;
        dav_prop_insert inserted;
        dav_prop_name name;

        /*
        ** First try live property providers; if they don't handle
        ** the property, then try looking it up in the propdb.
        */

        if (elem->priv == NULL) {
            elem->priv = apr_pcalloc(propdb->p, sizeof(*priv));
        }
        priv = elem->priv;

        /* cache the propid; dav_get_props() could be called many times */
        if (priv->propid == 0)
            dav_find_liveprop(propdb, elem);

        if (priv->propid != DAV_PROPID_CORE_UNKNOWN) {

            /* insert the property. returns 1 if an insertion was done. */
            if ((err = dav_insert_liveprop(propdb, elem, DAV_PROP_INSERT_VALUE,
                                           &hdr_good, &inserted)) != NULL) {
                /* ### need to propagate the error to the caller... */
                /* ### skip it for now, as if nothing was inserted */
            }
            if (inserted == DAV_PROP_INSERT_VALUE) {
                have_good = 1;

                /*
                ** Add the liveprop's namespace URIs. Note that provider==NULL
                ** for core properties.
                */
                if (priv->provider != NULL) {
                    const char * const * scan_ns_uri;

                    for (scan_ns_uri = priv->provider->namespace_uris;
                         *scan_ns_uri != NULL;
                         ++scan_ns_uri) {
                        long ns;

                        ns = dav_get_liveprop_ns_index(*scan_ns_uri);
                        if (marks_liveprop[ns])
                            continue;
                        marks_liveprop[ns] = 1;

                        dav_insert_xmlns(propdb->p, "lp", ns, *scan_ns_uri,
                                         &hdr_ns);
                    }
                }

                /* property added. move on to the next property. */
                continue;
            }
            else if (inserted == DAV_PROP_INSERT_NOTDEF) {
                /* nothing to do. fall thru to allow property to be handled
                   as a dead property */
            }
#if DAV_DEBUG
            else {
#if 0
                /* ### need to change signature to return an error */
                return dav_new_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR, 0,
                                     "INTERNAL DESIGN ERROR: insert_liveprop "
                                     "did not insert what was asked for.");
#endif
            }
#endif
        }

        /* The property wasn't a live property, so look in the dead property
           database. */

        /* make sure propdb is really open */
        if (propdb->deferred) {
            /* ### what to do with db open error? */
            (void) dav_really_open_db(propdb, 1 /*ro*/);
        }

        if (elem->ns == APR_XML_NS_NONE)
            name.ns = "";
        else
            name.ns = APR_XML_GET_URI_ITEM(propdb->ns_xlate, elem->ns);
        name.name = elem->name;

        /* only bother to look if a database exists */
        if (propdb->db != NULL) {
            int found;

            if ((err = (*db_hooks->output_value)(propdb->db, &name,
                                                 xi, &hdr_good,
                                                 &found)) != NULL) {
                /* ### what to do? continue doesn't seem right... */
                continue;
            }

            if (found) {
                have_good = 1;

                /* if we haven't added the db's namespaces, then do so... */
                if (!xi_filled) {
                    (void) (*db_hooks->define_namespaces)(propdb->db, xi);
                    xi_filled = 1;
                }
                continue;
            }
        }

        /* not found as a live OR dead property. add a record to the "bad"
           propstats */

        /* make sure we've started our "bad" propstat */
        if (hdr_bad.first == NULL) {
            apr_text_append(propdb->p, &hdr_bad,
                            "<D:propstat>" DEBUG_CR
                            "<D:prop>" DEBUG_CR);
        }

        /* output this property's name (into the bad propstats) */
        dav_output_prop_name(propdb->p, &name, xi, &hdr_bad);
    }

    apr_text_append(propdb->p, &hdr_good,
                    "</D:prop>" DEBUG_CR
                    "<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR
                    "</D:propstat>" DEBUG_CR);

    /* default to start with the good */
    result.propstats = hdr_good.first;

    /* we may not have any "bad" results */
    if (hdr_bad.first != NULL) {
        /* "close" the bad propstat */
        apr_text_append(propdb->p, &hdr_bad,
                        "</D:prop>" DEBUG_CR
                        "<D:status>HTTP/1.1 404 Not Found</D:status>" DEBUG_CR
                        "</D:propstat>" DEBUG_CR);

        /* if there are no good props, then just return the bad */
        if (!have_good) {
            result.propstats = hdr_bad.first;
        }
        else {
            /* hook the bad propstat to the end of the good one */
            hdr_good.last->next = hdr_bad.first;
        }
    }

    /* add in all the various namespaces, and return them */
    dav_xmlns_generate(xi, &hdr_ns);
    result.xmlns = hdr_ns.first;

    return result;
}
Ejemplo n.º 30
0
AP_CORE_DECLARE_NONSTD(apr_status_t) ap_byterange_filter(ap_filter_t *f,
                                                         apr_bucket_brigade *bb)
{
#define MIN_LENGTH(len1, len2) ((len1 > len2) ? len2 : len1)
    request_rec *r = f->r;
    conn_rec *c = r->connection;
    byterange_ctx *ctx;
    apr_bucket *e;
    apr_bucket_brigade *bsend;
    apr_off_t range_start;
    apr_off_t range_end;
    char *current;
    apr_off_t clength = 0;
    apr_status_t rv;
    int found = 0;
    int num_ranges;

    /* Iterate through the brigade until reaching EOS or a bucket with
     * unknown length. */
    for (e = APR_BRIGADE_FIRST(bb);
         (e != APR_BRIGADE_SENTINEL(bb) && !APR_BUCKET_IS_EOS(e)
          && e->length != (apr_size_t)-1);
         e = APR_BUCKET_NEXT(e)) {
        clength += e->length;
    }

    /* Don't attempt to do byte range work if this brigade doesn't
     * contain an EOS, or if any of the buckets has an unknown length;
     * this avoids the cases where it is expensive to perform
     * byteranging (i.e. may require arbitrary amounts of memory). */
    if (!APR_BUCKET_IS_EOS(e) || clength <= 0) {
        ap_remove_output_filter(f);
        return ap_pass_brigade(f->next, bb);
    }

    num_ranges = ap_set_byterange(r);

    /* We have nothing to do, get out of the way. */
    if (num_ranges == 0) {
        ap_remove_output_filter(f);
        return ap_pass_brigade(f->next, bb);
    }

    ctx = apr_pcalloc(r->pool, sizeof(*ctx));
    ctx->num_ranges = num_ranges;
    /* create a brigade in case we never call ap_save_brigade() */
    ctx->bb = apr_brigade_create(r->pool, c->bucket_alloc);

    if (ctx->num_ranges > 1) {
        /* Is ap_make_content_type required here? */
        const char *orig_ct = ap_make_content_type(r, r->content_type);
        ctx->boundary = apr_psprintf(r->pool, "%" APR_UINT64_T_HEX_FMT "%lx",
                                     (apr_uint64_t)r->request_time, (long) getpid());

        ap_set_content_type(r, apr_pstrcat(r->pool, "multipart",
                                           use_range_x(r) ? "/x-" : "/",
                                           "byteranges; boundary=",
                                           ctx->boundary, NULL));

        if (strcasecmp(orig_ct, NO_CONTENT_TYPE)) {
            ctx->bound_head = apr_pstrcat(r->pool,
                                          CRLF "--", ctx->boundary,
                                          CRLF "Content-type: ",
                                          orig_ct,
                                          CRLF "Content-range: bytes ",
                                          NULL);
        }
        else {
            /* if we have no type for the content, do our best */
            ctx->bound_head = apr_pstrcat(r->pool,
                                          CRLF "--", ctx->boundary,
                                          CRLF "Content-range: bytes ",
                                          NULL);
        }
        ap_xlate_proto_to_ascii(ctx->bound_head, strlen(ctx->bound_head));
    }

    /* this brigade holds what we will be sending */
    bsend = apr_brigade_create(r->pool, c->bucket_alloc);

    while ((current = ap_getword(r->pool, &r->range, ','))
           && (rv = parse_byterange(current, clength, &range_start,
                                    &range_end))) {
        apr_bucket *e2;
        apr_bucket *ec;

        if (rv == -1) {
            continue;
        }

        /* These calls to apr_brigage_partition should only fail in
         * pathological cases, e.g. a file being truncated whilst
         * being served. */
        if ((rv = apr_brigade_partition(bb, range_start, &ec)) != APR_SUCCESS) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
                          PARTITION_ERR_FMT, range_start, clength);
            continue;
        }
        if ((rv = apr_brigade_partition(bb, range_end+1, &e2)) != APR_SUCCESS) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
                          PARTITION_ERR_FMT, range_end+1, clength);
            continue;
        }

        found = 1;

        /* For single range requests, we must produce Content-Range header.
         * Otherwise, we need to produce the multipart boundaries.
         */
        if (ctx->num_ranges == 1) {
            apr_table_setn(r->headers_out, "Content-Range",
                           apr_psprintf(r->pool, "bytes " BYTERANGE_FMT,
                                        range_start, range_end, clength));
        }
        else {
            char *ts;

            e = apr_bucket_pool_create(ctx->bound_head, strlen(ctx->bound_head),
                                       r->pool, c->bucket_alloc);
            APR_BRIGADE_INSERT_TAIL(bsend, e);

            ts = apr_psprintf(r->pool, BYTERANGE_FMT CRLF CRLF,
                              range_start, range_end, clength);
            ap_xlate_proto_to_ascii(ts, strlen(ts));
            e = apr_bucket_pool_create(ts, strlen(ts), r->pool,
                                       c->bucket_alloc);
            APR_BRIGADE_INSERT_TAIL(bsend, e);
        }

        do {
            apr_bucket *foo;
            const char *str;
            apr_size_t len;

            if (apr_bucket_copy(ec, &foo) != APR_SUCCESS) {
                /* As above; this should not fail since the bucket has
                 * a known length, but just to be sure, this takes
                 * care of uncopyable buckets that do somehow manage
                 * to slip through.  */
                /* XXX: check for failure? */
                apr_bucket_read(ec, &str, &len, APR_BLOCK_READ);
                apr_bucket_copy(ec, &foo);
            }
            APR_BRIGADE_INSERT_TAIL(bsend, foo);
            ec = APR_BUCKET_NEXT(ec);
        } while (ec != e2);
    }

    if (found == 0) {
        ap_remove_output_filter(f);
        r->status = HTTP_OK;
        /* bsend is assumed to be empty if we get here. */
        e = ap_bucket_error_create(HTTP_RANGE_NOT_SATISFIABLE, NULL,
                                   r->pool, c->bucket_alloc);
        APR_BRIGADE_INSERT_TAIL(bsend, e);
        e = apr_bucket_eos_create(c->bucket_alloc);
        APR_BRIGADE_INSERT_TAIL(bsend, e);
        return ap_pass_brigade(f->next, bsend);
    }

    if (ctx->num_ranges > 1) {
        char *end;

        /* add the final boundary */
        end = apr_pstrcat(r->pool, CRLF "--", ctx->boundary, "--" CRLF, NULL);
        ap_xlate_proto_to_ascii(end, strlen(end));
        e = apr_bucket_pool_create(end, strlen(end), r->pool, c->bucket_alloc);
        APR_BRIGADE_INSERT_TAIL(bsend, e);
    }

    e = apr_bucket_eos_create(c->bucket_alloc);
    APR_BRIGADE_INSERT_TAIL(bsend, e);

    /* we're done with the original content - all of our data is in bsend. */
    apr_brigade_cleanup(bb);

    /* send our multipart output */
    return ap_pass_brigade(f->next, bsend);
}