XRootD
XrdOucUri.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d O u c U r i . c c */
4 /* */
5 /******************************************************************************/
6 
7 /*
8 This software is Copyright (c) 2016 by David Farrell.
9 
10 Source: https://github.com/dnmfarrell/URI-Encode-C
11 
12 Modified by Andrew Hanushevsky, SLAC.
13 Changes: a) Make this C++ looking.
14  b) Use XRoootD naming conventions.
15  c) Avoid relying on unaligned uint32_t fetches and stores.
16  d) Reduce the encode table size by 50%.
17  e) Add a couple of handy methods.
18  f) General code simplifications.
19 
20 This is free software, licensed under:
21 
22  The (two-clause) FreeBSD License
23 
24 The FreeBSD License
25 
26 Redistribution and use in source and binary forms, with or without
27 modification, are permitted provided that the following conditions are
28 met:
29 
30  1. Redistributions of source code must retain the above copyright
31  notice, this list of conditions and the following disclaimer.
32 
33  2. Redistributions in binary form must reproduce the above copyright
34  notice, this list of conditions and the following disclaimer in the
35  documentation and/or other materials provided with the
36  distribution.
37 
38 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
39 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
40 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
41 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
42 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
44 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
45 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
46 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
47 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
48 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49 */
50 
51 #include <cstdlib>
52 #include <cstring>
53 
54 #include "XrdOuc/XrdOucUri.hh"
55 
56 /******************************************************************************/
57 /* S t a t i c O b j e c t s */
58 /******************************************************************************/
59 
60 namespace
61 {
62 
63 #define __ 0xFF
64 
65 static const unsigned char hexval[0x100] = {
66 // 0 1 2 3 4 5 6 7 8 9 a b c d e f
67  __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* 00-0F */
68  __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* 10-1F */
69  __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* 20-2F */
70  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,__,__,__,__,__,__, /* 30-3F */
71  __,10,11,12,13,14,15,__,__,__,__,__,__,__,__,__, /* 40-4F */
72  __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* 50-5F */
73  __,10,11,12,13,14,15,__,__,__,__,__,__,__,__,__, /* 60-6F */
74  __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* 70-7F */
75  __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* 80-8F */
76  __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* 90-9F */
77  __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* A0-AF */
78  __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* B0-BF */
79  __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* C0-CF */
80  __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* D0-DF */
81  __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* E0-EF */
82  __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ /* F0-FF */
83 };
84 
85 #undef __
86 
87 #define ____ "\0\0"
88 
89 static const unsigned char uri_encode_tbl[ (2 * 0x100) + 1 ] = {
90 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
91  "00" "01" "02" "03" "04" "05" "06" "07" "08" "09" "0A" "0B" "0C" "0D" "0E" "0F" /* 0: 0 ~ 15 */
92  "10" "11" "12" "13" "14" "15" "16" "17" "18" "19" "1A" "1B" "1C" "1D" "1E" "1F" /* 1: 16 ~ 31 */
93  "20" "21" "22" "23" "24" "25" "26" "27" "28" "29" "2A" "2B" "2C" ____ ____ "2F" /* 2: 32 ~ 47 */
94  ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ "3A" "3B" "3C" "3D" "3E" "3F" /* 3: 48 ~ 63 */
95  "40" ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ /* 4: 64 ~ 79 */
96  ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ "5B" "5C" "5D" "5E" ____ /* 5: 80 ~ 95 */
97  "60" ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ /* 6: 96 ~ 111 */
98  ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ "7B" "7C" "7D" ____ "7F" /* 7: 112 ~ 127 */
99  "80" "81" "82" "83" "84" "85" "86" "87" "88" "89" "8A" "8B" "8C" "8D" "8E" "8F" /* 8: 128 ~ 143 */
100  "90" "91" "92" "93" "94" "95" "96" "97" "98" "99" "9A" "9B" "9C" "9D" "9E" "9F" /* 9: 144 ~ 159 */
101  "A0" "A1" "A2" "A3" "A4" "A5" "A6" "A7" "A8" "A9" "AA" "AB" "AC" "AD" "AE" "AF" /* A: 160 ~ 175 */
102  "B0" "B1" "B2" "B3" "B4" "B5" "B6" "B7" "B8" "B9" "BA" "BB" "BC" "BD" "BE" "BF" /* B: 176 ~ 191 */
103  "C0" "C1" "C2" "C3" "C4" "C5" "C6" "C7" "C8" "C9" "CA" "CB" "CC" "CD" "CE" "CF" /* C: 192 ~ 207 */
104  "D0" "D1" "D2" "D3" "D4" "D5" "D6" "D7" "D8" "D9" "DA" "DB" "DC" "DD" "DE" "DF" /* D: 208 ~ 223 */
105  "E0" "E1" "E2" "E3" "E4" "E5" "E6" "E7" "E8" "E9" "EA" "EB" "EC" "ED" "EE" "EF" /* E: 224 ~ 239 */
106  "F0" "F1" "F2" "F3" "F4" "F5" "F6" "F7" "F8" "F9" "FA" "FB" "FC" "FD" "FE" "FF" /* F: 240 ~ 255 */
107 };
108 #undef ____
109 }
110 
111 /******************************************************************************/
112 /* D e c o d e */
113 /******************************************************************************/
114 
115 
116 int XrdOucUri::Decode (const char *src, int len, char *dst)
117 {
118  int i = 0, j = 0;
119  unsigned char v1, v2;
120 
121 // Run through looking for any sequences that need to be converted.
122 //
123  while(i < len)
124  {if(src[i] == '%' && i + 2 < len)
125  {v1 = hexval[ (unsigned char)src[i+1] ];
126  v2 = hexval[ (unsigned char)src[i+2] ];
127 
128  /* skip invalid hex sequences */
129  if ((v1 | v2) == 0xFF) dst[j++] = src[i++];
130  else {dst[j++] = (v1 << 4) | v2;
131  i += 3;
132  }
133  } else dst[j++] = src[i++];
134  }
135 
136 // All done, add null byte and return its index
137 //
138  dst[j] = '\0';
139  return j;
140 }
141 
142 /******************************************************************************/
143 /* E n c o d e */
144 /******************************************************************************/
145 
146 int XrdOucUri::Encode(const char *src, int len, char **dst)
147 {
148 
149 // Get the size of the destination buffer
150 //
151  int n = Encoded(src, len);
152 
153 // Allocate an output buffer
154 //
155  if (!(*dst = (char *)malloc(n))) return 0;
156 
157 // Return final result
158 //
159  return Encode(src, len, *dst);
160 }
161 
162 /******************************************************************************/
163 
164 int XrdOucUri::Encode(const char *src, int len, char *dst)
165 {
166  const unsigned char *code;
167  int j = 0;
168 
169 // Encode every character that needs to be encoded
170 //
171  for(int i = 0; i < len; i++)
172  {code = &uri_encode_tbl[((unsigned int)((unsigned char)src[i])) << 1];
173  if (*code)
174  {dst[j++] = '%';
175  memcpy(&dst[j], code, 2);
176  j += 2;
177  } else dst[j++] = src[i];
178  }
179 
180 // All done, end with null byte and return index to that byte
181 //
182  dst[j] = '\0';
183  return j;
184 }
185 
186 /******************************************************************************/
187 /* E n c o d e d */
188 /******************************************************************************/
189 
190 int XrdOucUri::Encoded(const char *src, int len)
191 {
192  int totlen = 0;
193 
194 // Calculate the size that the destination buffer must have
195 //
196  for(int i = 0; i < len; i++)
197  {totlen += (uri_encode_tbl[((unsigned int)src[i]) << 1] ? 3 : 1);}
198 
199 // Return size needed for destination buffer
200 //
201  return totlen + 1;
202 }
#define __
Definition: XrdOucUri.cc:63
#define ____
Definition: XrdOucUri.cc:87
static int Decode(const char *src, int len, char *dst)
Definition: XrdOucUri.cc:116
static int Encode(const char *src, int len, char **dst)
Definition: XrdOucUri.cc:146
static int Encoded(const char *src, int len)
Definition: XrdOucUri.cc:190