XRootD
Loading...
Searching...
No Matches
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/*
8This software is Copyright (c) 2016 by David Farrell.
9
10Source: https://github.com/dnmfarrell/URI-Encode-C
11
12Modified by Andrew Hanushevsky, SLAC.
13Changes: 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
20This is free software, licensed under:
21
22 The (two-clause) FreeBSD License
23
24The FreeBSD License
25
26Redistribution and use in source and binary forms, with or without
27modification, are permitted provided that the following conditions are
28met:
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
38THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
39"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
40LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
41A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
42HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
44LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
45DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
46THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
47(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
48OF 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
60namespace
61{
62
63#define __ 0xFF
64
65static 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
89static 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
116int 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
146int 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
164int 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
190int 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