LCOV - code coverage report
Current view: top level - common - percent.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 67 74 90.5 %
Date: 2016-09-12 13:01:59 Functions: 7 9 77.8 %

          Line data    Source code
       1             : /* percent.c - Percent escaping
       2             :  * Copyright (C) 2008, 2009 Free Software Foundation, Inc.
       3             :  *
       4             :  * This file is part of GnuPG.
       5             :  *
       6             :  * This file is free software; you can redistribute it and/or modify
       7             :  * it under the terms of either
       8             :  *
       9             :  *   - the GNU Lesser General Public License as published by the Free
      10             :  *     Software Foundation; either version 3 of the License, or (at
      11             :  *     your option) any later version.
      12             :  *
      13             :  * or
      14             :  *
      15             :  *   - the GNU General Public License as published by the Free
      16             :  *     Software Foundation; either version 2 of the License, or (at
      17             :  *     your option) any later version.
      18             :  *
      19             :  * or both in parallel, as here.
      20             :  *
      21             :  * This file is distributed in the hope that it will be useful,
      22             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      23             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      24             :  * GNU General Public License for more details.
      25             :  *
      26             :  * You should have received a copy of the GNU General Public License
      27             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      28             :  */
      29             : 
      30             : #include <config.h>
      31             : #include <stdlib.h>
      32             : #include <errno.h>
      33             : #include <ctype.h>
      34             : #include <assert.h>
      35             : 
      36             : #include "util.h"
      37             : 
      38             : 
      39             : /* Create a newly alloced string from STRING with all spaces and
      40             :    control characters converted to plus signs or %xx sequences.  The
      41             :    function returns the new string or NULL in case of a malloc
      42             :    failure.
      43             : 
      44             :    Note that we also escape the quote character to work around a bug
      45             :    in the mingw32 runtime which does not correcty handle command line
      46             :    quoting.  We correctly double the quote mark when calling a program
      47             :    (i.e. gpg-protect-tool), but the pre-main code does not notice the
      48             :    double quote as an escaped quote.  We do this also on POSIX systems
      49             :    for consistency.  */
      50             : char *
      51         440 : percent_plus_escape (const char *string)
      52             : {
      53             :   char *buffer, *p;
      54             :   const char *s;
      55             :   size_t length;
      56             : 
      57       76930 :   for (length=1, s=string; *s; s++)
      58             :     {
      59       76490 :       if (*s == '+' || *s == '\"' || *s == '%'
      60       75621 :           || *(const unsigned char *)s < 0x20)
      61        2595 :         length += 3;
      62             :       else
      63       73895 :         length++;
      64             :     }
      65             : 
      66         440 :   buffer = p = xtrymalloc (length);
      67         440 :   if (!buffer)
      68           0 :     return NULL;
      69             : 
      70       76930 :   for (s=string; *s; s++)
      71             :     {
      72       76490 :       if (*s == '+' || *s == '\"' || *s == '%'
      73       75621 :           || *(const unsigned char *)s < 0x20)
      74             :         {
      75        2595 :           snprintf (p, 4, "%%%02X", *(unsigned char *)s);
      76        2595 :           p += 3;
      77             :         }
      78       73895 :       else if (*s == ' ')
      79        8470 :         *p++ = '+';
      80             :       else
      81       65425 :         *p++ = *s;
      82             :     }
      83         440 :   *p = 0;
      84             : 
      85         440 :   return buffer;
      86             : 
      87             : }
      88             : 
      89             : 
      90             : /* Do the percent and plus/space unescaping from STRING to BUFFER and
      91             :    return the length of the valid buffer.  Plus unescaping is only
      92             :    done if WITHPLUS is true.  An escaped Nul character will be
      93             :    replaced by NULREPL.  */
      94             : static size_t
      95           9 : do_unescape (unsigned char *buffer, const unsigned char *string,
      96             :              int withplus, int nulrepl)
      97             : {
      98           9 :   unsigned char *p = buffer;
      99             : 
     100          40 :   while (*string)
     101             :     {
     102          22 :       if (*string == '%' && string[1] && string[2])
     103             :         {
     104           9 :           string++;
     105           9 :           *p = xtoi_2 (string);
     106           9 :           if (!*p)
     107           0 :             *p = nulrepl;
     108           9 :           string++;
     109             :         }
     110          13 :       else if (*string == '+' && withplus)
     111           7 :         *p = ' ';
     112             :       else
     113           6 :         *p = *string;
     114          22 :       p++;
     115          22 :       string++;
     116             :     }
     117             : 
     118           9 :   return (p - buffer);
     119             : }
     120             : 
     121             : 
     122             : /* Count space required after unescaping STRING.  Note that this will
     123             :    never be larger than strlen (STRING).  */
     124             : static size_t
     125           9 : count_unescape (const unsigned char *string)
     126             : {
     127           9 :   size_t n = 0;
     128             : 
     129          40 :   while (*string)
     130             :     {
     131          22 :       if (*string == '%' && string[1] && string[2])
     132             :         {
     133           9 :           string++;
     134           9 :           string++;
     135             :         }
     136          22 :       string++;
     137          22 :       n++;
     138             :     }
     139             : 
     140           9 :   return n;
     141             : }
     142             : 
     143             : 
     144             : /* Helper.  */
     145             : static char *
     146           9 : do_plus_or_plain_unescape (const char *string, int withplus, int nulrepl)
     147             : {
     148             :   size_t nbytes, n;
     149             :   char *newstring;
     150             : 
     151           9 :   nbytes = count_unescape (string);
     152           9 :   newstring = xtrymalloc (nbytes+1);
     153           9 :   if (newstring)
     154             :     {
     155           9 :       n = do_unescape (newstring, string, withplus, nulrepl);
     156           9 :       assert (n == nbytes);
     157           9 :       newstring[n] = 0;
     158             :     }
     159           9 :   return newstring;
     160             : }
     161             : 
     162             : 
     163             : /* Create a new allocated string from STRING with all "%xx" sequences
     164             :    decoded and all plus signs replaced by a space.  Embedded Nul
     165             :    characters are replaced by the value of NULREPL.  The function
     166             :    returns the new string or NULL in case of a malloc failure.  */
     167             : char *
     168           9 : percent_plus_unescape (const char *string, int nulrepl)
     169             : {
     170           9 :   return do_plus_or_plain_unescape (string, 1, nulrepl);
     171             : }
     172             : 
     173             : 
     174             : /* Create a new allocated string from STRING with all "%xx" sequences
     175             :    decoded.  Embedded Nul characters are replaced by the value of
     176             :    NULREPL.  The function returns the new string or NULL in case of a
     177             :    malloc failure.  */
     178             : char *
     179           0 : percent_unescape (const char *string, int nulrepl)
     180             : {
     181           0 :   return do_plus_or_plain_unescape (string, 0, nulrepl);
     182             : }
     183             : 
     184             : 
     185             : static size_t
     186           9 : do_unescape_inplace (char *string, int withplus, int nulrepl)
     187             : {
     188             :   unsigned char *p, *p0;
     189             : 
     190           9 :   p = p0 = string;
     191          40 :   while (*string)
     192             :     {
     193          22 :       if (*string == '%' && string[1] && string[2])
     194             :         {
     195           9 :           string++;
     196           9 :           *p = xtoi_2 (string);
     197           9 :           if (!*p)
     198           0 :             *p = nulrepl;
     199           9 :           string++;
     200             :         }
     201          13 :       else if (*string == '+' && withplus)
     202           7 :         *p = ' ';
     203             :       else
     204           6 :         *p = *string;
     205          22 :       p++;
     206          22 :       string++;
     207             :     }
     208             : 
     209           9 :   return (p - p0);
     210             : }
     211             : 
     212             : 
     213             : /* Perform percent and plus unescaping in STRING and return the new
     214             :    valid length of the string.  Embedded Nul characters are replaced
     215             :    by the value of NULREPL.  A terminating Nul character is not
     216             :    inserted; the caller might want to call this function this way:
     217             : 
     218             :       foo[percent_plus_unescape_inplace (foo, 0)] = 0;
     219             :  */
     220             : size_t
     221           9 : percent_plus_unescape_inplace (char *string, int nulrepl)
     222             : {
     223           9 :   return do_unescape_inplace (string, 1, nulrepl);
     224             : }
     225             : 
     226             : 
     227             : /* Perform percent unescaping in STRING and return the new valid
     228             :    length of the string.  Embedded Nul characters are replaced by the
     229             :    value of NULREPL.  A terminating Nul character is not inserted; the
     230             :    caller might want to call this function this way:
     231             : 
     232             :       foo[percent_unescape_inplace (foo, 0)] = 0;
     233             :  */
     234             : size_t
     235           0 : percent_unescape_inplace (char *string, int nulrepl)
     236             : {
     237           0 :   return do_unescape_inplace (string, 0, nulrepl);
     238             : }

Generated by: LCOV version 1.11