/* send a response to the client for this baton */ static svn_error_t * send_response(const dav_svn_repos *repos, svn_fs_root_t *root, const char *path, svn_boolean_t is_dir, ap_filter_t *output, apr_bucket_brigade *bb, apr_pool_t *pool) { const char *href; const char *vsn_url; apr_status_t status; svn_revnum_t rev_to_use; href = dav_svn__build_uri(repos, DAV_SVN__BUILD_URI_PUBLIC, SVN_IGNORED_REVNUM, path, 0 /* add_href */, pool); rev_to_use = dav_svn__get_safe_cr(root, path, pool); vsn_url = dav_svn__build_uri(repos, DAV_SVN__BUILD_URI_VERSION, rev_to_use, path, 0 /* add_href */, pool); status = ap_fputstrs(output, bb, "<D:response>" DEBUG_CR "<D:href>", apr_xml_quote_string(pool, href, 1), "</D:href>" DEBUG_CR "<D:propstat><D:prop>" DEBUG_CR, is_dir ? "<D:resourcetype><D:collection/></D:resourcetype>" : "<D:resourcetype/>", DEBUG_CR, "<D:checked-in><D:href>", apr_xml_quote_string(pool, vsn_url, 1), "</D:href></D:checked-in>" DEBUG_CR "</D:prop>" DEBUG_CR "<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR "</D:propstat>" DEBUG_CR "</D:response>" DEBUG_CR, NULL); if (status != APR_SUCCESS) return svn_error_wrap_apr(status, "Can't write response to output"); return SVN_NO_ERROR; }
dav_error * dav_svn__merge_response(ap_filter_t *output, const dav_svn_repos *repos, svn_revnum_t new_rev, char *post_commit_err, apr_xml_elem *prop_elem, svn_boolean_t disable_merge_response, apr_pool_t *pool) { apr_bucket_brigade *bb; svn_fs_root_t *root; svn_error_t *serr; const char *vcc; const char *rev; svn_string_t *creationdate, *creator_displayname; const char *post_commit_err_elem = NULL, *post_commit_header_info = NULL; serr = svn_fs_revision_root(&root, repos->fs, new_rev, pool); if (serr != NULL) { return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, "Could not open the FS root for the " "revision just committed.", repos->pool); } bb = apr_brigade_create(pool, output->c->bucket_alloc); /* prep some strings */ /* the HREF for the baseline is actually the VCC */ vcc = dav_svn__build_uri(repos, DAV_SVN__BUILD_URI_VCC, SVN_IGNORED_REVNUM, NULL, 0 /* add_href */, pool); /* the version-name of the baseline is the revision number */ rev = apr_psprintf(pool, "%ld", new_rev); /* get the post-commit hook stderr, if any */ if (post_commit_err) { post_commit_header_info = apr_psprintf(pool, " xmlns:S=\"%s\"", SVN_XML_NAMESPACE); post_commit_err_elem = apr_psprintf(pool, "<S:post-commit-err>%s" "</S:post-commit-err>", post_commit_err); } else { post_commit_header_info = "" ; post_commit_err_elem = "" ; } /* get the creationdate and creator-displayname of the new revision, too. */ serr = svn_fs_revision_prop(&creationdate, repos->fs, new_rev, SVN_PROP_REVISION_DATE, pool); if (serr != NULL) { return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, "Could not get date of newest revision", repos->pool); } serr = svn_fs_revision_prop(&creator_displayname, repos->fs, new_rev, SVN_PROP_REVISION_AUTHOR, pool); if (serr != NULL) { return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, "Could not get author of newest revision", repos->pool); } (void) ap_fputstrs(output, bb, DAV_XML_HEADER DEBUG_CR "<D:merge-response xmlns:D=\"DAV:\"", post_commit_header_info, ">" DEBUG_CR "<D:updated-set>" DEBUG_CR /* generate a response for the new baseline */ "<D:response>" DEBUG_CR "<D:href>", apr_xml_quote_string(pool, vcc, 1), "</D:href>" DEBUG_CR "<D:propstat><D:prop>" DEBUG_CR /* ### this is wrong. it's a VCC, not a baseline. but ### we need to tell the client to look at *this* ### resource for the version-name. */ "<D:resourcetype><D:baseline/></D:resourcetype>" DEBUG_CR, post_commit_err_elem, DEBUG_CR "<D:version-name>", rev, "</D:version-name>" DEBUG_CR, NULL); if (creationdate) { (void) ap_fputstrs(output, bb, "<D:creationdate>", apr_xml_quote_string(pool, creationdate->data, 1), "</D:creationdate>" DEBUG_CR, NULL); } if (creator_displayname) { (void) ap_fputstrs(output, bb, "<D:creator-displayname>", apr_xml_quote_string(pool, creator_displayname->data, 1), "</D:creator-displayname>" DEBUG_CR, NULL); } (void) ap_fputstrs(output, bb, "</D:prop>" DEBUG_CR "<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR "</D:propstat>" DEBUG_CR "</D:response>" DEBUG_CR, NULL); /* ONLY have dir_delta drive the editor if the caller asked us to generate a full MERGE response. svn clients can ask us to suppress this walk by sending specific request headers. */ if (! disable_merge_response) { /* Now we need to generate responses for all the resources which changed. This is done through a delta of the two roots. Note that a directory is not marked when open_dir is seen (since it typically is used just for changing members in that directory); instead, we want for a property change (the only reason the client would need to fetch a new directory). ### we probably should say something about the dirs, so that ### we can pass back the new version URL */ /* and go make me proud, boy! */ serr = do_resources(repos, root, new_rev, output, bb, pool); if (serr != NULL) { return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, "Error constructing resource list.", repos->pool); } } /* wrap up the merge response */ (void) ap_fputs(output, bb, "</D:updated-set>" DEBUG_CR "</D:merge-response>" DEBUG_CR); /* send whatever is left in the brigade */ (void) ap_pass_brigade(output, bb); return SVN_NO_ERROR; }
static void pstartElement(void *ctxt, const xmlChar * uname, const xmlChar ** uattrs) { int num_match; char *subs; int is_uri; const char **a; size_t s_to, s_from; saxctxt *ctx = (saxctxt *) ctxt; apr_array_header_t *linkattrs; int i; const char *name = (const char *) uname; const char **attrs = (const char **) uattrs; const htmlElemDesc *desc = htmlTagLookup(uname); /* VoxCDN FIXME: rewrite this, it's ridiculously bad */ #if 0 /* for now, err on the side of leaving stuff alone */ int enforce = 0; if ((ctx->cfg->doctype == fpi_html) || (ctx->cfg->doctype == fpi_xhtml)) { /* enforce html */ enforce = 2; if (!desc || desc->depr) return; } else if ((ctx->cfg->doctype == fpi_html) || (ctx->cfg->doctype == fpi_xhtml)) { enforce = 1; /* enforce html legacy */ if (!desc) { return; } } if (!desc && enforce) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, ctx->f->r, "Bogus HTML element %s dropped", name) ; return; } if (desc && desc->depr && (enforce == 2) ) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, ctx->f->r, "Deprecated HTML element %s dropped", name) ; return; } #endif ap_fputc(ctx->f->next, ctx->bb, '<'); ap_fputs(ctx->f->next, ctx->bb, name); if (attrs) { linkattrs = apr_hash_get(ctx->cfg->links, name, APR_HASH_KEY_STRING); for (a = attrs; *a; a += 2) { ctx->offset = 0; if (a[1]) { pappend(ctx, a[1], strlen(a[1]) + 1); is_uri = 0; if (linkattrs) { tattr *attrs = (tattr *) linkattrs->elts; for (i = 0; i < linkattrs->nelts; ++i) { if (!strcmp(*a, attrs[i].val)) { is_uri = 1; break; } } } if(is_uri) { /* first do the server replacements */ if(ctx->cfg->map) { server_remap_t *remaps = (server_remap_t *)ctx->cfg->map->elts; for(i = 0; i < ctx->cfg->map->nelts; ++i) { if(!ap_regexec(&(remaps[i].regex), ctx->buf, 0, 0, 0)) { int add_auth = ctx->cfg->global_auth | (remaps[i].flags & REMAP_FLAG_AUTH); int add_qstring_ignore = ctx->cfg->global_qstring_ignore | (remaps[i].flags & REMAP_FLAG_QSTRING_IGNORE); subs = remap_url(ctx, ctx->buf, add_auth, add_qstring_ignore); if(subs) { ++num_match; s_to = strlen(subs); s_from = strlen(ctx->buf); if(s_to > s_from) preserve(ctx, s_to - s_from); memcpy(ctx->buf, subs, s_to+1); break; /* only do one substitution per link */ } } } } } } if (!a[1]) ap_fputstrs(ctx->f->next, ctx->bb, " ", a[0], NULL); else { /* write the attribute */ ap_fputstrs(ctx->f->next, ctx->bb, " ", a[0], "=\"", NULL); pcharacters(ctx, (const xmlChar *) ctx->buf, strlen(ctx->buf)); ap_fputc(ctx->f->next, ctx->bb, '"'); } } } ctx->offset = 0; if(desc && desc->empty) ap_fputs(ctx->f->next, ctx->bb, "/>"); else ap_fputc(ctx->f->next, ctx->bb, '>'); }