diff options
Diffstat (limited to 'subversion/libsvn_ra_serf/inherited_props.c')
| -rw-r--r-- | subversion/libsvn_ra_serf/inherited_props.c | 237 | 
1 files changed, 89 insertions, 148 deletions
| diff --git a/subversion/libsvn_ra_serf/inherited_props.c b/subversion/libsvn_ra_serf/inherited_props.c index 54eae0b5be7c..f1172e7b6815 100644 --- a/subversion/libsvn_ra_serf/inherited_props.c +++ b/subversion/libsvn_ra_serf/inherited_props.c @@ -41,7 +41,7 @@  /* The current state of our XML parsing. */  typedef enum iprops_state_e { -  NONE = 0, +  INITIAL = 0,    IPROPS_REPORT,    IPROPS_ITEM,    IPROPS_PATH, @@ -61,18 +61,12 @@ typedef struct iprops_context_t {    /* The repository's root URL. */    const char *repos_root_url; -  /* Current CDATA values*/ -  svn_stringbuf_t *curr_path; +  /* Current property name */    svn_stringbuf_t *curr_propname; -  svn_stringbuf_t *curr_propval; -  const char *curr_prop_val_encoding;    /* Current element in IPROPS. */    svn_prop_inherited_item_t *curr_iprop; -  /* Serf context completion flag for svn_ra_serf__context_run_wait() */ -  svn_boolean_t done; -    /* Path we are finding inherited properties for.  This is relative to       the RA session passed to svn_ra_serf__get_inherited_props. */    const char *path; @@ -80,162 +74,121 @@ typedef struct iprops_context_t {    svn_revnum_t revision;  } iprops_context_t; +#define S_ SVN_XML_NAMESPACE +static const svn_ra_serf__xml_transition_t iprops_table[] = { +  { INITIAL, S_, SVN_DAV__INHERITED_PROPS_REPORT, IPROPS_REPORT, +    FALSE, { NULL }, FALSE }, + +  { IPROPS_REPORT, S_, SVN_DAV__IPROP_ITEM, IPROPS_ITEM, +    FALSE, { NULL }, TRUE }, + +  { IPROPS_ITEM, S_, SVN_DAV__IPROP_PATH, IPROPS_PATH, +    TRUE, { NULL }, TRUE }, + +  { IPROPS_ITEM, S_, SVN_DAV__IPROP_PROPNAME, IPROPS_PROPNAME, +    TRUE, { NULL }, TRUE }, + +  { IPROPS_ITEM, S_, SVN_DAV__IPROP_PROPVAL, IPROPS_PROPVAL, +    TRUE, { "?V:encoding", NULL }, TRUE }, + +  { 0 } +}; + +/* Conforms to svn_ra_serf__xml_opened_t */  static svn_error_t * -start_element(svn_ra_serf__xml_parser_t *parser, -              svn_ra_serf__dav_props_t name, -              const char **attrs, +iprops_opened(svn_ra_serf__xml_estate_t *xes, +              void *baton, +              int entered_state, +              const svn_ra_serf__dav_props_t *tag,                apr_pool_t *scratch_pool)  { -  iprops_context_t *iprops_ctx = parser->user_data; -  iprops_state_e state; +  iprops_context_t *iprops_ctx = baton; -  state = parser->state->current_state; -  if (state == NONE -      && strcmp(name.name, SVN_DAV__INHERITED_PROPS_REPORT) == 0) +  if (entered_state == IPROPS_ITEM)      { -      svn_ra_serf__xml_push_state(parser, IPROPS_REPORT); -    } -  else if (state == IPROPS_REPORT && -           strcmp(name.name, SVN_DAV__IPROP_ITEM) == 0) -    { -      svn_stringbuf_setempty(iprops_ctx->curr_path);        svn_stringbuf_setempty(iprops_ctx->curr_propname); -      svn_stringbuf_setempty(iprops_ctx->curr_propval); -      iprops_ctx->curr_prop_val_encoding = NULL; -      iprops_ctx->curr_iprop = NULL; -      svn_ra_serf__xml_push_state(parser, IPROPS_ITEM); -    } -  else if (state == IPROPS_ITEM && -           strcmp(name.name, SVN_DAV__IPROP_PROPVAL) == 0) -    { -      const char *prop_val_encoding = svn_xml_get_attr_value("encoding", -                                                             attrs); -      iprops_ctx->curr_prop_val_encoding = apr_pstrdup(iprops_ctx->pool, -                                                       prop_val_encoding); -      svn_ra_serf__xml_push_state(parser, IPROPS_PROPVAL); -    } -  else if (state == IPROPS_ITEM && -           strcmp(name.name, SVN_DAV__IPROP_PATH) == 0) -    { -      svn_ra_serf__xml_push_state(parser, IPROPS_PATH); -    } -  else if (state == IPROPS_ITEM && -           strcmp(name.name, SVN_DAV__IPROP_PROPNAME) == 0) -    { -      svn_ra_serf__xml_push_state(parser, IPROPS_PROPNAME); -    } -  else if (state == IPROPS_ITEM && -           strcmp(name.name, SVN_DAV__IPROP_PROPVAL) == 0) -    { -      svn_ra_serf__xml_push_state(parser, IPROPS_PROPVAL); -    } +      iprops_ctx->curr_iprop = apr_pcalloc(iprops_ctx->pool, +                                           sizeof(*iprops_ctx->curr_iprop)); + +      iprops_ctx->curr_iprop->prop_hash = apr_hash_make(iprops_ctx->pool); +    }    return SVN_NO_ERROR;  } +/* Conforms to svn_ra_serf__xml_closed_t  */  static svn_error_t * -end_element(svn_ra_serf__xml_parser_t *parser, -            svn_ra_serf__dav_props_t name, -            apr_pool_t *scratch_pool) +iprops_closed(svn_ra_serf__xml_estate_t *xes, +              void *baton, +              int leaving_state, +              const svn_string_t *cdata, +              apr_hash_t *attrs, +              apr_pool_t *scratch_pool)  { -  iprops_context_t *iprops_ctx = parser->user_data; -  iprops_state_e state; - -  state = parser->state->current_state; +  iprops_context_t *iprops_ctx = baton; -    if (state == IPROPS_REPORT && -      strcmp(name.name, SVN_DAV__INHERITED_PROPS_REPORT) == 0) +  if (leaving_state == IPROPS_ITEM)      { -      svn_ra_serf__xml_pop_state(parser); +      APR_ARRAY_PUSH(iprops_ctx->iprops, svn_prop_inherited_item_t *) = +        iprops_ctx->curr_iprop; + +      iprops_ctx->curr_iprop = NULL;      } -  else if (state == IPROPS_PATH -           && strcmp(name.name, SVN_DAV__IPROP_PATH) == 0) +  else if (leaving_state == IPROPS_PATH)      { -      iprops_ctx->curr_iprop = apr_palloc( -        iprops_ctx->pool, sizeof(svn_prop_inherited_item_t)); +      /* Every <iprop-item> has a single <iprop-path> */ +      if (iprops_ctx->curr_iprop->path_or_url) +        return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);        iprops_ctx->curr_iprop->path_or_url =          svn_path_url_add_component2(iprops_ctx->repos_root_url, -                                    iprops_ctx->curr_path->data, +                                    cdata->data,                                      iprops_ctx->pool); -      iprops_ctx->curr_iprop->prop_hash = apr_hash_make(iprops_ctx->pool); -      svn_ra_serf__xml_pop_state(parser);      } -  else if (state == IPROPS_PROPVAL -           && strcmp(name.name, SVN_DAV__IPROP_PROPVAL) == 0) +  else if (leaving_state == IPROPS_PROPNAME)      { -      const svn_string_t *prop_val; +      if (iprops_ctx->curr_propname->len) +        return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL); -      if (iprops_ctx->curr_prop_val_encoding) -        { -          svn_string_t encoded_prop_val; +      /* Store propname for value */ +      svn_stringbuf_set(iprops_ctx->curr_propname, cdata->data); +    } +  else if (leaving_state == IPROPS_PROPVAL) +    { +      const char *encoding; +      const svn_string_t *val_str; + +      if (! iprops_ctx->curr_propname->len) +        return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL); -          if (strcmp(iprops_ctx->curr_prop_val_encoding, "base64") != 0) -            return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL); +      encoding = svn_hash_gets(attrs, "V:encoding"); -          encoded_prop_val.data = iprops_ctx->curr_propval->data; -          encoded_prop_val.len = iprops_ctx->curr_propval->len; -          prop_val = svn_base64_decode_string(&encoded_prop_val, -                                              iprops_ctx->pool); +      if (encoding) +        { +          if (strcmp(encoding, "base64") != 0) +            return svn_error_createf(SVN_ERR_XML_MALFORMED, +                                     NULL, +                                     _("Got unrecognized encoding '%s'"), +                                     encoding); + +          /* Decode into the right pool.  */ +          val_str = svn_base64_decode_string(cdata, iprops_ctx->pool);          }        else          { -          prop_val = svn_string_create_from_buf(iprops_ctx->curr_propval, -                                                iprops_ctx->pool); +          /* Copy into the right pool.  */ +          val_str = svn_string_dup(cdata, iprops_ctx->pool);          }        svn_hash_sets(iprops_ctx->curr_iprop->prop_hash,                      apr_pstrdup(iprops_ctx->pool,                                  iprops_ctx->curr_propname->data), -                    prop_val); -      /* Clear current propname and propval in the event there are -         multiple properties on the current path. */ +                    val_str); +      /* Clear current propname. */        svn_stringbuf_setempty(iprops_ctx->curr_propname); -      svn_stringbuf_setempty(iprops_ctx->curr_propval); -      svn_ra_serf__xml_pop_state(parser); -    } -  else if (state == IPROPS_PROPNAME -           && strcmp(name.name, SVN_DAV__IPROP_PROPNAME) == 0) -    { -      svn_ra_serf__xml_pop_state(parser); -    } -  else if (state == IPROPS_ITEM -           && strcmp(name.name, SVN_DAV__IPROP_ITEM) == 0) -    { -      APR_ARRAY_PUSH(iprops_ctx->iprops, svn_prop_inherited_item_t *) = -        iprops_ctx->curr_iprop; -      svn_ra_serf__xml_pop_state(parser); -    } -  return SVN_NO_ERROR; -} - - -static svn_error_t * -cdata_handler(svn_ra_serf__xml_parser_t *parser, -              const char *data, -              apr_size_t len, -              apr_pool_t *scratch_pool) -{ -  iprops_context_t *iprops_ctx = parser->user_data; -  iprops_state_e state = parser->state->current_state; - -  switch (state) -    { -    case IPROPS_PATH: -      svn_stringbuf_appendbytes(iprops_ctx->curr_path, data, len); -      break; - -    case IPROPS_PROPNAME: -      svn_stringbuf_appendbytes(iprops_ctx->curr_propname, data, len); -      break; - -    case IPROPS_PROPVAL: -      svn_stringbuf_appendbytes(iprops_ctx->curr_propval, data, len); -      break; - -    default: -      break;      } +  else +    SVN_ERR_MALFUNCTION(); /* Invalid transition table */    return SVN_NO_ERROR;  } @@ -281,7 +234,7 @@ svn_ra_serf__get_inherited_props(svn_ra_session_t *ra_session,    iprops_context_t *iprops_ctx;    svn_ra_serf__session_t *session = ra_session->priv;    svn_ra_serf__handler_t *handler; -  svn_ra_serf__xml_parser_t *parser_ctx; +  svn_ra_serf__xml_context_t *xmlctx;    const char *req_url;    SVN_ERR(svn_ra_serf__get_stable_url(&req_url, @@ -295,19 +248,20 @@ svn_ra_serf__get_inherited_props(svn_ra_session_t *ra_session,    SVN_ERR_ASSERT(session->repos_root_str);    iprops_ctx = apr_pcalloc(scratch_pool, sizeof(*iprops_ctx)); -  iprops_ctx->done = FALSE;    iprops_ctx->repos_root_url = session->repos_root_str;    iprops_ctx->pool = result_pool; -  iprops_ctx->curr_path = svn_stringbuf_create_empty(scratch_pool);    iprops_ctx->curr_propname = svn_stringbuf_create_empty(scratch_pool); -  iprops_ctx->curr_propval = svn_stringbuf_create_empty(scratch_pool);    iprops_ctx->curr_iprop = NULL;    iprops_ctx->iprops = apr_array_make(result_pool, 1,                                         sizeof(svn_prop_inherited_item_t *));    iprops_ctx->path = path;    iprops_ctx->revision = revision; -  handler = apr_pcalloc(scratch_pool, sizeof(*handler)); +  xmlctx = svn_ra_serf__xml_context_create(iprops_table, +                                           iprops_opened, iprops_closed, NULL, +                                           iprops_ctx, +                                           scratch_pool); +  handler = svn_ra_serf__create_expat_handler(xmlctx, scratch_pool);    handler->method = "REPORT";    handler->path = req_url; @@ -318,18 +272,6 @@ svn_ra_serf__get_inherited_props(svn_ra_session_t *ra_session,    handler->body_type = "text/xml";    handler->handler_pool = scratch_pool; -  parser_ctx = apr_pcalloc(scratch_pool, sizeof(*parser_ctx)); - -  parser_ctx->pool = scratch_pool; -  parser_ctx->user_data = iprops_ctx; -  parser_ctx->start = start_element; -  parser_ctx->end = end_element; -  parser_ctx->cdata = cdata_handler; -  parser_ctx->done = &iprops_ctx->done; - -  handler->response_handler = svn_ra_serf__handle_xml_parser; -  handler->response_baton = parser_ctx; -    err = svn_ra_serf__context_run_one(handler, scratch_pool);    SVN_ERR(svn_error_compose_create(                      svn_ra_serf__error_on_status(handler->sline, @@ -337,8 +279,7 @@ svn_ra_serf__get_inherited_props(svn_ra_session_t *ra_session,                                                   handler->location),                      err)); -  if (iprops_ctx->done) -    *iprops = iprops_ctx->iprops; +  *iprops = iprops_ctx->iprops;    return SVN_NO_ERROR;  } | 
