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

📄 liveprops.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * liveprops.c: mod_dav_svn live property provider functions for Subversion
 *
 * ====================================================================
 * Copyright (c) 2000-2004 CollabNet.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://subversion.tigris.org/license-1.html.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://subversion.tigris.org/.
 * ====================================================================
 */



#include <httpd.h>
#include <util_xml.h>
#include <apr_tables.h>
#include <apr_md5.h>
#include <mod_dav.h>

#include "dav_svn.h"

#include "svn_pools.h"
#include "svn_time.h"
#include "svn_dav.h"
#include "svn_md5.h"


/*
** The namespace URIs that we use. This list and the enumeration must
** stay in sync.
*/
static const char * const dav_svn_namespace_uris[] =
{
    "DAV:",
    SVN_DAV_PROP_NS_DAV,

    NULL        /* sentinel */
};
enum {
    DAV_SVN_NAMESPACE_URI_DAV,  /* the DAV: namespace URI */
    DAV_SVN_NAMESPACE_URI       /* the dav<->ra_dav namespace URI */
};

#define SVN_RO_DAV_PROP(name) \
        { DAV_SVN_NAMESPACE_URI_DAV, #name, DAV_PROPID_##name, 0 }
#define SVN_RW_DAV_PROP(name) \
        { DAV_SVN_NAMESPACE_URI_DAV, #name, DAV_PROPID_##name, 1 }
#define SVN_RO_DAV_PROP2(sym,name) \
        { DAV_SVN_NAMESPACE_URI_DAV, #name, DAV_PROPID_##sym, 0 }
#define SVN_RW_DAV_PROP2(sym,name) \
        { DAV_SVN_NAMESPACE_URI_DAV, #name, DAV_PROPID_##sym, 1 }

#define SVN_RO_SVN_PROP(sym,name) \
        { DAV_SVN_NAMESPACE_URI, #name, SVN_PROPID_##sym, 0 }
#define SVN_RW_SVN_PROP(sym,name) \
        { DAV_SVN_NAMESPACE_URI, #name, SVN_PROPID_##sym, 1 }


enum {
  SVN_PROPID_baseline_relative_path = 1,
  SVN_PROPID_md5_checksum,
  SVN_PROPID_repository_uuid
};

static const dav_liveprop_spec dav_svn_props[] =
{
  /* ### don't worry about these for a bit */
#if 0
  /* WebDAV properties */
  SVN_RO_DAV_PROP(getcontentlanguage),  /* ### make this r/w? */
#endif
  SVN_RO_DAV_PROP(getcontentlength),
  SVN_RO_DAV_PROP(getcontenttype),      /* ### make this r/w? */
  SVN_RO_DAV_PROP(getetag),
  SVN_RO_DAV_PROP(creationdate),
  SVN_RO_DAV_PROP(getlastmodified),

  /* DeltaV properties */
  SVN_RO_DAV_PROP2(baseline_collection, baseline-collection),
  SVN_RO_DAV_PROP2(checked_in, checked-in),
  SVN_RO_DAV_PROP2(version_controlled_configuration,
                   version-controlled-configuration),
  SVN_RO_DAV_PROP2(version_name, version-name),
  SVN_RO_DAV_PROP2(creator_displayname, creator-displayname),
  SVN_RO_DAV_PROP2(auto_version, auto-version),

  /* SVN properties */
  SVN_RO_SVN_PROP(baseline_relative_path, baseline-relative-path),
  SVN_RO_SVN_PROP(md5_checksum, md5-checksum),
  SVN_RO_SVN_PROP(repository_uuid, repository-uuid),

  { 0 } /* sentinel */
};

static const dav_liveprop_group dav_svn_liveprop_group =
{
    dav_svn_props,
    dav_svn_namespace_uris,
    &dav_svn_hooks_liveprop
};

/* Return the revision property PROPNAME's value in PROPVAL for
   RESOURCE in the revision COMMITTED_REV after verifying that the
   path is readable.  If the property if inaccessible, SVN_NO_ERROR is
   returned and *PROPVAL is NULL.

   This function must only be used to retrieve properties for which it
   is sufficient to have read access to a single changed path in the
   revision to have access to the revprop, e.g.
   SVN_PROP_REVISION_AUTHOR or SVN_PROP_REVISION_DATE.

   The reason for this is that we only check readability of the
   current path (which is one of the revisions' changed paths per
   definition).  If the current path is readable, the revprop is also
   readable.  While it's possible that the property is readable even
   though the current path is not readable (because another path in
   the same revision is readable), it's a silly situation worth
   ignoring to gain the extra performance. */
static svn_error_t *svn_svn_get_path_revprop(svn_string_t **propval,
                                             const dav_resource *resource,
                                             svn_revnum_t committed_rev,
                                             const char *propname,
                                             apr_pool_t *pool)
{
  dav_svn_authz_read_baton arb;
  svn_boolean_t allowed;
  svn_fs_root_t *root;

  *propval = NULL;

  arb.r = resource->info->r;
  arb.repos = resource->info->repos;
  SVN_ERR(svn_fs_revision_root(&root,
                               resource->info->repos->fs,
                               committed_rev, pool));
  SVN_ERR(dav_svn_authz_read(&allowed,
                             root,
                             resource->info->repos_path,
                             &arb, pool));

  if (! allowed)
    return SVN_NO_ERROR;

  /* Get the property of the created revision. The authz is already
     performed, so we don't need to do it here too. */
  return svn_repos_fs_revision_prop(propval,
                                    resource->info->repos->repos,
                                    committed_rev,
                                    propname,
                                    NULL, NULL, pool);
}

static dav_prop_insert dav_svn_insert_prop(const dav_resource *resource,
                                           int propid, dav_prop_insert what,
                                           apr_text_header *phdr)
{
  const char *value = NULL;
  const char *s;
  apr_pool_t *response_pool = resource->pool;
  apr_pool_t *p = resource->info->pool;
  const dav_liveprop_spec *info;
  int global_ns;
  svn_error_t *serr;

  /*
  ** None of SVN provider properties are defined if the resource does not
  ** exist. Just bail for this case.
  **
  ** Even though we state that the SVN properties are not defined, the
  ** client cannot store dead values -- we deny that thru the is_writable
  ** hook function.
  */
  if (!resource->exists)
    return DAV_PROP_INSERT_NOTSUPP;

  /* ### we may want to respond to DAV_PROPID_resourcetype for PRIVATE
     ### resources. need to think on "proper" interaction with mod_dav */

  switch (propid)
    {
    case DAV_PROPID_getlastmodified:
    case DAV_PROPID_creationdate:
      {
        /* In subversion terms, the date attached to a file's CR is
           the true "last modified" time.  However, we're defining
           creationdate in the same way.  IMO, the "creationdate" is
           really the date attached to the revision in which the item
           *first* came into existence; this would found by tracing
           back through the log of the file -- probably via
           svn_fs_revisions_changed.  gstein, is it a bad thing that
           we're currently using 'creationdate' to mean the same thing
           as 'last modified date'?  */
        const char *datestring;
        apr_time_t timeval;
        enum dav_svn_time_format format;

        /* ### for now, our global VCC has no such property. */
        if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
            && resource->info->restype == DAV_SVN_RESTYPE_VCC)
          {
            return DAV_PROP_INSERT_NOTSUPP;
          }
       
        if (propid == DAV_PROPID_creationdate)
          {
            /* Return an ISO8601 date; this is what the svn client
               expects, and rfc2518 demands it. */
            format = dav_svn_time_format_iso8601;
          }
        else /* propid == DAV_PROPID_getlastmodified */
          {
            format = dav_svn_time_format_rfc1123;
          }

        if (0 != dav_svn_get_last_modified_time (&datestring, &timeval,
                                                 resource, format, p))
          {
            return DAV_PROP_INSERT_NOTDEF;
          }

        value = apr_xml_quote_string(p, datestring, 1);
        break;
      }

    case DAV_PROPID_creator_displayname:
      {        
        svn_revnum_t committed_rev = SVN_INVALID_REVNUM;
        svn_string_t *last_author = NULL;

        /* ### for now, our global VCC has no such property. */
        if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
            && resource->info->restype == DAV_SVN_RESTYPE_VCC)
          {
            return DAV_PROP_INSERT_NOTSUPP;
          }

        if (resource->baselined && resource->type == DAV_RESOURCE_TYPE_VERSION)
          {
            /* A baseline URI. */
            committed_rev = resource->info->root.rev;
          }
        else if (resource->type == DAV_RESOURCE_TYPE_REGULAR
                 || resource->type == DAV_RESOURCE_TYPE_WORKING
                 || resource->type == DAV_RESOURCE_TYPE_VERSION)
          {
            /* Get the CR field out of the node's skel.  Notice that the
               root object might be an ID root -or- a revision root. */
            serr = svn_fs_node_created_rev(&committed_rev,
                                           resource->info->root.root,
                                           resource->info->repos_path, p);
            if (serr != NULL)
              {
                /* ### what to do? */
                svn_error_clear(serr);
                value = "###error###";
                break;
              }
          }        
        else
          {
            return DAV_PROP_INSERT_NOTSUPP;
          }

        serr = svn_svn_get_path_revprop(&last_author,
                                        resource,
                                        committed_rev,
                                        SVN_PROP_REVISION_AUTHOR,
                                        p);
        if (serr)
          {
            /* ### what to do? */
            svn_error_clear(serr);
            value = "###error###";
            break;
          }

        if (last_author == NULL)
          return DAV_PROP_INSERT_NOTDEF;

        value = apr_xml_quote_string(p, last_author->data, 1);
        break;
      }

    case DAV_PROPID_getcontentlanguage:
      /* ### need something here */
      return DAV_PROP_INSERT_NOTSUPP;
      break;

    case DAV_PROPID_getcontentlength:
      {
        svn_filesize_t len = 0;
        
        /* our property, but not defined on collection resources */
        if (resource->collection || resource->baselined)
          return DAV_PROP_INSERT_NOTSUPP;

        serr = svn_fs_file_length(&len, resource->info->root.root,
                                  resource->info->repos_path, p);
        if (serr != NULL)
          {
            svn_error_clear(serr);
            value = "0";  /* ### what to do? */
            break;
          }

        value = apr_psprintf(p, "%" SVN_FILESIZE_T_FMT, len);
        break;
      }

    case DAV_PROPID_getcontenttype:
      {
        /* The subversion client assumes that any file without an
           svn:mime-type property is of type text/plain.  So it seems
           safe (and consistent) to assume the same on the server.  */
        svn_string_t *pval;

        if (resource->baselined && resource->type == DAV_RESOURCE_TYPE_VERSION)
          return DAV_PROP_INSERT_NOTSUPP;

        if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
            && resource->info->restype == DAV_SVN_RESTYPE_VCC)
          {
            return DAV_PROP_INSERT_NOTSUPP;
          }

        serr = svn_fs_node_prop (&pval, resource->info->root.root,
                                 resource->info->repos_path,
                                 SVN_PROP_MIME_TYPE, p);

        if ((serr != NULL) || (pval == NULL))
          {
            svn_error_clear(serr);
            if (resource->collection) /* defaults for directories */
              {
                if (resource->info->repos->xslt_uri)
                  value = "text/xml";
                else
                  value = "text/html";
              }
            else
              {
                value = "text/plain"; /* default for file */
              }
          }            
        else
          {
            serr = svn_mime_type_validate (pval->data, p);
            if (serr)
              {
                /* Probably serr->apr == SVN_ERR_BAD_MIME_TYPE, but
                   there's no point even checking.  No matter what the
                   error is, we can't claim to have a mime type for
                   this resource. */
                svn_error_clear(serr);
                return DAV_PROP_INSERT_NOTDEF;
              }
            else
              value = pval->data;
          }

        break;
      }

    case DAV_PROPID_getetag:
      if (resource->type == DAV_RESOURCE_TYPE_PRIVATE
          && resource->info->restype == DAV_SVN_RESTYPE_VCC)
        {
          return DAV_PROP_INSERT_NOTSUPP;
        }

      value = dav_svn_getetag(resource, p);
      break;

    case DAV_PROPID_auto_version:
      /* we only support one autoversioning behavior, and thus only
         return this one static value; someday when we support
         locking, there are other possible values/behaviors for this. */
      if (resource->info->repos->autoversioning)
        value = "DAV:checkout-checkin";
      else
        return DAV_PROP_INSERT_NOTDEF;
      break;

    case DAV_PROPID_baseline_collection:
      /* only defined for Baselines */
      /* ### whoops. also defined for a VCC. deal with it later. */
      if (resource->type != DAV_RESOURCE_TYPE_VERSION || !resource->baselined)
        return DAV_PROP_INSERT_NOTSUPP;
      value = dav_svn_build_uri(resource->info->repos, DAV_SVN_BUILD_URI_BC,
                                resource->info->root.rev, NULL,
                                1 /* add_href */, p);
      break;

⌨️ 快捷键说明

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