⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dbm.c

📁 Apache 2.0.63 is the current stable version of the 2.0 series, and is recommended over any previous
💻 C
📖 第 1 页 / 共 2 页
字号:
    dav_db *db;
    dav_error *err;
    apr_datum_t key;
    apr_datum_t value = { 0 };

    *pdb = NULL;

    /*
    ** Return if an error occurred, or there is no database.
    **
    ** NOTE: db could be NULL if we attempted to open a readonly
    **       database that doesn't exist. If we require read/write
    **       access, then a database was created and opened.
    */
    if ((err = dav_dbm_open(pool, resource, ro, &db)) != NULL
        || db == NULL)
        return err;

    db->uri_index = apr_hash_make(pool);

    key.dptr = DAV_GDBM_NS_KEY;
    key.dsize = DAV_GDBM_NS_KEY_LEN;
    if ((err = dav_dbm_fetch(db, key, &value)) != NULL) {
        /* ### push a higher-level description? */
        return err;
    }

    if (value.dptr == NULL) {
        dav_propdb_metadata m = {
            DAV_DBVSN_MAJOR, DAV_DBVSN_MINOR, 0
        };

        /*
        ** If there is no METADATA key, then the database may be
        ** from versions 0.9.0 .. 0.9.4 (which would be incompatible).
        ** These can be identified by the presence of an NS_TABLE entry.
        */
        key.dptr = "NS_TABLE";
        key.dsize = 8;
        if (dav_dbm_exists(db, key)) {
            dav_dbm_close(db);

            /* call it a major version error */
            return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR,
                                 DAV_ERR_PROP_BAD_MAJOR,
                                 "Prop database has the wrong major "
                                 "version number and cannot be used.");
        }

        /* initialize a new metadata structure */
        dav_set_bufsize(pool, &db->ns_table, sizeof(m));
        memcpy(db->ns_table.buf, &m, sizeof(m));
    }
    else {
        dav_propdb_metadata m;
        int ns;
        const char *uri;

        dav_set_bufsize(pool, &db->ns_table, value.dsize);
        memcpy(db->ns_table.buf, value.dptr, value.dsize);

        memcpy(&m, value.dptr, sizeof(m));
        if (m.major != DAV_DBVSN_MAJOR) {
            dav_dbm_close(db);

            return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR,
                                 DAV_ERR_PROP_BAD_MAJOR,
                                 "Prop database has the wrong major "
                                 "version number and cannot be used.");
        }
        db->version = m.minor;
        db->ns_count = ntohs(m.ns_count);

        dav_dbm_freedatum(db, value);

        /* create db->uri_index */
        for (ns = 0, uri = db->ns_table.buf + sizeof(dav_propdb_metadata);
             ns++ < db->ns_count;
             uri += strlen(uri) + 1) {

            /* we must copy the key, in case ns_table.buf moves */
            apr_hash_set(db->uri_index,
                         apr_pstrdup(pool, uri), APR_HASH_KEY_STRING,
                         (void *)ns);
        }
    }

    *pdb = db;
    return NULL;
}

static void dav_propdb_close(dav_db *db)
{

    if (db->ns_table_dirty) {
        dav_propdb_metadata m;
        apr_datum_t key;
        apr_datum_t value;
        dav_error *err;

        key.dptr = DAV_GDBM_NS_KEY;
        key.dsize = DAV_GDBM_NS_KEY_LEN;

        value.dptr = db->ns_table.buf;
        value.dsize = db->ns_table.cur_len;

        /* fill in the metadata that we store into the prop db. */
        m.major = DAV_DBVSN_MAJOR;
        m.minor = db->version;          /* ### keep current minor version? */
        m.ns_count = htons(db->ns_count);

        memcpy(db->ns_table.buf, &m, sizeof(m));

        err = dav_dbm_store(db, key, value);
        /* ### what to do with the error? */
    }

    dav_dbm_close(db);
}

