示例#1
0
svn_error_t *
svn_repos__validate_prop(const char *name,
                         const svn_string_t *value,
                         apr_pool_t *pool)
{
    svn_prop_kind_t kind = svn_property_kind2(name);

    /* Allow deleting any property, even a property we don't allow to set. */
    if (value == NULL)
        return SVN_NO_ERROR;

    /* Disallow setting non-regular properties. */
    if (kind != svn_prop_regular_kind)
        return svn_error_createf
               (SVN_ERR_REPOS_BAD_ARGS, NULL,
                _("Storage of non-regular property '%s' is disallowed through the "
                  "repository interface, and could indicate a bug in your client"),
                name);

    /* Validate "svn:" properties. */
    if (svn_prop_is_svn_prop(name) && value != NULL)
    {
        /* Validate that translated props (e.g., svn:log) are UTF-8 with
         * LF line endings. */
        if (svn_prop_needs_translation(name))
        {
            if (!svn_utf__is_valid(value->data, value->len))
            {
                return svn_error_createf
                       (SVN_ERR_BAD_PROPERTY_VALUE, NULL,
                        _("Cannot accept '%s' property because it is not encoded in "
                          "UTF-8"), name);
            }

            /* Disallow inconsistent line ending style, by simply looking for
             * carriage return characters ('\r'). */
            if (strchr(value->data, '\r') != NULL)
            {
                return svn_error_createf
                       (SVN_ERR_BAD_PROPERTY_VALUE, NULL,
                        _("Cannot accept non-LF line endings in '%s' property"),
                        name);
            }
        }

        /* "svn:date" should be a valid date. */
        if (strcmp(name, SVN_PROP_REVISION_DATE) == 0)
        {
            apr_time_t temp;
            svn_error_t *err;

            err = svn_time_from_cstring(&temp, value->data, pool);
            if (err)
                return svn_error_create(SVN_ERR_BAD_PROPERTY_VALUE,
                                        err, NULL);
        }
    }

    return SVN_NO_ERROR;
}
示例#2
0
svn_boolean_t
svn_prop_needs_translation(const char *propname)
{
  /* ### Someday, we may want to be picky and choosy about which
     properties require UTF8 and EOL conversion.  For now, all "svn:"
     props need it.  */

  return svn_prop_is_svn_prop(propname);
}
示例#3
0
svn_boolean_t
svn_prop_has_svn_prop(const apr_hash_t *props, apr_pool_t *pool)
{
  apr_hash_index_t *hi;
  const void *prop_name;

  if (! props)
    return FALSE;

  for (hi = apr_hash_first(pool, (apr_hash_t *)props); hi;
       hi = apr_hash_next(hi))
    {
      apr_hash_this(hi, &prop_name, NULL, NULL);
      if (svn_prop_is_svn_prop((const char *) prop_name))
        return TRUE;
    }

  return FALSE;
}
示例#4
0
static svn_error_t *
propset_on_url(const char *propname,
               const svn_string_t *propval,
               const char *target,
               svn_boolean_t skip_checks,
               svn_revnum_t base_revision_for_url,
               const apr_hash_t *revprop_table,
               svn_commit_callback2_t commit_callback,
               void *commit_baton,
               svn_client_ctx_t *ctx,
               apr_pool_t *pool)
{
  enum svn_prop_kind prop_kind = svn_property_kind(NULL, propname);
  svn_ra_session_t *ra_session;
  svn_node_kind_t node_kind;
  const char *message;
  const svn_delta_editor_t *editor;
  void *edit_baton;
  apr_hash_t *commit_revprops;
  svn_error_t *err;

  if (prop_kind != svn_prop_regular_kind)
    return svn_error_createf
      (SVN_ERR_BAD_PROP_KIND, NULL,
       _("Property '%s' is not a regular property"), propname);

  /* Open an RA session for the URL. Note that we don't have a local
     directory, nor a place to put temp files. */
  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, target,
                                               NULL, NULL, FALSE, TRUE,
                                               ctx, pool));

  SVN_ERR(svn_ra_check_path(ra_session, "", base_revision_for_url,
                            &node_kind, pool));
  if (node_kind == svn_node_none)
    return svn_error_createf
      (SVN_ERR_FS_NOT_FOUND, NULL,
       _("Path '%s' does not exist in revision %ld"),
       target, base_revision_for_url);

  /* Setting an inappropriate property is not allowed (unless
     overridden by 'skip_checks', in some circumstances).  Deleting an
     inappropriate property is allowed, however, since older clients
     allowed (and other clients possibly still allow) setting it in
     the first place. */
  if (propval && svn_prop_is_svn_prop(propname))
    {
      const svn_string_t *new_value;
      struct getter_baton gb;

      gb.ra_session = ra_session;
      gb.base_revision_for_url = base_revision_for_url;
      SVN_ERR(svn_wc_canonicalize_svn_prop(&new_value, propname, propval,
                                           target, node_kind, skip_checks,
                                           get_file_for_validation, &gb, pool));
      propval = new_value;
    }

  /* Create a new commit item and add it to the array. */
  if (SVN_CLIENT__HAS_LOG_MSG_FUNC(ctx))
    {
      svn_client_commit_item3_t *item;
      const char *tmp_file;
      apr_array_header_t *commit_items = apr_array_make(pool, 1, sizeof(item));

      item = svn_client_commit_item3_create(pool);
      item->url = target;
      item->state_flags = SVN_CLIENT_COMMIT_ITEM_PROP_MODS;
      APR_ARRAY_PUSH(commit_items, svn_client_commit_item3_t *) = item;
      SVN_ERR(svn_client__get_log_msg(&message, &tmp_file, commit_items,
                                      ctx, pool));
      if (! message)
        return SVN_NO_ERROR;
    }
  else
    message = "";

  SVN_ERR(svn_client__ensure_revprop_table(&commit_revprops, revprop_table,
                                           message, ctx, pool));

  /* Fetch RA commit editor. */
  SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton,
                                    commit_revprops,
                                    commit_callback,
                                    commit_baton,
                                    NULL, TRUE, /* No lock tokens */
                                    pool));

  err = do_url_propset(propname, propval, node_kind, base_revision_for_url,
                       editor, edit_baton, pool);

  if (err)
    {
      /* At least try to abort the edit (and fs txn) before throwing err. */
      svn_error_clear(editor->abort_edit(edit_baton, pool));
      return svn_error_trace(err);
    }

  /* Close the edit. */
  return editor->close_edit(edit_baton, pool);
}