/** * Retrieves the resource id of a version of a VCR * * @param db handle to the database * @param db_r VCR with @serialno set * @param version_num number of specific version of the VCR * @param version_id will be set to resource id of the version * * @return NULL on success, error otherwise. */ dav_error *dbms_get_version_id(const dav_repos_db *db, dav_repos_resource *db_r, int version_num, int *version_id) { apr_pool_t *pool = db_r->p; dav_repos_query *q = NULL; int ierrno = 0; TRACE(); q = dbms_prepare(pool, db->db, "SELECT resource_id FROM versions " "WHERE number=? AND vcr_id=?"); dbms_set_int(q, 1, version_num); dbms_set_int(q, 2, db_r->serialno); if (dbms_execute(q)) { dbms_query_destroy(q); db_error_message(pool, db->db, "dbms_execute error"); return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "DBMS Error"); } if ((ierrno = dbms_next(q)) <= 0) { dbms_query_destroy(q); db_error_message(pool, db->db, "dbms_next error"); return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "DBMS Error"); } *version_id = dbms_get_int(q, 1); dbms_query_destroy(q); return NULL; }
/* ** dav_fs_parse_locktoken ** ** Parse an opaquelocktoken URI into a locktoken. */ static dav_error * dav_fs_parse_locktoken( apr_pool_t *p, const char *char_token, dav_locktoken **locktoken_p) { dav_locktoken *locktoken; if (ap_strstr_c(char_token, "opaquelocktoken:") != char_token) { return dav_new_error(p, HTTP_BAD_REQUEST, DAV_ERR_LOCK_UNK_STATE_TOKEN, 0, "The lock token uses an unknown State-token " "format and could not be parsed."); } char_token += 16; locktoken = apr_pcalloc(p, sizeof(*locktoken)); if (apr_uuid_parse(&locktoken->uuid, char_token)) { return dav_new_error(p, HTTP_BAD_REQUEST, DAV_ERR_LOCK_PARSE_TOKEN, 0, "The opaquelocktoken has an incorrect format " "and could not be parsed."); } *locktoken_p = locktoken; return NULL; }
static dav_error *dav_deltav_patch_validate(const dav_resource * resource, const apr_xml_elem * elem, int operation, void **context, int *defer_to_dead) { dav_elem_private *priv = elem->priv; TRACE(); *context = (void *)get_livepropspec_from_id(dav_deltav_props, priv->propid); if (priv->propid == DAV_PROPID_auto_version) { *defer_to_dead = 0; if (resource->versioned && operation == DAV_PROP_OP_SET) { char *av_value = elem->first_child ? apr_pstrdup(resource->pool, elem->first_child->name) : ""; if (!(strcmp(av_value, "checkout-checkin"))) ; else if(!(strcmp(av_value, "checkout-unlocked-checkin") && strcmp(av_value, "checkout") && strcmp(av_value, "locked-checkout"))) return dav_new_error (resource->pool, HTTP_FORBIDDEN, 0, apr_psprintf (resource->pool, "%s supported currently", av_value)); else return dav_new_error(resource->pool, HTTP_BAD_REQUEST, 0, "Undefined value given for DAV:auto-version "); } else return dav_new_error(resource->pool, HTTP_FORBIDDEN, 0, "Not a set operation on a VCR"); } return NULL; }
/** * Get the version number of a version resource using its resource id * @param d handle to the database * @param r a resource whose checked_id is set to the resource_id of the version the version number is assigned to the vr_num field * @return NULL on success, dav_error otherwise */ dav_error *dbms_get_version_number(const dav_repos_db *d, dav_repos_resource *r) { apr_pool_t *pool = r->p; dav_repos_query *q = NULL; int ierrno = 0; dav_error *err = NULL; TRACE(); q = dbms_prepare(pool, d->db, "SELECT number FROM versions " "WHERE resource_id=?"); dbms_set_int(q, 1, r->checked_id); if (dbms_execute(q)) { dbms_query_destroy(q); return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "DBMS Error"); } if ((ierrno = dbms_next(q)) <= 0) { dbms_query_destroy(q); return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "Could not lookup version number"); } r->vr_num = dbms_get_int(q, 1); dbms_query_destroy(q); return err; }
dav_error * dav_svn__new_error(apr_pool_t *pool, int status, int error_id, const char *desc) { if (error_id == 0) error_id = SVN_ERR_RA_DAV_REQUEST_FAILED; /* * Note: dav_new_error() in httpd 2.0/2.2 always treated * the errno field in dav_error as an apr_status_t when * logging; on some platforms errno and apr_status_t * aren't directly interchangeable. The code for httpd * > 2.2 below perpetuates this. */ #if AP_MODULE_MAGIC_AT_LEAST(20091119,0) return dav_new_error(pool, status, error_id, 0, desc); #else errno = 0; /* For the same reason as in dav_svn__new_error_tag */ return dav_new_error(pool, status, error_id, desc); #endif }
/** * Change the parent acl of a resource * @param d database handle * @param db_r the resource * @param new_parent_id serialno of the new parent * @return NULL for success, dav_error otherwise */ dav_error *dbms_change_acl_parent(dav_repos_db *d, dav_repos_resource *db_r, int new_parent_id) { dav_repos_query *q = NULL; apr_pool_t *pool = db_r->p; char *orig_path, *new_parent_path, *new_path; dav_error *err = NULL; TRACE(); /* Get current path */ q = dbms_prepare(pool, d->db, "SELECT path FROM acl_inheritance" " WHERE resource_id = ?"); dbms_set_int(q, 1, db_r->serialno); dbms_execute(q); if(dbms_next(q) <= 0) { dbms_query_destroy(q); /* Not currently part of acl_inheritance, just add it */ return dbms_inherit_parent_aces(d, db_r, new_parent_id); } else { orig_path = dbms_get_string(q, 1); dbms_query_destroy(q); } /* Get new_parent_path */ q = dbms_prepare(pool, d->db, "SELECT path FROM acl_inheritance" " WHERE resource_id = ?"); dbms_set_int(q, 1, new_parent_id); dbms_execute(q); if(dbms_next(q) <= 0) { dbms_query_destroy(q); return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "invalid parent specified in change_acl_parent"); } else { new_parent_path = dbms_get_string(q, 1); dbms_query_destroy(q); } new_path = apr_psprintf(pool, "%s,%ld", new_parent_path, db_r->serialno); /* Update path(s) */ q = dbms_prepare(pool, d->db, "UPDATE acl_inheritance" " SET path = replace(path, ?, ?)" " WHERE path LIKE ?" " OR path = ?"); dbms_set_string(q, 1, orig_path); dbms_set_string(q, 2, new_path); dbms_set_string(q, 3, apr_pstrcat(pool, orig_path, ",%", NULL)); dbms_set_string(q, 4, orig_path); if (dbms_execute(q)) err = dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "DBMS Error during update to acl_inheritance " "(moving subtree)"); dbms_query_destroy(q); return err; }
/* ** dav_fs_load_locknull_list: Returns a dav_buffer dump of the locknull file ** for the given directory. */ static dav_error * dav_fs_load_locknull_list(apr_pool_t *p, const char *dirpath, dav_buffer *pbuf) { apr_finfo_t finfo; apr_file_t *file = NULL; dav_error *err = NULL; apr_size_t amt; apr_status_t rv; dav_buffer_init(p, pbuf, dirpath); if (pbuf->buf[pbuf->cur_len - 1] == '/') pbuf->buf[--pbuf->cur_len] = '\0'; dav_buffer_place(p, pbuf, "/" DAV_FS_STATE_DIR "/" DAV_FS_LOCK_NULL_FILE); /* reset this in case we leave w/o reading into the buffer */ pbuf->cur_len = 0; if (apr_file_open(&file, pbuf->buf, APR_READ | APR_BINARY, APR_OS_DEFAULT, p) != APR_SUCCESS) { return NULL; } rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, file); if (rv != APR_SUCCESS) { err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, rv, apr_psprintf(p, "Opened but could not stat file %s", pbuf->buf)); goto loaderror; } if (finfo.size != (apr_size_t)finfo.size) { err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, 0, apr_psprintf(p, "Opened but rejected huge file %s", pbuf->buf)); goto loaderror; } amt = (apr_size_t)finfo.size; dav_set_bufsize(p, pbuf, amt); if ((rv = apr_file_read(file, pbuf->buf, &amt)) != APR_SUCCESS || amt != finfo.size) { err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, rv, apr_psprintf(p, "Failure reading locknull file " "for %s", dirpath)); /* just in case the caller disregards the returned error */ pbuf->cur_len = 0; goto loaderror; } loaderror: apr_file_close(file); return err; }
dav_error *dbms_restore_vcc(const dav_repos_db *db, dav_repos_resource *vcc, dav_repos_resource *cvr) { apr_pool_t *pool = vcc->p; dav_repos_query *q = NULL; /* delete all version controlled binds of the vcc */ q = dbms_prepare(pool, db->db, "DELETE FROM binds " "WHERE collection_id=? AND resource_id IN " "(SELECT resource_id FROM binds INNER JOIN vcrs USING resource_id WHERE collection_id=?)"); dbms_set_int(q, 1, vcc->serialno); dbms_set_int(q, 2, vcc->serialno); if (dbms_execute(q)) { dbms_query_destroy(q); return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "DBMS Error"); } dbms_query_destroy(q); /* delete any conflicting non-version controlled binds to the VCC that may have been introduced after checking out */ q = dbms_prepare(pool, db->db, "DELETE FROM binds " "WHERE collection_id=? AND name IN (SELECT name FROM binds WHERE collection_id=?"); dbms_set_int(q, 1, vcc->serialno); dbms_set_int(q, 2, cvr->serialno); if (dbms_execute(q)) { dbms_query_destroy(q); return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "DBMS Error"); } dbms_query_destroy(q); /* copy and restore all the binds from the collection version */ q = dbms_prepare(pool, db->db, "INSERT INTO binds " " (SELECT (NULL, name, ?, vcrs.resource_id, updated_at) " " FROM binds JOIN vcrs ON binds.resource_id=vcrs.vhr_id " " WHERE collection_id=?) "); dbms_set_int(q, 1, vcc->serialno); dbms_set_int(q, 2, cvr->serialno); if (dbms_execute(q)) { dbms_query_destroy(q); return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "DBMS Error"); } dbms_query_destroy(q); return NULL; }
/** * Add a (resource, parent) entry into acl_inheritance table, * if not already done. * @param d DBMS connection struct * @param db_r The child resource * @param parent Resource_id of the parent */ dav_error *dbms_inherit_parent_aces(const dav_repos_db *d, const dav_repos_resource *db_r, int parent) { dav_error *err = NULL; dav_repos_query *q = NULL; apr_pool_t *pool = db_r->p; TRACE(); /* check if the resource is already in acl_inheritance */ q = dbms_prepare(pool, d->db, "SELECT path FROM acl_inheritance" " WHERE resource_id = ?"); dbms_set_int(q, 1, db_r->serialno); if(dbms_execute(q)) { dbms_query_destroy(q); return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "DBMS Error during select " "on acl_inheritance"); } if(dbms_next(q) > 0) { /* resource already a part of acl_inheritance, nothing to do */ dbms_query_destroy(q); return err; } dbms_query_destroy(q); /* Insert the new entry (resource, parent) with proper lft & rgt values */ q = dbms_prepare(pool, d->db, "INSERT INTO acl_inheritance (resource_id, path)" " SELECT ?, a.path || ',' || ?" " FROM acl_inheritance a WHERE a.resource_id = ?"); dbms_set_int(q, 1, db_r->serialno); dbms_set_int(q, 2, db_r->serialno); dbms_set_int(q, 3, parent); if(dbms_execute(q)) err = dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "DBMS Error during update " "on acl_inheritance"); dbms_query_destroy(q); /* Set the private members of dav_acl */ if(db_r->acl) { dav_acl_private *priv = apr_pcalloc(pool, sizeof(*priv)); priv->parent_id = parent; db_r->acl->info = priv; } return err; }
/* ** Find a particular lock on a resource (specified by its locktoken). ** ** *lock will be set to NULL if the lock is not found. ** ** Note that the provider can optimize the unmarshalling -- only one ** lock (or none) must be constructed and returned. ** ** If partial_ok is true (non-zero), then an indirect lock can be ** partially filled in. Otherwise, another lookup is done and the ** lock structure will be filled out as a DAV_LOCKREC_INDIRECT. */ static dav_error * find_lock(dav_lockdb *lockdb, const dav_resource *resource, const dav_locktoken *locktoken, int partial_ok, dav_lock **lock) { dav_lockdb_private *info = lockdb->info; svn_error_t *serr; svn_lock_t *slock; dav_lock *dlock = NULL; /* If the resource's fs path is unreadable, we don't want to say anything about locks attached to it.*/ if (! dav_svn__allow_read(resource, SVN_INVALID_REVNUM, resource->pool)) return dav_new_error(resource->pool, HTTP_FORBIDDEN, DAV_ERR_LOCK_SAVE_LOCK, "Path is not accessible."); serr = svn_fs_get_lock(&slock, resource->info->repos->fs, resource->info->repos_path, resource->pool); if (serr) return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, "Failed to look up lock by path.", resource->pool); if (slock != NULL) { /* Sanity check. */ if (strcmp(locktoken->uuid_str, slock->token) != 0) return dav_new_error(resource->pool, HTTP_BAD_REQUEST, DAV_ERR_LOCK_SAVE_LOCK, "Incoming token doesn't match existing lock."); svn_lock_to_dav_lock(&dlock, slock, FALSE, resource->exists, resource->pool); /* Let svn clients know the creationdate of the slock. */ apr_table_setn(info->r->headers_out, SVN_DAV_CREATIONDATE_HEADER, svn_time_to_cstring(slock->creation_date, resource->pool)); /* Let svn clients know the 'owner' of the slock. */ apr_table_setn(info->r->headers_out, SVN_DAV_LOCK_OWNER_HEADER, slock->owner); } *lock = dlock; return 0; }
/* ** dav_fs_save_locknull_list: Saves contents of pbuf into the ** locknull file for dirpath. */ static dav_error * dav_fs_save_locknull_list(apr_pool_t *p, const char *dirpath, dav_buffer *pbuf) { const char *pathname; apr_file_t *file = NULL; dav_error *err = NULL; apr_size_t amt; apr_status_t rv; if (pbuf->buf == NULL) return NULL; dav_fs_ensure_state_dir(p, dirpath); pathname = apr_pstrcat(p, dirpath, dirpath[strlen(dirpath) - 1] == '/' ? "" : "/", DAV_FS_STATE_DIR "/" DAV_FS_LOCK_NULL_FILE, NULL); if (pbuf->cur_len == 0) { /* delete the file if cur_len == 0 */ if ((rv = apr_file_remove(pathname, p)) != APR_SUCCESS) { return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, rv, apr_psprintf(p, "Error removing %s", pathname)); } return NULL; } if ((rv = apr_file_open(&file, pathname, APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BINARY, APR_OS_DEFAULT, p)) != APR_SUCCESS) { return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, rv, apr_psprintf(p, "Error opening %s for writing", pathname)); } amt = pbuf->cur_len; if ((rv = apr_file_write_full(file, pbuf->buf, amt, &amt)) != APR_SUCCESS || amt != pbuf->cur_len) { err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, rv, apr_psprintf(p, "Error writing %" APR_SIZE_T_FMT " bytes to %s", pbuf->cur_len, pathname)); } apr_file_close(file); return err; }
static dav_error * dav_repos_patch_validate(const dav_resource * resource, const apr_xml_elem * elem, int operation, void **context, int *defer_to_dead) { apr_pool_t *pool = resource->pool; dav_elem_private *priv = elem->priv; dav_repos_resource *db_r = resource->info->db_r; dav_repos_db *db = resource->info->db; char *path; const char *data; apr_size_t size; if (operation == DAV_PROP_OP_DELETE) return dav_new_error(pool, HTTP_CONFLICT, 0, "This property cannot be removed"); *context = (void *)get_livepropspec_from_id(dav_repos_props, priv->propid); switch(priv->propid) { case DAV_PROPID_displayname: if (elem->first_cdata.first && (elem->first_cdata.first->text == NULL || strlen(elem->first_cdata.first->text) > DAV_DISPLAYNAME_LIMIT)) return dav_new_error(pool, HTTP_CONFLICT, 0, "Invalid value specified"); break; case DAV_PROPID_getcontentlanguage: if (validate_language_tag(pool, elem->first_cdata.first->text)) return dav_new_error(pool, HTTP_CONFLICT, 0, "Invalid value specified"); break; case DAV_PROPID_getcontenttype: apr_xml_to_text(pool, elem, APR_XML_X2T_INNER, NULL, NULL, &data, &size); data = strip_whitespace((char*)data); sabridge_get_resource_file(db, db_r, &path); if (!is_content_type_good(path, data)) return dav_new_error(pool, HTTP_CONFLICT, 0, "Couldn't pass filter"); break; default: return dav_new_error(pool, HTTP_FORBIDDEN, 0, "Cannot be modified"); } return NULL; }
/** * Set the DAV:auto-version property * @param * @param d DB connection struct containing the user, password, and DB name * @param db_r Identifies the resource to set the set the property on. * Should have db_r->serialno and db_r->autoversion_type set * @return NULL, for success; Error, otherwise. * */ dav_error *dbms_set_autoversion_type(const dav_repos_db * db, dav_repos_resource * db_r, dav_repos_autoversion_t av_type) { apr_pool_t *pool = db_r->p; dav_repos_query *q = NULL; TRACE(); q = dbms_prepare(pool, db->db, "UPDATE vcrs " "SET version_type=? " "WHERE resource_id=?"); dbms_set_int(q, 1, av_type); dbms_set_int(q, 2, db_r->serialno); if (dbms_execute(q)) { db_error_message(pool, db->db, "Could not set auto-version property"); dbms_query_destroy(q); return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "DBMS Error"); } dbms_query_destroy(q); db_r->autoversion_type = av_type; return NULL; }
/* Copies VCBs * @param r_src the source collection * @param r_dest the collection version */ dav_error *dbms_copy_resource_collection_version(const dav_repos_db * db, dav_repos_resource * r_src, dav_repos_resource * r_dst, request_rec * rec) { apr_pool_t *pool = r_src->p; dav_repos_query *q = NULL; dav_error *err = NULL; TRACE(); if ((r_src->resourcetype == dav_repos_COLLECTION || r_src->resourcetype == dav_repos_VERSIONED_COLLECTION) && r_dst->resourcetype == dav_repos_COLLECTION_VERSION) { /* copying from a collection to collection version */ q = dbms_prepare(pool, db->db, "INSERT INTO binds(name, collection_id, resource_id, updated_at) " " (SELECT name, ?, vhr_id, updated_at " " FROM binds INNER JOIN vcrs ON binds.resource_id=vcrs.resource_id " " WHERE collection_id=?) "); dbms_set_int(q, 1, r_dst->serialno); dbms_set_int(q, 2, r_src->serialno); if (dbms_execute(q)) { dbms_query_destroy(q); err = dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "DBMS Error while intersting into 'binds'"); } dbms_query_destroy(q); } return err; }
/** * Set the checkin and checkout version for a resource * @param d DB connection struct containing the user, password, and DB name * @param db_r Identifies the resource to set the property on r->uri. * Contains the live property and value to set. * @author: The author who changed the resource * @return NULL, for success; Error, otherwise. */ dav_error *dbms_insert_version(const dav_repos_db * db, dav_repos_resource *new_version) { apr_pool_t *pool = new_version->p; dav_repos_query *q = NULL; TRACE(); /* Make an entry into the versions table */ q = dbms_prepare(pool, db->db, "INSERT INTO versions(resource_id, number,vcr_id, vhr_id) " "VALUES(?, ?, ?, ?)"); dbms_set_int(q, 1, new_version->serialno); dbms_set_int(q, 2, new_version->version); dbms_set_int(q, 3, new_version->vcr_id); dbms_set_int(q, 4, new_version->vhr_id); if (dbms_execute(q)) { dbms_query_destroy(q); db_error_message(pool, db->db, "dbms_execute error"); return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "DBMS Error"); } dbms_query_destroy(q); return NULL; }
/** * Make an entry into the vcrs table for an existing resource. * Also changes the type of the resource * * @param db handle to the database * @param db_r resource which is being converted to a VCR * * @return */ dav_error *dbms_insert_vcr(const dav_repos_db *db, dav_repos_resource *db_r) { apr_pool_t *pool = db_r->p; dav_repos_query *q = NULL; TRACE(); /* Create the vcrs entry */ q = dbms_prepare(pool, db->db, "INSERT INTO vcrs(resource_id, checked_id, vhr_id, " " checked_state, version_type, checkin_on_unlock)" " VALUES ( ?, ?, ?, 'I', ?, 0)"); dbms_set_int(q, 1, db_r->serialno); dbms_set_int(q, 2, db_r->checked_id); dbms_set_int(q, 3, db_r->vhr_id); db_r->checked_state = DAV_RESOURCE_CHECKED_IN; dbms_set_int(q, 4, db_r->autoversion_type); db_r->checkin_on_unlock = 1; if (dbms_execute(q)) { dbms_query_destroy(q); db_error_message(pool, db->db, "dbms_execute error"); return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "DBMS Error"); } dbms_query_destroy(q); return NULL; }
static dav_error * dav_fs_dbm_error(dav_db *db, apr_pool_t *p, apr_status_t status) { int errcode; const char *errstr; dav_error *err; char errbuf[200]; if (status == APR_SUCCESS) return NULL; p = db ? db->pool : p; /* There might not be a <db> if we had problems creating it. */ if (db == NULL) { errcode = 1; errstr = "Could not open property database."; if (APR_STATUS_IS_EDSOOPEN(status)) ap_log_error(APLOG_MARK, APLOG_CRIT, status, ap_server_conf, APLOGNO(00576) "The DBM driver could not be loaded"); } else { (void) apr_dbm_geterror(db->file, &errcode, errbuf, sizeof(errbuf)); errstr = apr_pstrdup(p, errbuf); } err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, errcode, status, errstr); return err; }
/* Helper func for dav_lock_to_svn_lock: take an incoming "<D:owner><foo></D:owner>" tag and convert it to "<foo>". */ static dav_error * unescape_xml(const char **output, const char *input, apr_pool_t *pool) { apr_xml_parser *xml_parser = apr_xml_parser_create(pool); apr_xml_doc *xml_doc; apr_status_t apr_err; const char *xml_input = apr_pstrcat (pool, "<?xml version=\"1.0\" encoding=\"utf-8\"?>", input, NULL); apr_err = apr_xml_parser_feed(xml_parser, xml_input, strlen(xml_input)); if (!apr_err) apr_err = apr_xml_parser_done(xml_parser, &xml_doc); if (apr_err) { char errbuf[1024]; (void)apr_xml_parser_geterror(xml_parser, errbuf, sizeof(errbuf)); return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, DAV_ERR_LOCK_SAVE_LOCK, errbuf); } apr_xml_to_text(pool, xml_doc->root, APR_XML_X2T_INNER, xml_doc->namespaces, NULL, output, NULL); return SVN_NO_ERROR; }
/** * Update the principal-property ace with the new principal value of * the property * @param d database handle * @param db_r resource * @prop_ns_id the namespace id of the property * @prop_name the property name * @principal_id serialno of the new principal */ dav_error *dbms_update_principal_property_aces(dav_repos_db *d, dav_repos_resource *db_r, int prop_ns_id, const char *prop_name, int principal_id) { dav_repos_query *q = NULL; apr_pool_t *pool = db_r->p; dav_error *err = NULL; TRACE(); q = dbms_prepare(pool, d->db, "UPDATE aces SET principal_id = ? " "WHERE resource_id = ? AND property_namespace_id = ? " "AND property_name = ?"); dbms_set_int(q, 1, principal_id); dbms_set_int(q, 2, db_r->serialno); dbms_set_int(q, 3, prop_ns_id); dbms_set_string(q, 4, prop_name); if (dbms_execute(q)) err = dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "DBMS Error during update of property aces"); dbms_query_destroy(q); return err; }
static dav_error * dav_generic_dbm_new_error(apr_dbm_t *db, apr_pool_t *p, apr_status_t status) { int errcode; const char *errstr; dav_error *err; char errbuf[200]; if (status == APR_SUCCESS) { return NULL; } /* There might not be a <db> if we had problems creating it. */ if (db == NULL) { errcode = 1; errstr = "Could not open property database."; } else { (void) apr_dbm_geterror(db, &errcode, errbuf, sizeof(errbuf)); errstr = apr_pstrdup(p, errbuf); } err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, errcode, status, errstr); return err; }
static dav_error * dav_fs_dbm_error(dav_db *db, apr_pool_t *p, apr_status_t status) { int save_errno = errno; int errcode; const char *errstr; dav_error *err; char errbuf[200]; if (status == APR_SUCCESS) return NULL; p = db ? db->pool : p; /* There might not be a <db> if we had problems creating it. */ if (db == NULL) { errcode = 1; errstr = "Could not open property database."; } else { (void) apr_dbm_geterror(db->file, &errcode, errbuf, sizeof(errbuf)); errstr = apr_pstrdup(p, errbuf); } err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, errcode, errstr); err->save_errno = save_errno; return err; }
/** * This is the second most important function, as it delivers the content of the * file (or the directory if not DAV) * @param resource The resource generated previously * @param output Here is where the output must be written * @return NULL on success */ static dav_error *dav_ns_deliver(const dav_resource *resource, ap_filter_t *output) { apr_bucket_brigade *bb; apr_bucket *bkt; dav_error *err; bb = apr_brigade_create(resource->pool, output->c->bucket_alloc); if (resource->collection) err = dav_ns_deliver_collection(resource, resource->info->request->output_filters, bb); else if (resource->info->metalink) { err = dav_ns_deliver_metalink(resource, resource->info->request->output_filters, bb); } else err = dav_new_error(resource->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "NS should not be trying to deliver files!"); if (err != NULL) return err; /* Close and flush the output */ bkt = apr_bucket_eos_create(output->c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, bkt); if (ap_pass_brigade(resource->info->request->output_filters, bb) != APR_SUCCESS) return dav_shared_new_error(resource->info->request, NULL, HTTP_INTERNAL_SERVER_ERROR, "Could not write EOS to filter."); /* All OK */ return NULL; }
static dav_error *dbms_get_creator_displayname(const dav_repos_db *d, dav_repos_resource *r) { int ierrno = 0; apr_pool_t *pool = r->p; dav_repos_query *q = NULL; TRACE(); q = dbms_prepare(pool, d->db, "SELECT name FROM principals " "WHERE resource_id = ?"); dbms_set_int(q, 1, r->creator_id); if(dbms_execute(q)) { dbms_query_destroy(q); return dav_new_error(r->p, HTTP_INTERNAL_SERVER_ERROR, 0, "dbms_execute error"); } if ((ierrno = dbms_next(q)) <= 0) { dbms_query_destroy(q); r->creator_displayname = NULL; } r->creator_displayname = dbms_get_string(q, 1); dbms_query_destroy(q); return NULL; }
dav_error *dbms_get_redirect_props(const dav_repos_db *d, dav_repos_resource *r) { dav_repos_query *q = NULL; dav_error *err = NULL; TRACE(); /* do nothing if we have already fetched redirect props */ if (r->redirect_lifetime && r->reftarget) { return NULL; } q = dbms_prepare(r->p, d->db, "SELECT lifetime, reftarget " "FROM redirectrefs WHERE resource_id = ?"); dbms_set_int(q, 1, r->serialno); if (dbms_execute(q) || (dbms_next(q) <=0)) { err = dav_new_error(r->p, HTTP_INTERNAL_SERVER_ERROR, 0, "DBMS error in reftargets lookup."); goto error; } if (0 == apr_strnatcmp(dbms_get_string(q, 1), "p")) r->redirect_lifetime = DAV_REDIRECTREF_PERMANENT; else r->redirect_lifetime = DAV_REDIRECTREF_TEMPORARY; r->reftarget = dbms_get_string(q, 2); error: dbms_query_destroy(q); return err; }
dav_error *dbms_insert_redirectref(const dav_repos_db *d, dav_repos_resource *r, const char *reftarget, dav_redirectref_lifetime t) { dav_repos_query *q = NULL; dav_error *err = NULL; q = dbms_prepare(r->p, d->db, "INSERT INTO redirectrefs " "(resource_id, reftarget, lifetime, updated_at) " "VALUES (?, ?, ?, ?)"); dbms_set_int(q, 1, r->serialno); dbms_set_string(q, 2, reftarget); dbms_set_string(q, 3, lifetime_to_s(t)); dbms_set_string(q, 4, time_apr_to_str(r->p, apr_time_now())); if (dbms_execute(q)) err = dav_new_error(r->p, HTTP_INTERNAL_SERVER_ERROR, 0, "DBMS error while inserting into 'redirectrefs'"); dbms_query_destroy(q); return err; }
/* ** dav_fs_open_lockdb: ** ** "open" the lock database, as specified in the global server configuration. ** If force is TRUE, then the database is opened now, rather than lazily. ** ** Note that only one can be open read/write. */ static dav_error * dav_fs_open_lockdb(request_rec *r, int ro, int force, dav_lockdb **lockdb) { dav_lockdb_combined *comb; comb = apr_pcalloc(r->pool, sizeof(*comb)); comb->pub.hooks = &dav_hooks_locks_fs; comb->pub.ro = ro; comb->pub.info = &comb->priv; comb->priv.r = r; comb->priv.pool = r->pool; comb->priv.lockdb_path = dav_get_lockdb_path(r); if (comb->priv.lockdb_path == NULL) { return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, DAV_ERR_LOCK_NO_DB, 0, "A lock database was not specified with the " "DAVLockDB directive. One must be specified " "to use the locking functionality."); } /* done initializing. return it. */ *lockdb = &comb->pub; if (force) { /* ### add a higher-level comment? */ return dav_fs_really_open_lockdb(*lockdb); } return NULL; }
static dav_error *dav_acl_patch_validate(const dav_resource * resource, const apr_xml_elem * elem, int operation, void **context, int *defer_to_dead) { apr_pool_t *pool = resource->pool; dav_repos_resource *db_r = resource->info->db_r; dav_repos_db *db = resource->info->db; request_rec *rec = resource->info->rec; dav_elem_private *priv = elem->priv; dav_error *err = NULL; TRACE(); if (priv->propid == DAV_PROPID_group_member_set) { *defer_to_dead = 0; if (db_r->resourcetype!=dav_repos_GROUP || operation!=DAV_PROP_OP_SET) return dav_new_error(pool, HTTP_FORBIDDEN, 0, "Not a set operation on a group"); apr_xml_elem *href_elem = dav_find_child(elem, "href"); apr_hash_t *new_members = apr_hash_make(pool); apr_array_header_t *to_remove = NULL; while (href_elem && !err) { const char *prin_uri = dav_xml_get_cdata(href_elem, pool, 1); const char *prin_name = get_name_from_principal_URL(rec, prin_uri); if (prin_name == NULL) err = dav_new_error (pool, HTTP_CONFLICT, 0, "Not a DAV:principal-URL"); else apr_hash_set(new_members, prin_name, APR_HASH_KEY_STRING, ""); href_elem = href_elem->next; } if (err) return err; if (apr_hash_count(new_members)) err = dbms_calculate_group_changes(db, db_r, new_members,&to_remove); else err = dbms_get_group_members(db, db_r, &to_remove); if (err) return err; apr_hash_set(new_members, "-to-remove-", APR_HASH_KEY_STRING, to_remove); *context = new_members; } return err; }
/** * Retrieves DeltaV properties of a version resource * @param d handle to the database * @param vr version resource * @return NULL on success, dav_error otherwise */ dav_error *dbms_get_version_resource_props(const dav_repos_db *d, dav_repos_resource *vr) { apr_pool_t *pool = vr->p; dav_repos_query *q = NULL; int ierrno = 0; dav_error *err = NULL; dav_repos_resource *vcr = NULL; sabridge_new_dbr_from_dbr(vr, &vcr); TRACE(); q = dbms_prepare(pool, d->db, "SELECT number, vcr_id FROM versions " "WHERE resource_id=?"); dbms_set_int(q, 1, vr->serialno); if (dbms_execute(q)) { dbms_query_destroy(q); return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "dbms_execute error"); } if ((ierrno = dbms_next(q)) < 0) { dbms_query_destroy(q); return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "dbms_next error"); } if (ierrno == 0) { dbms_query_destroy(q); return err; } vr->version = dbms_get_int(q, 1); vr->vcr_id = dbms_get_int(q, 2); dbms_query_destroy(q); /* check if this is the last version of its VCR */ vcr->serialno = vr->vcr_id; err = dbms_get_vcr_props(d, vcr); if(vcr->checked_id == vr->serialno) vr->lastversion = 1; return err; }
/** * Retrieve all DeltaV properties of a version controlled resource * @param d handle to the database * @param r resource whose properties are retrieved * @return NULL on success, dav_error otherwise */ dav_error *dbms_get_vcr_props(const dav_repos_db *d, dav_repos_resource *r) { apr_pool_t *pool = r->p; dav_repos_query *q = NULL; int ierrno = 0; dav_error *err = NULL; char *checked_state; TRACE(); q = dbms_prepare(pool, d->db, "SELECT checked_state, checked_id, vhr_id, version_type, " " checkin_on_unlock " "FROM vcrs WHERE resource_id=? "); dbms_set_int(q, 1, r->serialno); if (dbms_execute(q)) { dbms_query_destroy(q); return dav_new_error(r->p, HTTP_INTERNAL_SERVER_ERROR, 0, "dbms_execute error"); } if ((ierrno = dbms_next(q)) < 0) { dbms_query_destroy(q); return dav_new_error(r->p, HTTP_INTERNAL_SERVER_ERROR, 0, "dbms_next error"); } if (ierrno == 0) { dbms_query_destroy(q); r->checked_state = DAV_RESOURCE_NOT_VERSIONED; return err; } checked_state = dbms_get_string(q, 1); r->checked_state = checked_state[0]=='I'? DAV_RESOURCE_CHECKED_IN : DAV_RESOURCE_CHECKED_OUT; r->checked_id = dbms_get_int(q, 2); r->vhr_id = dbms_get_int(q, 3); r->autoversion_type = dbms_get_int(q, 4); dbms_query_destroy(q); err = dbms_get_version_number(d, r); return err; }
/** * Retrieve DeltaV properties of a Version History Resource * @param d handle to the database * @param vhr version history resource * @return NULL on success, dav_error otherwise */ dav_error *dbms_get_vhr_props(const dav_repos_db *d, dav_repos_resource *vhr) { apr_pool_t *pool = vhr->p; dav_repos_query *q = NULL; int ierrno = 0; dav_error *err = NULL; char *checked_state; TRACE(); q = dbms_prepare(pool, d->db, "SELECT resource_id, checked_state, checked_id " "FROM vcrs WHERE vhr_id=? "); dbms_set_int(q, 1, vhr->serialno); if (dbms_execute(q)) { dbms_query_destroy(q); return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "dbms_execute error"); } if ((ierrno = dbms_next(q)) < 0) { dbms_query_destroy(q); return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "dbms_next error"); } if (ierrno == 0) { dbms_query_destroy(q); return err; } vhr->vcr_id = dbms_get_int(q, 1); checked_state = dbms_get_string(q, 2); vhr->checked_state = checked_state[0]=='I'? DAV_RESOURCE_CHECKED_IN : DAV_RESOURCE_CHECKED_OUT; vhr->checked_id = dbms_get_int(q, 3); dbms_query_destroy(q); err = dbms_get_vhr_root_version_id(d, vhr); return err; }