static dav_error * dav_propdb_define_namespaces(dav_db *db, dav_xmlns_info *xi)
{
    int ns;
    const char *uri = db->ns_table.buf + sizeof(dav_propdb_metadata);

    /* within the prop values, we use "ns%d" for prefixes... register them */
    for (ns = 0; ns < db->ns_count; ++ns, uri += strlen(uri) + 1) {

        /* Empty URIs signify the empty namespace. These do not get a
           namespace prefix. when we generate the value, we will simply
           leave off the prefix, which is defined by mod_dav to be the
           empty namespace. */
        if (*uri == '\0')
            continue;

        /* ns_table.buf can move, so copy its value (we want the values to
           last as long as the provided dav_xmlns_info). */
        dav_xmlns_add(xi,
                      apr_psprintf(xi->pool, "ns%d", ns),
                      apr_pstrdup(xi->pool, uri));
    }

    return NULL;
}

static dav_error * dav_propdb_output_value(dav_db *db,
                                           const dav_prop_name *name,
                                           dav_xmlns_info *xi,
                                           apr_text_header *phdr,
                                           int *found)
{
    apr_datum_t key = dav_build_key(db, name);
    apr_datum_t value;
    dav_error *err;

    if ((err = dav_dbm_fetch(db, key, &value)) != NULL)
        return err;
    if (value.dptr == NULL) {
        *found = 0;
        return NULL;
    }
    *found = 1;

    dav_append_prop(db->pool, key.dptr, value.dptr, phdr);

    dav_dbm_freedatum(db, value);

    return NULL;
}

static dav_error * dav_propdb_map_namespaces(
    dav_db *db,
    const apr_array_header_t *namespaces,
    dav_namespace_map **mapping)
{
    dav_namespace_map *m = apr_palloc(db->pool, sizeof(*m));
    int i;
    int *pmap;
    const char **puri;

    /*
    ** Iterate over the provided namespaces. If a namespace already appears
    ** in our internal map of URI -> ns_id, then store that in the map. If
    ** we don't know the namespace yet, then add it to the map and to our
    ** table of known namespaces.
    */
    m->ns_map = pmap = apr_palloc(db->pool, namespaces->nelts * sizeof(*pmap));
    for (i = namespaces->nelts, puri = (const char **)namespaces->elts;
         i-- > 0;
         ++puri, ++pmap) {

        const char *uri = *puri;
        apr_size_t uri_len = strlen(uri);
        int ns_id = (int)apr_hash_get(db->uri_index, uri, uri_len);

        if (ns_id == 0) {
            dav_check_bufsize(db->pool, &db->ns_table, uri_len + 1);
            memcpy(db->ns_table.buf + db->ns_table.cur_len, uri, uri_len + 1);
            db->ns_table.cur_len += uri_len + 1;

            /* copy the uri in case the passed-in namespaces changes in
               some way. */
            apr_hash_set(db->uri_index, apr_pstrdup(db->pool, uri), uri_len,
                         (void *)(db->ns_count + 1));

            db->ns_table_dirty = 1;

            *pmap = db->ns_count++;
        }
        else {
            *pmap = ns_id - 1;
        }
    }

    *mapping = m;
    return NULL;
}

static dav_error * dav_propdb_store(dav_db *db, const dav_prop_name *name,
                                    const apr_xml_elem *elem,
                                    dav_namespace_map *mapping)
{
    apr_datum_t key = dav_build_key(db, name);
    apr_datum_t value;

    /* Note: mapping->ns_map was set up in dav_propdb_map_namespaces() */

    /* ### use a db- subpool for these values? clear on exit? */

    /* quote all the values in the element */
    /* ### be nice to do this without affecting the element itself */
    /* ### of course, the cast indicates Badness is occurring here */
    apr_xml_quote_elem(db->pool, (apr_xml_elem *)elem);

    /* generate a text blob for the xml:lang plus the contents */
    apr_xml_to_text(db->pool, elem, APR_XML_X2T_LANG_INNER, NULL,
                    mapping->ns_map,
                    (const char **)&value.dptr, &value.dsize);

    return dav_dbm_store(db, key, value);
}

