Author: hwright
Date: Wed Jan 11 15:57:13 2012
New Revision: 1230112

URL: http://svn.apache.org/viewvc?rev=1230112&view=rev
Log:
Merge r1215260, r1215288, r1215374, r1215375, r1215379, r1227146 from trunk:

 * r1215260, r1215288, r1215374, r1215375, r1215379, r1227146
   Fix issue #4082 ("'svn log --with-all-revprops' over ra-dav
   intolerant of XML-unsafe property values").
   Justification:
     'Tis better to succeed than to fail.  Unless of course you're
     talking about successfully doing evil, in which case 'tis better
     to fail.  But we're not talking about doing evil here.  Unless
     you think XML is evil.  But seriously, these commits introduce a
     protocol change for WebDAV.  I suspect that might disqualify it
     in some folks' eyes from backport to a patch release rather
     automatically.  But the protocol change is (as all our other
     protocol changes are) designed to maintain compatibility across
     client and server versions.  If the client advertises support for
     the new behavior, and the server has such support, the bugfix
     logic is activitated.  A patched client will not trouble an
     unpatched server; nor vice-versa.  Further, the effects of the
     corrected behavior do not persist, so there's no dataset damage
     imposed for users who would roll this change back out of their
     systems (by reverting to a prior release).  Therefore, cmpilato
     can't think of a good reason not to backport the change.
   Notes:
     r1215260 - mod_dav_svn support for this issue
     r1215288 - libsvn_ra_neon support for this issue
     r1215374 - followup to r1215288
     r1215375 - libsvn_ra_serf support for this issue
     r1215379 - followup to r1215375
     r1227146 - fix unitialised variable
   Votes:
     +1: philip, cmpilato, rhuijben

Modified:
    subversion/branches/1.7.x/   (props changed)
    subversion/branches/1.7.x/STATUS
    subversion/branches/1.7.x/subversion/libsvn_ra_neon/log.c
    subversion/branches/1.7.x/subversion/libsvn_ra_serf/log.c
    subversion/branches/1.7.x/subversion/mod_dav_svn/reports/log.c

Propchange: subversion/branches/1.7.x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Jan 11 15:57:13 2012
@@ -70,4 +70,4 @@
 /subversion/branches/tree-conflicts:868291-873154
 /subversion/branches/tree-conflicts-notify:873926-874008
 /subversion/branches/uris-as-urls:1060426-1064427
-/subversion/trunk:1146013,1146121,1146219,1146222,1146274,1146492,1146555,1146606,1146620,1146684,1146781,1146832,1146834,1146870,1146899,1146904,1147293,1147299,1147309,1147882,1148071,1148083,1148094,1148131,1148374,1148424,1148566,1148588,1148652,1148662,1148699,1148853,1148877,1148882,1148936,1149103,1149105,1149135,1149141,1149160,1149228,1149240,1149343,1149371-1149372,1149377,1149398,1149401,1149539,1149572,1149627,1149675,1149701,1149713,1150242,1150254,1150260-1150261,1150266,1150302,1150327,1150368,1150372,1150441,1150506,1150812,1150853,1151036,1151177,1151610,1151854,1151906,1151911,1152129,1152140,1152189-1152190,1152267,1152282,1152286,1152726,1152809,1153138,1153141,1153416,1153540,1153566,1153799,1153807,1153968,1154009,1154023,1154115,1154119,1154121,1154144,1154155,1154159,1154165,1154215,1154225,1154273,1154278,1154379,1154382,1154461,1154717-1154718,1154733,1154908,1154982,1155015,1155044,1155124,1155131,1155160,1155313,1155334,1155391,1155404,1156085,115
 
