Hi!

I've noticed, that Subversion 1.8.x client can't break lock if it has a
non-infinite timeout (for example, if lock was acquired by non-standard WebDAV
client, like MS Office).  The 'svn unlock' fails with following error:
[[[
svn: E170003: Server does not support locking features
svn: E125003: Bogus date
]]]

I've discovered, that this happens because lock timeout values is parsed
incorrectly in libsvn_ra_serf (while libsvn_ra_neon works correct).

According to section 14.29 of RFC 4918 [1] the value of timeout XML element is
transferred as TimeType (see section 10.7 of the same RFC).  Instead of handling
it properly, libsvn_ra_serf tries to parse it like X-SVN-Creation-Date header
(which uses ISO-8601 date format):

[[[
if (leaving_state == TIMEOUT)
{
  if (strcmp(cdata->data, "Infinite") == 0)
    lock_ctx->lock->expiration_date = 0;
  else
    SVN_ERR(svn_time_from_cstring(&lock_ctx->lock->creation_date,
                                  cdata->data, lock_ctx->pool));
}
]]]

It seems, that code is just copy-pasted from function handle_lock():

[[[
val = serf_bucket_headers_get(headers, SVN_DAV_CREATIONDATE_HEADER);
if (val)
  {
    SVN_ERR(svn_time_from_cstring(&ctx->lock->creation_date, val,
                                  ctx->pool));
  }
]]]

I have attached a patch that fixes this problem.  The corresponding code is
taken from libsvn_ra_neon (with little tweaks from me).  Log message:
[[[
Fix lock timeout value handling in libsvn_ra_serf: parse value in correct way.

* subversion/libsvn_ra_serf/lock.c
  (locks_closed): Parse XML element value as TimeType

Patch by: Sergey Raevskiy <sergey.raevskiy{_AT_}visualsvn.com>
]]]

[1] https://tools.ietf.org/html/rfc4918


Thanks and regards,
Sergey Raevskiy
Index: subversion/libsvn_ra_serf/lock.c
===================================================================
--- subversion/libsvn_ra_serf/lock.c    (revision 1579559)
+++ subversion/libsvn_ra_serf/lock.c    (working copy)
@@ -150,9 +150,17 @@ locks_closed(svn_ra_serf__xml_estate_t *xes,
     {
       if (strcmp(cdata->data, "Infinite") == 0)
         lock_ctx->lock->expiration_date = 0;
+      else if (strncmp(cdata->data, "Second-", 7) == 0)
+        {
+          int time_offset;
+
+          SVN_ERR(svn_cstring_atoi(&time_offset, cdata->data + 7));
+          lock_ctx->lock->expiration_date = lock_ctx->lock->creation_date
+            + apr_time_from_sec(time_offset);
+        }
       else
-        SVN_ERR(svn_time_from_cstring(&lock_ctx->lock->creation_date,
-                                      cdata->data, lock_ctx->pool));
+        return svn_error_create(SVN_ERR_RA_DAV_RESPONSE_HEADER_BADNESS,
+                                NULL, _("Invalid timeout value"));
     }
   else if (leaving_state == HREF)
     {

Reply via email to