static dav_error * dav_propdb_remove(dav_db *db, const dav_prop_name *name)
{
    apr_datum_t key = dav_build_key(db, name);
    return dav_dbm_delete(db, key);
}

static int dav_propdb_exists(dav_db *db, const dav_prop_name *name)
{
    apr_datum_t key = dav_build_key(db, name);
    return dav_dbm_exists(db, key);
}

static const char *dav_get_ns_table_uri(dav_db *db, int ns_id)
{
    const char *p = db->ns_table.buf + sizeof(dav_propdb_metadata);

    while (ns_id--)
        p += strlen(p) + 1;

    return p;
}

static void dav_set_name(dav_db *db, dav_prop_name *pname)
{
    const char *s = db->iter.dptr;

    if (s == NULL) {
        pname->ns = pname->name = NULL;
    }
    else if (*s == ':') {
        pname->ns = "";
        pname->name = s + 1;
    }
    else {
        int id = atoi(s);

        pname->ns = dav_get_ns_table_uri(db, id);
        if (s[1] == ':') {
            pname->name = s + 2;
        }
        else {
            pname->name = ap_strchr_c(s + 2, ':') + 1;
        }
    }
}

static dav_error * dav_propdb_next_name(dav_db *db, dav_prop_name *pname)
{
    dav_error *err;

    /* free the previous key. note: if the loop is aborted, then the DBM
       will toss the key (via pool cleanup) */
    if (db->iter.dptr != NULL)
        dav_dbm_freedatum(db, db->iter);

    if ((err = dav_dbm_nextkey(db, &db->iter)) != NULL)
        return err;

    /* skip past the METADATA key */
    if (db->iter.dptr != NULL && *db->iter.dptr == 'M')
        return dav_propdb_next_name(db, pname);

    dav_set_name(db, pname);
    return NULL;
}

static dav_error * dav_propdb_first_name(dav_db *db, dav_prop_name *pname)
{
    dav_error *err;

    if ((err = dav_dbm_firstkey(db, &db->iter)) != NULL)
        return err;

    /* skip past the METADATA key */
    if (db->iter.dptr != NULL && *db->iter.dptr == 'M')
        return dav_propdb_next_name(db, pname);

    dav_set_name(db, pname);
    return NULL;
}

static dav_error * dav_propdb_get_rollback(dav_db *db,
                                           const dav_prop_name *name,
                                           dav_deadprop_rollback **prollback)
{
    dav_deadprop_rollback *rb = apr_pcalloc(db->pool, sizeof(*rb));
    apr_datum_t key;
    apr_datum_t value;
    dav_error *err;

    key = dav_build_key(db, name);
    rb->key.dptr = apr_pstrdup(db->pool, key.dptr);
    rb->key.dsize = key.dsize;

    if ((err = dav_dbm_fetch(db, key, &value)) != NULL)
        return err;
    if (value.dptr != NULL) {
        rb->value.dptr = apr_pmemdup(db->pool, value.dptr, value.dsize);
        rb->value.dsize = value.dsize;
    }

    *prollback = rb;
    return NULL;
}

static dav_error * dav_propdb_apply_rollback(dav_db *db,
                                             dav_deadprop_rollback *rollback)
{
    if (rollback->value.dptr == NULL) {
        /* don't fail if the thing isn't really there. */
        (void) dav_dbm_delete(db, rollback->key);
        return NULL;
    }

    return dav_dbm_store(db, rollback->key, rollback->value);
}

const dav_hooks_db dav_hooks_db_dbm =
{
    dav_propdb_open,
    dav_propdb_close,
    dav_propdb_define_namespaces,
    dav_propdb_output_value,
    dav_propdb_map_namespaces,
    dav_propdb_store,
    dav_propdb_remove,
    dav_propdb_exists,
    dav_propdb_first_name,
    dav_propdb_next_name,
    dav_propdb_get_rollback,
    dav_propdb_apply_rollback,

    NULL /* ctx */
};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -