gloox 1.0.28
util.cpp
1/*
2 Copyright (c) 2006-2023 by Jakob Schröter <js@camaya.net>
3 This file is part of the gloox library. http://camaya.net/gloox
4
5 This software is distributed under a license. The full license
6 agreement can be found in the file LICENSE in this distribution.
7 This software may not be copied, modified, sold or distributed
8 other than expressed in the named license agreement.
9
10 This software is distributed without any warranty.
11*/
12
13#include "util.h"
14#include "gloox.h"
15
16#include <cstdio>
17
18namespace gloox
19{
20
21 namespace util
22 {
23
24 int internalLog2( unsigned int n )
25 {
26 int pos = 0;
27 if ( n >= 1<<16 ) { n >>= 16; pos += 16; }
28 if ( n >= 1<< 8 ) { n >>= 8; pos += 8; }
29 if ( n >= 1<< 4 ) { n >>= 4; pos += 4; }
30 if ( n >= 1<< 2 ) { n >>= 2; pos += 2; }
31 if ( n >= 1<< 1 ) { pos += 1; }
32 return ( (n == 0) ? (-1) : pos );
33 }
34
35 unsigned _lookup( const std::string& str, const char* values[], unsigned size, int def )
36 {
37 unsigned i = 0;
38 for( ; i < size && str != values[i]; ++i )
39 ;
40 return ( i == size && def >= 0 ) ? static_cast<unsigned int>( def ) : i;
41 }
42
43 const std::string _lookup( unsigned code, const char* values[], unsigned size, const std::string& def )
44 {
45 return code < size ? std::string( values[code] ) : def;
46 }
47
48 unsigned _lookup2( const std::string& str, const char* values[],
49 unsigned size, int def )
50 {
51 return 1 << _lookup( str, values, size, def <= 0 ? def : static_cast<int>( internalLog2( def ) ) );
52 }
53
54 const std::string _lookup2( unsigned code, const char* values[], unsigned size, const std::string& def )
55 {
56 const unsigned i = static_cast<unsigned int>( internalLog2( code ) );
57 return i < size ? std::string( values[i] ) : def;
58 }
59
60 std::string hex( const std::string& input )
61 {
62 const char* H = input.c_str();
63 char* buf = new char[input.length() * 2 + 1];
64 for( unsigned int i = 0; i < input.length(); ++i )
65 sprintf( buf + i * 2, "%02x", static_cast<unsigned char>( H[i] ) );
66 return std::string( buf, 40 );
67 }
68
69 static const char escape_chars[] = { '&', '<', '>', '\'', '"' };
70
71 static const std::string escape_seqs[] = { "amp;", "lt;", "gt;", "apos;", "quot;" };
72
73 static const std::string escape_seqs_full[] = { "&amp;", "&lt;", "&gt;", "&apos;", "&quot;" };
74
75 static const unsigned escape_size = 5;
76
77 const std::string escape( std::string what )
78 {
79 for( size_t val, i = 0; i < what.length(); ++i )
80 {
81 for( val = 0; val < escape_size; ++val )
82 {
83 if( what[i] == escape_chars[val] )
84 {
85 what[i] = '&';
86 what.insert( i+1, escape_seqs[val] );
87 i += escape_seqs[val].length();
88 break;
89 }
90 }
91 }
92 return what;
93 }
94
95 void appendEscaped( std::string& target, const std::string& data )
96 {
97 size_t rangeStart = 0, rangeCount = 0;
98 size_t length = data.length();
99 const char* dataPtr = data.data();
100 for( size_t val, i = 0; i < length; ++i )
101 {
102 const char current = dataPtr[i];
103 for( val = 0; val < escape_size; ++val )
104 {
105 if( current == escape_chars[val] )
106 {
107 // We have a character that needs to be escaped.
108 if( rangeCount > 0 )
109 {
110 // We have a range of the data that needs to be appended
111 // before we escape the current character.
112 // NOTE: Use "data" (std::string) here not dataPtr (const char*).
113 // Both have the same content, but there isn't
114 // an append override that takes const char*, pos, n
115 // (so a temporary std::string would be created)
116 target.append( data, rangeStart, rangeCount );
117 }
118 target.append( escape_seqs_full[val] );
119 rangeStart = i + 1;
120 rangeCount = 0;
121 break;
122 }
123 }
124
125 if( rangeStart <= i )
126 {
127 // current did not need to be escaped
128 ++rangeCount;
129 }
130 }
131
132 if( rangeCount > 0 )
133 {
134 // Append the remaining pending range of data that does
135 // not need to be escaped.
136 // NOTE: See previous comment on using data not dataPtr for append.
137 target.append( data, rangeStart, rangeCount );
138 }
139 }
140
141 bool checkValidXMLChars( const std::string& data )
142 {
143 if( data.empty() )
144 return true;
145
146 const char* dataPtr = data.data();
147 const char* end = dataPtr + data.length();
148 for( ; dataPtr != end; ++dataPtr )
149 {
150 unsigned char current = static_cast<unsigned char>( *dataPtr );
151 if( current < 0x20 )
152 {
153 if( current == 0x09
154 || current == 0x0a
155 || current == 0x0d )
156 // Valid character
157 continue;
158 else
159 // Invalid character
160 break;
161 }
162 else if( current >= 0xf5 )
163 // Invalid character
164 break;
165 else if( current == 0xc0
166 || current == 0xc1 )
167 // Invalid character
168 break;
169 else
170 // Valid character
171 continue;
172 }
173
174 return ( dataPtr == end );
175 }
176
177 void replaceAll( std::string& target, const std::string& find, const std::string& replace )
178 {
179 std::string::size_type findSize = find.size();
180 std::string::size_type replaceSize = replace.size();
181
182 if( findSize == 0 )
183 return;
184
185 std::string::size_type index = target.find( find, 0 );
186
187 while( index != std::string::npos )
188 {
189 target.replace( index, findSize, replace );
190 index = target.find( find, index+replaceSize );
191 }
192 }
193
194 }
195
196}
197
int internalLog2(unsigned int n)
Definition util.cpp:24
unsigned _lookup(const std::string &str, const char *values[], unsigned size, int def)
Definition util.cpp:35
unsigned _lookup2(const std::string &str, const char *values[], unsigned size, int def)
Definition util.cpp:48
void appendEscaped(std::string &target, const std::string &data)
Definition util.cpp:95
void replaceAll(std::string &target, const std::string &find, const std::string &replace)
Definition util.cpp:177
bool checkValidXMLChars(const std::string &data)
Definition util.cpp:141
std::string hex(const std::string &input)
Definition util.cpp:60
const std::string escape(std::string what)
Definition util.cpp:77
The namespace for the gloox library.
Definition adhoc.cpp:28