6098,1156216,1156218,1156312,1156527,1156717,1156721,1156750,1156827,1156838,1157416,1158187,1158193-1158194,1158196,1158201,1158207,1158209-1158210,1158217,1158285,1158288,1158303,1158309,1158407,1158419,1158421,1158436,1158455,1158616-1158617,1158634,1158854,1158875,1158886,1158893,1158896,1158919,1158924,1158963,1159093,1159098,1159101,1159132,1159136,1159148,1159230,1159275,1159400,1159686,1159760,1159772,1160605,1160671,1160682,1160704-1160705,1160756,1161063,1161080,1161185,1161210,1161683,1161721,1162024,1162033,1162201,1162516,1162880,1162974,1162995,1163243,1163383,1163557,1163792,1163953,1164027,1164386,1164426,1164517,1164535,1164554,1164580,1164614,1164645,1164760,1164765,1166500,1166555,1166678,1167062,1167173,1167209,1167269,1167503,1167659,1167681,1169524,1169531,1169650,1171708,1173111,1173425,1173639,1174051,1174060,1174652,1174761,1174797-1174798,1174806,1175888,1176915,1176949,1177001,1177492,1177732,1178280,1178282,1178942,1179680,1179767,1180154,1181090,
 
1181110,1181155,1181215,1181609,1181666,1182115,1182527,1182771,1182904,1182909,1183054,1183263,1183347,1185222,1185242,1185280,1185282,1185730,1185738,1185746,1185763,1185768,1185886,1185911,1185918,1186059,1186092,1186101,1186107,1186109,1186121,1186231,1186240,1186422,1186434,1186732,1186755,1186784,1186815,1186928,1186944,1186981,1186983,1187311,1187676,1187695,1188609,1188652,1188677,1188762,1188774,1189190,1189261,1189395,1189580,1189665,1195480,1197135,1197998,1199876,1199950,1200837,1201002,1201824,1202135,1202187,1202630,1202807,1203546,1203651,1203653,1204167,1204478,1204610,1204673,1205193,1205726,1205839,1205848,1206523,1206533,1207858,1207949,1208840,1209631,1209654,1210195,1211483,1211859,1211885,1212476,1212482,1212484,1213331,1213673,1213681,1213690,1213711,1213716,1214139,1220742,1220750,1221793,1222521,1222693,1229252
+/subversion/trunk:1146013,1146121,1146219,1146222,1146274,1146492,1146555,1146606,1146620,1146684,1146781,1146832,1146834,1146870,1146899,1146904,1147293,1147299,1147309,1147882,1148071,1148083,1148094,1148131,1148374,1148424,1148566,1148588,1148652,1148662,1148699,1148853,1148877,1148882,1148936,1149103,1149105,1149135,1149141,1149160,1149228,1149240,1149343,1149371-1149372,1149377,1149398,1149401,1149539,1149572,1149627,1149675,1149701,1149713,1150242,1150254,1150260-1150261,1150266,1150302,1150327,1150368,1150372,1150441,1150506,1150812,1150853,1151036,1151177,1151610,1151854,1151906,1151911,1152129,1152140,1152189-1152190,1152267,1152282,1152286,1152726,1152809,1153138,1153141,1153416,1153540,1153566,1153799,1153807,1153968,1154009,1154023,1154115,1154119,1154121,1154144,1154155,1154159,1154165,1154215,1154225,1154273,1154278,1154379,1154382,1154461,1154717-1154718,1154733,1154908,1154982,1155015,1155044,1155124,1155131,1155160,1155313,1155334,1155391,1155404,1156085,115
 
6098,1156216,1156218,1156312,1156527,1156717,1156721,1156750,1156827,1156838,1157416,1158187,1158193-1158194,1158196,1158201,1158207,1158209-1158210,1158217,1158285,1158288,1158303,1158309,1158407,1158419,1158421,1158436,1158455,1158616-1158617,1158634,1158854,1158875,1158886,1158893,1158896,1158919,1158924,1158963,1159093,1159098,1159101,1159132,1159136,1159148,1159230,1159275,1159400,1159686,1159760,1159772,1160605,1160671,1160682,1160704-1160705,1160756,1161063,1161080,1161185,1161210,1161683,1161721,1162024,1162033,1162201,1162516,1162880,1162974,1162995,1163243,1163383,1163557,1163792,1163953,1164027,1164386,1164426,1164517,1164535,1164554,1164580,1164614,1164645,1164760,1164765,1166500,1166555,1166678,1167062,1167173,1167209,1167269,1167503,1167659,1167681,1169524,1169531,1169650,1171708,1173111,1173425,1173639,1174051,1174060,1174652,1174761,1174797-1174798,1174806,1175888,1176915,1176949,1177001,1177492,1177732,1178280,1178282,1178942,1179680,1179767,1180154,1181090,
 
1181110,1181155,1181215,1181609,1181666,1182115,1182527,1182771,1182904,1182909,1183054,1183263,1183347,1185222,1185242,1185280,1185282,1185730,1185738,1185746,1185763,1185768,1185886,1185911,1185918,1186059,1186092,1186101,1186107,1186109,1186121,1186231,1186240,1186422,1186434,1186732,1186755,1186784,1186815,1186928,1186944,1186981,1186983,1187311,1187676,1187695,1188609,1188652,1188677,1188762,1188774,1189190,1189261,1189395,1189580,1189665,1195480,1197135,1197998,1199876,1199950,1200837,1201002,1201824,1202135,1202187,1202630,1202807,1203546,1203651,1203653,1204167,1204478,1204610,1204673,1205193,1205726,1205839,1205848,1206523,1206533,1207858,1207949,1208840,1209631,1209654,1210195,1211483,1211859,1211885,1212476,1212482,1212484,1213331,1213673,1213681,1213690,1213711,1213716,1214139,1215260,1215288,1215374-1215375,1215379,1220742,1220750,1221793,1222521,1222693,1227146,1229252

Modified: subversion/branches/1.7.x/STATUS
URL: 
http://svn.apache.org/viewvc/subversion/branches/1.7.x/STATUS?rev=1230112&r1=1230111&r2=1230112&view=diff
==============================================================================
--- subversion/branches/1.7.x/STATUS (original)
+++ subversion/branches/1.7.x/STATUS Wed Jan 11 15:57:13 2012
@@ -187,33 +187,3 @@ Veto-blocked changes:
 
 Approved changes:
 =================
-
- * r1215260, r1215288, r1215374, r1215375, r1215379, r1227146
-   Fix issue #4082 ("'svn log --with-all-revprops' over ra-dav
-   intolerant of XML-unsafe property values").
-   Justification:
-     'Tis better to succeed than to fail.  Unless of course you're
-     talking about successfully doing evil, in which case 'tis better
-     to fail.  But we're not talking about doing evil here.  Unless
-     you think XML is evil.  But seriously, these commits introduce a
-     protocol change for WebDAV.  I suspect that might disqualify it
-     in some folks' eyes from backport to a patch release rather
-     automatically.  But the protocol change is (as all our other
-     protocol changes are) designed to maintain compatibility across
-     client and server versions.  If the client advertises support for
-     the new behavior, and the server has such support, the bugfix
-     logic is activitated.  A patched client will not trouble an
-     unpatched server; nor vice-versa.  Further, the effects of the
-     corrected behavior do not persist, so there's no dataset damage
-     imposed for users who would roll this change back out of their
-     systems (by reverting to a prior release).  Therefore, cmpilato
-     can't think of a good reason not to backport the change.
-   Notes:
-     r1215260 - mod_dav_svn support for this issue
-     r1215288 - libsvn_ra_neon support for this issue
-     r1215374 - followup to r1215288
-     r1215375 - libsvn_ra_serf support for this issue
-     r1215379 - followup to r1215375
-     r1227146 - fix unitialised variable
-   Votes:
-     +1: philip, cmpilato, rhuijben

Modified: subversion/branches/1.7.x/subversion/libsvn_ra_neon/log.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/libsvn_ra_neon/log.c?rev=1230112&r1=1230111&r2=1230112&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/libsvn_ra_neon/log.c (original)
+++ subversion/branches/1.7.x/subversion/libsvn_ra_neon/log.c Wed Jan 11 
15:57:13 2012
@@ -32,6 +32,7 @@
 #include "svn_error.h"
 #include "svn_pools.h"
 #include "svn_path.h"
+#include "svn_base64.h"
 #include "svn_xml.h"
 #include "svn_props.h"
 
@@ -52,6 +53,8 @@ struct log_baton
   */
   svn_stringbuf_t *want_cdata;
   svn_stringbuf_t *cdata;
