OSDN Git Service

Success build TortoiseMerge.
[tortoisegit/TortoiseGitJp.git] / src / TortoiseMerge / libsvn_diff / cmdline.c
1 /*\r
2  * cmdline.c :  Helpers for command-line programs.\r
3  *\r
4  * ====================================================================\r
5  * Copyright (c) 2003-2009 CollabNet.  All rights reserved.\r
6  *\r
7  * This software is licensed as described in the file COPYING, which\r
8  * you should have received as part of this distribution.  The terms\r
9  * are also available at http://subversion.tigris.org/license-1.html.\r
10  * If newer versions of this license are posted there, you may use a\r
11  * newer version instead, at your option.\r
12  *\r
13  * This software consists of voluntary contributions made by many\r
14  * individuals.  For exact contribution history, see the revision\r
15  * history and logs, available at http://subversion.tigris.org/.\r
16  * ====================================================================\r
17  */\r
18 \r
19 \r
20 #include <stdlib.h>             /* for atexit() */\r
21 #include <stdio.h>              /* for setvbuf() */\r
22 #include <locale.h>             /* for setlocale() */\r
23 \r
24 #ifndef WIN32\r
25 #include <sys/types.h>\r
26 #include <sys/stat.h>\r
27 #include <fcntl.h>\r
28 #include <unistd.h>\r
29 #endif\r
30 \r
31 #include <apr_errno.h>          /* for apr_strerror */\r
32 #include <apr_general.h>        /* for apr_initialize/apr_terminate */\r
33 #include <apr_atomic.h>         /* for apr_atomic_init */\r
34 #include <apr_strings.h>        /* for apr_snprintf */\r
35 #include <apr_pools.h>\r
36 \r
37 #include "svn_cmdline.h"\r
38 #include "svn_dso.h"\r
39 #include "svn_path.h"\r
40 #include "svn_pools.h"\r
41 #include "svn_error.h"\r
42 #include "svn_nls.h"\r
43 #include "svn_utf.h"\r
44 #include "svn_auth.h"\r
45 #include "svn_version.h"\r
46 #include "svn_xml.h"\r
47 #include "svn_base64.h"\r
48 #include "svn_config.h"\r
49 \r
50 //#include "private/svn_cmdline_private.h"\r
51 //#include "private/svn_utf_private.h"\r
52 \r
53 //#include "svn_private_config.h"\r
54 \r
55 //#include "win32_crashrpt.h"\r
56 \r
57 /* The stdin encoding. If null, it's the same as the native encoding. */\r
58 static const char *input_encoding = NULL;\r
59 \r
60 /* The stdout encoding. If null, it's the same as the native encoding. */\r
61 static const char *output_encoding = NULL;\r
62 \r
63 #if 0\r
64 int\r
65 svn_cmdline_init(const char *progname, FILE *error_stream)\r
66 {\r
67   apr_status_t status;\r
68   apr_pool_t *pool;\r
69   svn_error_t *err;\r
70 \r
71 #ifndef WIN32\r
72   {\r
73     struct stat st;\r
74 \r
75     /* The following makes sure that file descriptors 0 (stdin), 1\r
76        (stdout) and 2 (stderr) will not be "reused", because if\r
77        e.g. file descriptor 2 would be reused when opening a file, a\r
78        write to stderr would write to that file and most likely\r
79        corrupt it. */\r
80     if ((fstat(0, &st) == -1 && open("/dev/null", O_RDONLY) == -1) ||\r
81         (fstat(1, &st) == -1 && open("/dev/null", O_WRONLY) == -1) ||\r
82         (fstat(2, &st) == -1 && open("/dev/null", O_WRONLY) == -1))\r
83       {\r
84         if (error_stream)\r
85           fprintf(error_stream, "%s: error: cannot open '/dev/null'\n",\r
86                   progname);\r
87         return EXIT_FAILURE;\r
88       }\r
89   }\r
90 #endif\r
91 \r
92   /* Ignore any errors encountered while attempting to change stream\r
93      buffering, as the streams should retain their default buffering\r
94      modes. */\r
95   if (error_stream)\r
96     setvbuf(error_stream, NULL, _IONBF, 0);\r
97 #ifndef WIN32\r
98   setvbuf(stdout, NULL, _IOLBF, 0);\r
99 #endif\r
100 \r
101 #ifdef WIN32\r
102 #if _MSC_VER < 1400\r
103   /* Initialize the input and output encodings. */\r
104   {\r
105     static char input_encoding_buffer[16];\r
106     static char output_encoding_buffer[16];\r
107 \r
108     apr_snprintf(input_encoding_buffer, sizeof input_encoding_buffer,\r
109                  "CP%u", (unsigned) GetConsoleCP());\r
110     input_encoding = input_encoding_buffer;\r
111 \r
112     apr_snprintf(output_encoding_buffer, sizeof output_encoding_buffer,\r
113                  "CP%u", (unsigned) GetConsoleOutputCP());\r
114     output_encoding = output_encoding_buffer;\r
115   }\r
116 #endif /* _MSC_VER < 1400 */\r
117 \r
118 #ifdef SVN_USE_WIN32_CRASHHANDLER\r
119   /* Attach (but don't load) the crash handler */\r
120   SetUnhandledExceptionFilter(svn__unhandled_exception_filter);\r
121 #endif\r
122 \r
123 #endif /* WIN32 */\r
124 \r
125   /* C programs default to the "C" locale. But because svn is supposed\r
126      to be i18n-aware, it should inherit the default locale of its\r
127      environment.  */\r
128   if (!setlocale(LC_ALL, "")\r
129       && !setlocale(LC_CTYPE, ""))\r
130     {\r
131       if (error_stream)\r
132         {\r
133           const char *env_vars[] = { "LC_ALL", "LC_CTYPE", "LANG", NULL };\r
134           const char **env_var = &env_vars[0], *env_val = NULL;\r
135           while (*env_var)\r
136             {\r
137               env_val = getenv(*env_var);\r
138               if (env_val && env_val[0])\r
139                 break;\r
140               ++env_var;\r
141             }\r
142 \r
143           if (!*env_var)\r
144             {\r
145               /* Unlikely. Can setlocale fail if no env vars are set? */\r
146               --env_var;\r
147               env_val = "not set";\r
148             }\r
149 \r
150           fprintf(error_stream,\r
151                   "%s: warning: cannot set LC_CTYPE locale\n"\r
152                   "%s: warning: environment variable %s is %s\n"\r
153                   "%s: warning: please check that your locale name is correct\n",\r
154                   progname, progname, *env_var, env_val, progname);\r
155         }\r
156     }\r
157 \r
158   /* Initialize the APR subsystem, and register an atexit() function\r
159      to Uninitialize that subsystem at program exit. */\r
160   status = apr_initialize();\r
161   if (status)\r
162     {\r
163       if (error_stream)\r
164         {\r
165           char buf[1024];\r
166           apr_strerror(status, buf, sizeof(buf) - 1);\r
167           fprintf(error_stream,\r
168                   "%s: error: cannot initialize APR: %s\n",\r
169                   progname, buf);\r
170         }\r
171       return EXIT_FAILURE;\r
172     }\r
173 \r
174   /* This has to happen before any pools are created. */\r
175   if ((err = svn_dso_initialize2()))\r
176     {\r
177       if (error_stream && err->message)\r
178         fprintf(error_stream, "%s", err->message);\r
179 \r
180       svn_error_clear(err);\r
181       return EXIT_FAILURE;\r
182     }\r
183 \r
184   if (0 > atexit(apr_terminate))\r
185     {\r
186       if (error_stream)\r
187         fprintf(error_stream,\r
188                 "%s: error: atexit registration failed\n",\r
189                 progname);\r
190       return EXIT_FAILURE;\r
191     }\r
192 \r
193   /* Create a pool for use by the UTF-8 routines.  It will be cleaned\r
194      up by APR at exit time. */\r
195   pool = svn_pool_create(NULL);\r
196   svn_utf_initialize(pool);\r
197 \r
198   if ((err = svn_nls_init()))\r
199     {\r
200       if (error_stream && err->message)\r
201         fprintf(error_stream, "%s", err->message);\r
202 \r
203       svn_error_clear(err);\r
204       return EXIT_FAILURE;\r
205     }\r
206 \r
207   return EXIT_SUCCESS;\r
208 }\r
209 #endif \r
210 \r
211 svn_error_t *\r
212 svn_cmdline_cstring_from_utf8(const char **dest,\r
213                               const char *src,\r
214                               apr_pool_t *pool)\r
215 {\r
216   if (output_encoding == NULL)\r
217     return svn_utf_cstring_from_utf8(dest, src, pool);\r
218   else\r
219     return svn_utf_cstring_from_utf8_ex2(dest, src, output_encoding, pool);\r
220 }\r
221 \r
222 const char *\r
223 svn_cmdline_cstring_from_utf8_fuzzy(const char *src,\r
224                                     apr_pool_t *pool)\r
225 {\r
226   return svn_utf__cstring_from_utf8_fuzzy(src, pool,\r
227                                           svn_cmdline_cstring_from_utf8);\r
228 }\r
229 \r
230 \r
231 svn_error_t *\r
232 svn_cmdline_cstring_to_utf8(const char **dest,\r
233                             const char *src,\r
234                             apr_pool_t *pool)\r
235 {\r
236   if (input_encoding == NULL)\r
237     return svn_utf_cstring_to_utf8(dest, src, pool);\r
238   else\r
239     return svn_utf_cstring_to_utf8_ex2(dest, src, input_encoding, pool);\r
240 }\r
241 \r
242 #if 0\r
243 svn_error_t *\r
244 svn_cmdline_path_local_style_from_utf8(const char **dest,\r
245                                        const char *src,\r
246                                        apr_pool_t *pool)\r
247 {\r
248   return svn_cmdline_cstring_from_utf8(dest,\r
249                                        svn_path_local_style(src, pool),\r
250                                        pool);\r
251 }\r
252 \r
253 svn_error_t *\r
254 svn_cmdline_printf(apr_pool_t *pool, const char *fmt, ...)\r
255 {\r
256   const char *message;\r
257   va_list ap;\r
258 \r
259   /* A note about encoding issues:\r
260    * APR uses the execution character set, but here we give it UTF-8 strings,\r
261    * both the fmt argument and any other string arguments.  Since apr_pvsprintf\r
262    * only cares about and produces ASCII characters, this works under the\r
263    * assumption that all supported platforms use an execution character set\r
264    * with ASCII as a subset.\r
265    */\r
266 \r
267   va_start(ap, fmt);\r
268   message = apr_pvsprintf(pool, fmt, ap);\r
269   va_end(ap);\r
270 \r
271   return svn_cmdline_fputs(message, stdout, pool);\r
272 }\r
273 #endif\r
274 svn_error_t *\r
275 svn_cmdline_fprintf(FILE *stream, apr_pool_t *pool, const char *fmt, ...)\r
276 {\r
277   const char *message;\r
278   va_list ap;\r
279 \r
280   /* See svn_cmdline_printf () for a note about character encoding issues. */\r
281 \r
282   va_start(ap, fmt);\r
283   message = apr_pvsprintf(pool, fmt, ap);\r
284   va_end(ap);\r
285 \r
286   return svn_cmdline_fputs(message, stream, pool);\r
287 }\r
288 \r
289 svn_error_t *\r
290 svn_cmdline_fputs(const char *string, FILE* stream, apr_pool_t *pool)\r
291 {\r
292   svn_error_t *err;\r
293   const char *out;\r
294 \r
295   err = svn_cmdline_cstring_from_utf8(&out, string, pool);\r
296 \r
297   if (err)\r
298     {\r
299       svn_error_clear(err);\r
300       out = svn_cmdline_cstring_from_utf8_fuzzy(string, pool);\r
301     }\r
302 \r
303   /* On POSIX systems, errno will be set on an error in fputs, but this might\r
304      not be the case on other platforms.  We reset errno and only\r
305      use it if it was set by the below fputs call.  Else, we just return\r
306      a generic error. */\r
307   errno = 0;\r
308 \r
309   if (fputs(out, stream) == EOF)\r
310     {\r
311       if (errno)\r
312         return svn_error_wrap_apr(errno, _("Write error"));\r
313       else\r
314         return svn_error_create\r
315           (SVN_ERR_IO_WRITE_ERROR, NULL, NULL);\r
316     }\r
317 \r
318   return SVN_NO_ERROR;\r
319 }\r
320 #if 0\r
321 svn_error_t *\r
322 svn_cmdline_fflush(FILE *stream)\r
323 {\r
324   /* See comment in svn_cmdline_fputs about use of errno and stdio. */\r
325   errno = 0;\r
326   if (fflush(stream) == EOF)\r
327     {\r
328       if (errno)\r
329         return svn_error_wrap_apr(errno, _("Write error"));\r
330       else\r
331         return svn_error_create(SVN_ERR_IO_WRITE_ERROR, NULL, NULL);\r
332     }\r
333 \r
334   return SVN_NO_ERROR;\r
335 }\r
336 \r
337 const char *svn_cmdline_output_encoding(apr_pool_t *pool)\r
338 {\r
339   if (output_encoding)\r
340     return apr_pstrdup(pool, output_encoding);\r
341   else\r
342     return SVN_APR_LOCALE_CHARSET;\r
343 }\r
344 \r
345 int\r
346 svn_cmdline_handle_exit_error(svn_error_t *err,\r
347                               apr_pool_t *pool,\r
348                               const char *prefix)\r
349 {\r
350   svn_handle_error2(err, stderr, FALSE, prefix);\r
351   svn_error_clear(err);\r
352   if (pool)\r
353     svn_pool_destroy(pool);\r
354   return EXIT_FAILURE;\r
355 }\r
356 \r
357 /* This implements 'svn_auth_ssl_server_trust_prompt_func_t'.\r
358 \r
359    Don't actually prompt.  Instead, set *CRED_P to valid credentials\r
360    iff FAILURES is empty or is exactly SVN_AUTH_SSL_UNKNOWNCA.  If\r
361    there are any other failure bits, then set *CRED_P to null (that\r
362    is, reject the cert).\r
363 \r
364    Ignore MAY_SAVE; we don't save certs we never prompted for.\r
365 \r
366    Ignore BATON, REALM, and CERT_INFO,\r
367 \r
368    Ignore any further films by George Lucas. */\r
369 static svn_error_t *\r
370 ssl_trust_unknown_server_cert\r
371   (svn_auth_cred_ssl_server_trust_t **cred_p,\r
372    void *baton,\r
373    const char *realm,\r
374    apr_uint32_t failures,\r
375    const svn_auth_ssl_server_cert_info_t *cert_info,\r
376    svn_boolean_t may_save,\r
377    apr_pool_t *pool)\r
378 {\r
379   *cred_p = NULL;\r
380 \r
381   if (failures == 0 || failures == SVN_AUTH_SSL_UNKNOWNCA)\r
382     {\r
383       *cred_p = apr_pcalloc(pool, sizeof(**cred_p));\r
384       (*cred_p)->may_save = FALSE;\r
385       (*cred_p)->accepted_failures = failures;\r
386     }\r
387 \r
388   return SVN_NO_ERROR;\r
389 }\r
390 \r
391 svn_error_t *\r
392 svn_cmdline_create_auth_baton(svn_auth_baton_t **ab,\r
393                               svn_boolean_t non_interactive,\r
394                               const char *auth_username,\r
395                               const char *auth_password,\r
396                               const char *config_dir,\r
397                               svn_boolean_t no_auth_cache,\r
398                               svn_boolean_t trust_server_cert,\r
399                               svn_config_t *cfg,\r
400                               svn_cancel_func_t cancel_func,\r
401                               void *cancel_baton,\r
402                               apr_pool_t *pool)\r
403 {\r
404   svn_boolean_t store_password_val = TRUE;\r
405   svn_boolean_t store_auth_creds_val = TRUE;\r
406   svn_auth_provider_object_t *provider;\r
407   svn_cmdline_prompt_baton2_t *pb = NULL;\r
408 \r
409   /* The whole list of registered providers */\r
410   apr_array_header_t *providers;\r
411 \r
412   /* Populate the registered providers with the platform-specific providers */\r
413   SVN_ERR(svn_auth_get_platform_specific_client_providers\r
414             (&providers, cfg, pool));\r
415 \r
416   /* If we have a cancellation function, cram it and the stuff it\r
417      needs into the prompt baton. */\r
418   if (cancel_func)\r
419     {\r
420       pb = apr_palloc(pool, sizeof(*pb));\r
421       pb->cancel_func = cancel_func;\r
422       pb->cancel_baton = cancel_baton;\r
423       pb->config_dir = config_dir;\r
424     }\r
425 \r
426   if (non_interactive == FALSE)\r
427     {\r
428       /* This provider doesn't prompt the user in order to get creds;\r
429          it prompts the user regarding the caching of creds. */\r
430       svn_auth_get_simple_provider2(&provider,\r
431                                     svn_cmdline_auth_plaintext_prompt,\r
432                                     pb, pool);\r
433     }\r
434   else\r
435     {\r
436       svn_auth_get_simple_provider2(&provider, NULL, NULL, pool);\r
437     }\r
438 \r
439   APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;\r
440   svn_auth_get_username_provider(&provider, pool);\r
441   APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;\r
442 \r
443   /* The server-cert, client-cert, and client-cert-password providers. */\r
444   SVN_ERR(svn_auth_get_platform_specific_provider(&provider,\r
445                                                   "windows",\r
446                                                   "ssl_server_trust",\r
447                                                   pool));\r
448 \r
449   if (provider)\r
450     APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;\r
451 \r
452   svn_auth_get_ssl_server_trust_file_provider(&provider, pool);\r
453   APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;\r
454   svn_auth_get_ssl_client_cert_file_provider(&provider, pool);\r
455   APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;\r
456 \r
457   if (non_interactive == FALSE)\r
458     {\r
459       /* This provider doesn't prompt the user in order to get creds;\r
460          it prompts the user regarding the caching of creds. */\r
461       svn_auth_get_ssl_client_cert_pw_file_provider2\r
462         (&provider, svn_cmdline_auth_plaintext_passphrase_prompt,\r
463          pb, pool);\r
464     }\r
465   else\r
466     {\r
467       svn_auth_get_ssl_client_cert_pw_file_provider2(&provider, NULL, NULL,\r
468                                                      pool);\r
469     }\r
470   APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;\r
471 \r
472   if (non_interactive == FALSE)\r
473     {\r
474       /* Two basic prompt providers: username/password, and just username. */\r
475       svn_auth_get_simple_prompt_provider(&provider,\r
476                                           svn_cmdline_auth_simple_prompt,\r
477                                           pb,\r
478                                           2, /* retry limit */\r
479                                           pool);\r
480       APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;\r
481 \r
482       svn_auth_get_username_prompt_provider\r
483         (&provider, svn_cmdline_auth_username_prompt, pb,\r
484          2, /* retry limit */ pool);\r
485       APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;\r
486 \r
487       /* Three ssl prompt providers, for server-certs, client-certs,\r
488          and client-cert-passphrases.  */\r
489       svn_auth_get_ssl_server_trust_prompt_provider\r
490         (&provider, svn_cmdline_auth_ssl_server_trust_prompt, pb, pool);\r
491       APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;\r
492 \r
493       svn_auth_get_ssl_client_cert_prompt_provider\r
494         (&provider, svn_cmdline_auth_ssl_client_cert_prompt, pb, 2, pool);\r
495       APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;\r
496 \r
497       svn_auth_get_ssl_client_cert_pw_prompt_provider\r
498         (&provider, svn_cmdline_auth_ssl_client_cert_pw_prompt, pb, 2, pool);\r
499       APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;\r
500     }\r
501   else if (trust_server_cert)\r
502     {\r
503       /* Remember, only register this provider if non_interactive. */\r
504       svn_auth_get_ssl_server_trust_prompt_provider\r
505         (&provider, ssl_trust_unknown_server_cert, NULL, pool);\r
506       APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;\r
507     }\r
508 \r
509   /* Build an authentication baton to give to libsvn_client. */\r
510   svn_auth_open(ab, providers, pool);\r
511 \r
512   /* Place any default --username or --password credentials into the\r
513      auth_baton's run-time parameter hash. */\r
514   if (auth_username)\r
515     svn_auth_set_parameter(*ab, SVN_AUTH_PARAM_DEFAULT_USERNAME,\r
516                            auth_username);\r
517   if (auth_password)\r
518     svn_auth_set_parameter(*ab, SVN_AUTH_PARAM_DEFAULT_PASSWORD,\r
519                            auth_password);\r
520 \r
521   /* Same with the --non-interactive option. */\r
522   if (non_interactive)\r
523     svn_auth_set_parameter(*ab, SVN_AUTH_PARAM_NON_INTERACTIVE, "");\r
524 \r
525   if (config_dir)\r
526     svn_auth_set_parameter(*ab, SVN_AUTH_PARAM_CONFIG_DIR,\r
527                            config_dir);\r
528 \r
529   /* Determine whether storing passwords in any form is allowed.\r
530    * This is the deprecated location for this option, the new\r
531    * location is SVN_CONFIG_CATEGORY_SERVERS. The RA layer may\r
532    * override the value we set here. */\r
533   SVN_ERR(svn_config_get_bool(cfg, &store_password_val,\r
534                               SVN_CONFIG_SECTION_AUTH,\r
535                               SVN_CONFIG_OPTION_STORE_PASSWORDS,\r
536                               SVN_CONFIG_DEFAULT_OPTION_STORE_PASSWORDS));\r
537 \r
538   if (! store_password_val)\r
539     svn_auth_set_parameter(*ab, SVN_AUTH_PARAM_DONT_STORE_PASSWORDS, "");\r
540 \r
541   /* Determine whether we are allowed to write to the auth/ area.\r
542    * This is the deprecated location for this option, the new\r
543    * location is SVN_CONFIG_CATEGORY_SERVERS. The RA layer may\r
544    * override the value we set here. */\r
545   SVN_ERR(svn_config_get_bool(cfg, &store_auth_creds_val,\r
546                               SVN_CONFIG_SECTION_AUTH,\r
547                               SVN_CONFIG_OPTION_STORE_AUTH_CREDS,\r
548                               SVN_CONFIG_DEFAULT_OPTION_STORE_AUTH_CREDS));\r
549 \r
550   if (no_auth_cache || ! store_auth_creds_val)\r
551     svn_auth_set_parameter(*ab, SVN_AUTH_PARAM_NO_AUTH_CACHE, "");\r
552 \r
553 #ifdef SVN_HAVE_GNOME_KEYRING\r
554   svn_auth_set_parameter(*ab, SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC,\r
555                          &svn_cmdline__auth_gnome_keyring_unlock_prompt);\r
556 #endif /* SVN_HAVE_GNOME_KEYRING */\r
557 \r
558   return SVN_NO_ERROR;\r
559 }\r
560 \r
561 svn_error_t *\r
562 svn_cmdline__getopt_init(apr_getopt_t **os,\r
563                          int argc,\r
564                          const char *argv[],\r
565                          apr_pool_t *pool)\r
566 {\r
567   apr_status_t apr_err = apr_getopt_init(os, pool, argc, argv);\r
568   if (apr_err)\r
569     return svn_error_wrap_apr(apr_err,\r
570                               _("Error initializing command line arguments"));\r
571   return SVN_NO_ERROR;\r
572 }\r
573 \r
574 \r
575 void\r
576 svn_cmdline__print_xml_prop(svn_stringbuf_t **outstr,\r
577                             const char* propname,\r
578                             svn_string_t *propval,\r
579                             apr_pool_t *pool)\r
580 {\r
581   const char *xml_safe;\r
582   const char *encoding = NULL;\r
583 \r
584   if (*outstr == NULL)\r
585     *outstr = svn_stringbuf_create("", pool);\r
586 \r
587   if (svn_xml_is_xml_safe(propval->data, propval->len))\r
588     {\r
589       svn_stringbuf_t *xml_esc = NULL;\r
590       svn_xml_escape_cdata_string(&xml_esc, propval, pool);\r
591       xml_safe = xml_esc->data;\r
592     }\r
593   else\r
594     {\r
595       const svn_string_t *base64ed = svn_base64_encode_string2(propval, TRUE,\r
596                                                                pool);\r
597       encoding = "base64";\r
598       xml_safe = base64ed->data;\r
599     }\r
600 \r
601   if (encoding)\r
602     svn_xml_make_open_tag(outstr, pool, svn_xml_protect_pcdata,\r
603                           "property", "name", propname,\r
604                           "encoding", encoding, NULL);\r
605   else\r
606     svn_xml_make_open_tag(outstr, pool, svn_xml_protect_pcdata,\r
607                           "property", "name", propname, NULL);\r
608 \r
609   svn_stringbuf_appendcstr(*outstr, xml_safe);\r
610 \r
611   svn_xml_make_close_tag(outstr, pool, "property");\r
612 \r
613   return;\r
614 }\r
615 \r
616 \r
617 #endif