+  const char *cdata_encoding; /* encoding of CDATA (NULL or "base64") */
+
   /* Allocate log message information.
    * NOTE: this pool may be cleared multiple times as log messages are
    * received.
@@ -162,14 +165,27 @@ log_start_element(int *elem, void *baton
     case ELEM_comment:
       lb->want_cdata = lb->cdata;
       svn_stringbuf_setempty(lb->cdata);
+      lb->cdata_encoding = NULL;
+          
+      /* Some tags might contain encoded CDATA. */
+      if ((elm->id == ELEM_comment) ||
+          (elm->id == ELEM_creator_displayname) ||
+          (elm->id == ELEM_log_date) ||
+          (elm->id == ELEM_rev_prop))
+        {
+          lb->cdata_encoding = svn_xml_get_attr_value("encoding", atts);
+          if (lb->cdata_encoding)
+            lb->cdata_encoding = apr_pstrdup(lb->subpool, lb->cdata_encoding);
+        }
+
+      /* revprop tags have names. */
       if (elm->id == ELEM_revprop)
         {
-          lb->revprop_name = apr_pstrdup(lb->subpool,
-                                         svn_xml_get_attr_value("name",
-                                                                atts));
-          if (lb->revprop_name == NULL)
+          const char *revprop_name = svn_xml_get_attr_value("name", atts);
+          if (revprop_name == NULL)
             return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
                                      _("Missing name attr in revprop 
element"));
+          lb->revprop_name = apr_pstrdup(lb->subpool, revprop_name);
         }
       break;
     case ELEM_has_children:
@@ -235,6 +251,36 @@ log_start_element(int *elem, void *baton
   return SVN_NO_ERROR;
 }
 
+/*
+ * Set *DECODED_CDATA to a copy of current CDATA being tracked in LB,
+ * decoded as necessary, and allocated from LB->subpool.
+ */
+static svn_error_t *
+maybe_decode_log_cdata(const svn_string_t **decoded_cdata,
+                       struct log_baton *lb)
+{
+  if (lb->cdata_encoding)
+    {
+      svn_string_t in;
+      in.data = lb->cdata->data;
+      in.len = lb->cdata->len;
+
+      /* Check for a known encoding type.  This is easy -- there's
+         only one.  */
+      if (strcmp(lb->cdata_encoding, "base64") != 0)
+        return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);
+
+      *decoded_cdata = svn_base64_decode_string(&in, lb->subpool);
+    }
+  else
+    {
+      *decoded_cdata = svn_string_create_from_buf(lb->cdata, lb->subpool);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+                       
 
 /*
  * This implements the `svn_ra_neon__xml_endelm_cb' prototype.
@@ -244,6 +290,10 @@ log_end_element(void *baton, int state,
                 const char *nspace, const char *name)
 {
   struct log_baton *lb = baton;
+  const svn_string_t *decoded_cdata;
+
+  if (lb->want_cdata)
+    SVN_ERR(maybe_decode_log_cdata(&decoded_cdata, lb));
 
   switch (state)
     {
@@ -256,8 +306,7 @@ log_end_element(void *baton, int state,
           if (! lb->log_entry->revprops)
             lb->log_entry->revprops = apr_hash_make(lb->subpool);
           apr_hash_set(lb->log_entry->revprops, SVN_PROP_REVISION_AUTHOR,
-                       APR_HASH_KEY_STRING,
-                       svn_string_create_from_buf(lb->cdata, lb->subpool));
+                       APR_HASH_KEY_STRING, decoded_cdata);
         }
       break;
     case ELEM_log_date:
@@ -266,8 +315,7 @@ log_end_element(void *baton, int state,
           if (! lb->log_entry->revprops)
             lb->log_entry->revprops = apr_hash_make(lb->subpool);
           apr_hash_set(lb->log_entry->revprops, SVN_PROP_REVISION_DATE,
-                       APR_HASH_KEY_STRING,
-                       svn_string_create_from_buf(lb->cdata, lb->subpool));
+                       APR_HASH_KEY_STRING, decoded_cdata);
         }
       break;
     case ELEM_added_path:
@@ -289,8 +337,7 @@ log_end_element(void *baton, int state,
       if (! lb->log_entry->revprops)
         lb->log_entry->revprops = apr_hash_make(lb->subpool);
       apr_hash_set(lb->log_entry->revprops, lb->revprop_name,
-                   APR_HASH_KEY_STRING,
-                   svn_string_create_from_buf(lb->cdata, lb->subpool));
+                   APR_HASH_KEY_STRING, decoded_cdata);
       break;
     case ELEM_comment:
       if (lb->want_message)
@@ -298,8 +345,7 @@ log_end_element(void *baton, int state,
           if (! lb->log_entry->revprops)
             lb->log_entry->revprops = apr_hash_make(lb->subpool);
           apr_hash_set(lb->log_entry->revprops, SVN_PROP_REVISION_LOG,
-                       APR_HASH_KEY_STRING,
-                       svn_string_create_from_buf(lb->cdata, lb->subpool));
+                       APR_HASH_KEY_STRING, decoded_cdata);
         }
       break;
     case ELEM_log_item:
@@ -380,8 +426,8 @@ svn_error_t * svn_ra_neon__get_log(svn_r
      Maybe Greg can explain?  Meanwhile, I'm tentatively using
      "request_*" for my local vars below. */
 
-  static const char log_request_head[]
-    = "<S:log-report xmlns:S=\"" SVN_XML_NAMESPACE "\">" DEBUG_CR;
+  static const char log_request_head[] = "<S:log-report xmlns:S=\""
+    SVN_XML_NAMESPACE "\">" DEBUG_CR "<S:encode-binary-props/>";
 
   static const char log_request_tail[] = "</S:log-report>" DEBUG_CR;
 
@@ -494,6 +540,7 @@ svn_error_t * svn_ra_neon__get_log(svn_r
   lb.cdata = svn_stringbuf_create("", pool);
   lb.log_entry = svn_log_entry_create(pool);
   lb.want_cdata = NULL;
+  lb.cdata_encoding = NULL;
   reset_log_item(&lb);
 
   /* ras's URL may not exist in HEAD, and thus it's not safe to send

Modified: subversion/branches/1.7.x/subversion/libsvn_ra_serf/log.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/libsvn_ra_serf/log.c?rev=1230112&r1=1230111&r2=1230112&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/libsvn_ra_serf/log.c (original)
+++ subversion/branches/1.7.x/subversion/libsvn_ra_serf/log.c Wed Jan 11 
15:57:13 2012
@@ -32,6 +32,7 @@
 #include "svn_pools.h"
 #include "svn_ra.h"
 #include "svn_dav.h"
+#include "svn_base64.h"
 #include "svn_xml.h"
 #include "svn_config.h"
 #include "svn_path.h"
@@ -67,9 +68,12 @@ typedef enum log_state_e {
 typedef struct log_info_t {
   apr_pool_t *pool;
 
-  /* The currently collected value as we build it up */
+  /* The currently collected value as we build it up, and its wire
+   * encoding (if any).
+   */
   const char *tmp;
   apr_size_t tmp_len;
+  const char *tmp_encoding;
 
   /* Temporary change path - ultimately inserted into changed_paths hash. */
   svn_log_changed_path2_t *tmp_path;
@@ -114,7 +118,8 @@ typedef struct log_context_t {
 static log_info_t *
 push_state(svn_ra_serf__xml_parser_t *parser,
            log_context_t *log_ctx,
-           log_state_e state)
+           log_state_e state,
+           const char **attrs)
 {
   svn_ra_serf__xml_push_state(parser, state);
 
@@ -152,6 +157,10 @@ push_state(svn_ra_serf__xml_parser_t *pa
     {
       log_info_t *info = parser->state->private;
 
+      info->tmp_encoding = svn_xml_get_attr_value("encoding", attrs);
+      if (info->tmp_encoding)
+        info->tmp_encoding = apr_pstrdup(info->pool, info->tmp_encoding);
+
       if (!info->log_entry->revprops)
         {
           info->log_entry->revprops = apr_hash_make(info->pool);
@@ -192,12 +201,12 @@ start_log(svn_ra_serf__xml_parser_t *par
   if (state == NONE &&
       strcmp(name.name, "log-report") == 0)
     {
-      push_state(parser, log_ctx, REPORT);
+      push_state(parser, log_ctx, REPORT, attrs);
     }
   else if (state == REPORT &&
            strcmp(name.name, "log-item") == 0)
     {
-      push_state(parser, log_ctx, ITEM);
+      push_state(parser, log_ctx, ITEM, attrs);
     }
   else if (state == ITEM)
     {
@@ -205,44 +214,43 @@ start_log(svn_ra_serf__xml_parser_t *par
 
       if (strcmp(name.name, SVN_DAV__VERSION_NAME) == 0)
         {
-          push_state(parser, log_ctx, VERSION);
+          push_state(parser, log_ctx, VERSION, attrs);
         }
       else if (strcmp(name.name, "creator-displayname") == 0)
         {
-          push_state(parser, log_ctx, CREATOR);
+          info = push_state(parser, log_ctx, CREATOR, attrs);
         }
       else if (strcmp(name.name, "date") == 0)
         {
-          push_state(parser, log_ctx, DATE);
+          info = push_state(parser, log_ctx, DATE, attrs);
         }
       else if (strcmp(name.name, "comment") == 0)
         {
-          push_state(parser, log_ctx, COMMENT);
+          info = push_state(parser, log_ctx, COMMENT, attrs);
         }
       else if (strcmp(name.name, "revprop") == 0)
         {
-          const char *revprop_name;
-          info = push_state(parser, log_ctx, REVPROP);
-          revprop_name = svn_xml_get_attr_value("name", attrs);
+          const char *revprop_name =
+            svn_xml_get_attr_value("name", attrs);
           if (revprop_name == NULL)
             return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
                                      _("Missing name attr in revprop 
element"));
-
+          info = push_state(parser, log_ctx, REVPROP, attrs);
           info->revprop_name = apr_pstrdup(info->pool, revprop_name);
         }
       else if (strcmp(name.name, "has-children") == 0)
         {
-          push_state(parser, log_ctx, HAS_CHILDREN);
+          push_state(parser, log_ctx, HAS_CHILDREN, attrs);
         }
       else if (strcmp(name.name, "subtractive-merge") == 0)
         {
-          push_state(parser, log_ctx, SUBTRACTIVE_MERGE);
+          push_state(parser, log_ctx, SUBTRACTIVE_MERGE, attrs);
         }
       else if (strcmp(name.name, "added-path") == 0)
         {
           const char *copy_path, *copy_rev_str;
 
-          info = push_state(parser, log_ctx, ADDED_PATH);
+          info = push_state(parser, log_ctx, ADDED_PATH, attrs);
           info->tmp_path->action = 'A';
 
           copy_path = svn_xml_get_attr_value("copyfrom-path", attrs);
@@ -266,7 +274,7 @@ start_log(svn_ra_serf__xml_parser_t *par
         {
           const char *copy_path, *copy_rev_str;
 
-          info = push_state(parser, log_ctx, REPLACED_PATH);
+          info = push_state(parser, log_ctx, REPLACED_PATH, attrs);
           info->tmp_path->action = 'R';
 
           copy_path = svn_xml_get_attr_value("copyfrom-path", attrs);
@@ -288,14 +296,14 @@ start_log(svn_ra_serf__xml_parser_t *par
         }
       else if (strcmp(name.name, "deleted-path") == 0)
         {
-          info = push_state(parser, log_ctx, DELETED_PATH);
+          info = push_state(parser, log_ctx, DELETED_PATH, attrs);
           info->tmp_path->action = 'D';
 
           SVN_ERR(read_changed_path_attributes(info->tmp_path, attrs));
         }
       else if (strcmp(name.name, "modified-path") == 0)
         {
-          info = push_state(parser, log_ctx, MODIFIED_PATH);
+          info = push_state(parser, log_ctx, MODIFIED_PATH, attrs);
           info->tmp_path->action = 'M';
 
           SVN_ERR(read_changed_path_attributes(info->tmp_path, attrs));
@@ -305,6 +313,39 @@ start_log(svn_ra_serf__xml_parser_t *par
   return SVN_NO_ERROR;
 }
 
+/*
+ * Set *DECODED_CDATA to a copy of current CDATA being tracked in INFO,
+ * decoded as necessary, and allocated from INFO->pool..
+ */
+static svn_error_t *
+maybe_decode_log_cdata(const svn_string_t **decoded_cdata,
+                       log_info_t *info)
+{
+  if (info->tmp_encoding)
+    {
+      svn_string_t in;
+      in.data = info->tmp;
+      in.len = info->tmp_len;
+
+      /* Check for a known encoding type.  This is easy -- there's
+         only one.  */
+      if (strcmp(info->tmp_encoding, "base64") != 0)
+        {
+          return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
+                                   _("Unsupported encoding '%s'"),
+                                   info->tmp_encoding);
+        }
+
+      *decoded_cdata = svn_base64_decode_string(&in, info->pool);
+    }
+  else
+    {
+      *decoded_cdata = svn_string_ncreate(info->tmp, info->tmp_len,
+                                          info->pool);
+    }
+  return SVN_NO_ERROR;
+}
+
 static svn_error_t *
 end_log(svn_ra_serf__xml_parser_t *parser,
         void *userData,
@@ -361,10 +402,10 @@ end_log(svn_ra_serf__xml_parser_t *parse
     {
       if (log_ctx->want_author)
         {
+          const svn_string_t *decoded_cdata;
+          SVN_ERR(maybe_decode_log_cdata(&decoded_cdata, info));
           apr_hash_set(info->log_entry->revprops, SVN_PROP_REVISION_AUTHOR,
-                       APR_HASH_KEY_STRING,
-                       svn_string_ncreate(info->tmp, info->tmp_len,
-                                          info->pool));
+                       APR_HASH_KEY_STRING, decoded_cdata);
         }
       info->tmp_len = 0;
       svn_ra_serf__xml_pop_state(parser);
@@ -374,10 +415,10 @@ end_log(svn_ra_serf__xml_parser_t *parse
     {
       if (log_ctx->want_date)
         {
+          const svn_string_t *decoded_cdata;
+          SVN_ERR(maybe_decode_log_cdata(&decoded_cdata, info));
           apr_hash_set(info->log_entry->revprops, SVN_PROP_REVISION_DATE,
-                       APR_HASH_KEY_STRING,
-                       svn_string_ncreate(info->tmp, info->tmp_len,
-                                          info->pool));
+                       APR_HASH_KEY_STRING, decoded_cdata);
         }
       info->tmp_len = 0;
       svn_ra_serf__xml_pop_state(parser);
@@ -387,19 +428,20 @@ end_log(svn_ra_serf__xml_parser_t *parse
     {
       if (log_ctx->want_message)
         {
+          const svn_string_t *decoded_cdata;
+          SVN_ERR(maybe_decode_log_cdata(&decoded_cdata, info));
           apr_hash_set(info->log_entry->revprops, SVN_PROP_REVISION_LOG,
-                       APR_HASH_KEY_STRING,
-                       svn_string_ncreate(info->tmp, info->tmp_len,
-                                          info->pool));
+                       APR_HASH_KEY_STRING, decoded_cdata);
         }
       info->tmp_len = 0;
       svn_ra_serf__xml_pop_state(parser);
     }
   else if (state == REVPROP)
     {
+      const svn_string_t *decoded_cdata;
+      SVN_ERR(maybe_decode_log_cdata(&decoded_cdata, info));
       apr_hash_set(info->log_entry->revprops, info->revprop_name,
-                   APR_HASH_KEY_STRING,
-                   svn_string_ncreate(info->tmp, info->tmp_len, info->pool));
+                   APR_HASH_KEY_STRING, decoded_cdata);
       info->tmp_len = 0;
       svn_ra_serf__xml_pop_state(parser);
     }
@@ -562,6 +604,10 @@ create_log_body(serf_bucket_t **body_bkt
         }
     }
 
+  svn_ra_serf__add_tag_buckets(buckets,
+                               "S:encode-binary-props", NULL,
+                               alloc);
+
   svn_ra_serf__add_close_tag_buckets(buckets, alloc,
                                      "S:log-report");
 

Modified: subversion/branches/1.7.x/subversion/mod_dav_svn/reports/log.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/mod_dav_svn/reports/log.c?rev=1230112&r1=1230111&r2=1230112&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/mod_dav_svn/reports/log.c (original)
+++ subversion/branches/1.7.x/subversion/mod_dav_svn/reports/log.c Wed Jan 11 
15:57:13 2012
@@ -30,6 +30,7 @@
 #include "svn_repos.h"
 #include "svn_string.h"
 #include "svn_types.h"
+#include "svn_base64.h"
 #include "svn_xml.h"
 #include "svn_path.h"
 #include "svn_dav.h"
@@ -61,6 +62,9 @@ struct log_receiver_baton
 
   /* whether the client requested any custom revprops */
   svn_boolean_t requested_custom_revprops;
+
+  /* whether the client can handle encoded binary property values */
+  svn_boolean_t encode_binary_props;
 };
 
 
@@ -119,35 +123,50 @@ log_receiver(void *baton,
            hi = apr_hash_next(hi))
         {
           char *name;
-          svn_string_t *value;
+          void *val;
+          const svn_string_t *value;
+          const char *encoding_str = "";
 
           svn_pool_clear(iterpool);
-          apr_hash_this(hi, (void *)&name, NULL, (void *)&value);
+          apr_hash_this(hi, (void *)&name, NULL, &val);
+          value = val;
+
+          /* If the client is okay with us encoding binary (or really,
+             any non-XML-safe) property values, do so as necessary. */
+          if (lrb->encode_binary_props)
+            {
+              if (! svn_xml_is_xml_safe(value->data, value->len))
+                {
+                  value = svn_base64_encode_string2(value, TRUE, iterpool);
+                  encoding_str = " encoding=\"base64\"";
+                }
+            }
+
           if (strcmp(name, SVN_PROP_REVISION_AUTHOR) == 0)
             SVN_ERR(dav_svn__brigade_printf
                     (lrb->bb, lrb->output,
-                     "<D:creator-displayname>%s</D:creator-displayname>"
-                     DEBUG_CR,
+                     "<D:creator-displayname%s>%s</D:creator-displayname>"
+                     DEBUG_CR, encoding_str,
                      apr_xml_quote_string(iterpool, value->data, 0)));
           else if (strcmp(name, SVN_PROP_REVISION_DATE) == 0)
             /* ### this should be DAV:creation-date, but we need to format
                ### that date a bit differently */
             SVN_ERR(dav_svn__brigade_printf
                     (lrb->bb, lrb->output,
-                     "<S:date>%s</S:date>" DEBUG_CR,
+                     "<S:date%s>%s</S:date>" DEBUG_CR, encoding_str,
                      apr_xml_quote_string(iterpool, value->data, 0)));
           else if (strcmp(name, SVN_PROP_REVISION_LOG) == 0)
             SVN_ERR(dav_svn__brigade_printf
                     (lrb->bb, lrb->output,
-                     "<D:comment>%s</D:comment>" DEBUG_CR,
+                     "<D:comment%s>%s</D:comment>" DEBUG_CR, encoding_str,
                      apr_xml_quote_string(pool,
                                           svn_xml_fuzzy_escape(value->data,
                                                                iterpool), 0)));
           else
             SVN_ERR(dav_svn__brigade_printf
                     (lrb->bb, lrb->output,
-                     "<S:revprop name=\"%s\">%s</S:revprop>" DEBUG_CR,
-                     apr_xml_quote_string(iterpool, name, 0),
+                     "<S:revprop name=\"%s\"%s>%s</S:revprop>" DEBUG_CR,
+                     apr_xml_quote_string(iterpool, name, 0), encoding_str,
                      apr_xml_quote_string(iterpool, value->data, 0)));
         }
     }
@@ -305,6 +324,7 @@ dav_svn__log_report(const dav_resource *
   seen_revprop_element = FALSE;
 
   lrb.requested_custom_revprops = FALSE;
+  lrb.encode_binary_props = FALSE;
   for (child = doc->root->first_child; child != NULL; child = child->next)
     {
       /* if this element isn't one of ours, then skip it */
@@ -333,6 +353,8 @@ dav_svn__log_report(const dav_resource *
         strict_node_history = TRUE; /* presence indicates positivity */
       else if (strcmp(child->name, "include-merged-revisions") == 0)
         include_merged_revisions = TRUE; /* presence indicates positivity */
+      else if (strcmp(child->name, "encode-binary-props") == 0)
+        lrb.encode_binary_props = TRUE; /* presence indicates positivity */
       else if (strcmp(child->name, "all-revprops") == 0)
         {
           revprops = NULL; /* presence indicates fetch all revprops */


Reply via email to