1 /* 2 * This file is part of nzbget. See <http://nzbget.net>. 3 * 4 * Copyright (C) 2007-2019 Andrey Prygunkov <hugbug@users.sourceforge.net> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 21 #ifndef UTIL_H 22 #define UTIL_H 23 24 #include "NString.h" 25 26 #ifdef WIN32 27 extern int optind, opterr; 28 extern char *optarg; 29 int getopt(int argc, char *argv[], char *optstring); 30 #endif 31 32 class Util 33 { 34 public: 35 static bool MatchFileExt(const char* filename, const char* extensionList, const char* listSeparator); 36 37 /* 38 * Split command line into arguments. 39 * Uses spaces and single quotation marks as separators. 40 * May return empty list if bad escaping was detected. 41 */ 42 static std::vector<CString> SplitCommandLine(const char* commandLine); 43 44 static int64 JoinInt64(uint32 Hi, uint32 Lo); 45 static void SplitInt64(int64 Int64, uint32* Hi, uint32* Lo); 46 47 static void TrimRight(char* str); 48 static char* Trim(char* str); EmptyStr(const char * str)49 static bool EmptyStr(const char* str) { return !str || !*str; } 50 static std::vector<CString> SplitStr(const char* str, const char* separators); 51 static bool EndsWith(const char* str, const char* suffix, bool caseSensitive); 52 static bool AlphaNum(const char* str); 53 54 /* replace all occurences of szFrom to szTo in string szStr with a limitation that szTo must be shorter than szFrom */ 55 static char* ReduceStr(char* str, const char* from, const char* to); 56 57 /* Calculate Hash using Bob Jenkins (1996) algorithm */ 58 static uint32 HashBJ96(const char* buffer, int bufSize, uint32 initValue); 59 60 #ifdef WIN32 61 static bool RegReadStr(HKEY keyRoot, const char* keyName, const char* valueName, char* buffer, int* bufLen); 62 #endif 63 64 static void SetStandByMode(bool standBy); 65 66 static time_t CurrentTime(); 67 static int64 CurrentTicks(); 68 static void Sleep(int milliseconds); 69 70 /* cross platform version of GNU timegm, which is similar to mktime but takes an UTC time as parameter */ 71 static time_t Timegm(tm const *t); 72 73 static void FormatTime(time_t timeSec, char* buffer, int bufsize); 74 static CString FormatTime(time_t timeSec); 75 76 static CString FormatSpeed(int bytesPerSecond); 77 static CString FormatSize(int64 fileSize); 78 static CString FormatBuffer(const char* buf, int len); 79 80 /* 81 * Returns program version and revision number as string formatted like "0.7.0-r295". 82 * If revision number is not available only version is returned ("0.7.0"). 83 */ VersionRevision()84 static const char* VersionRevision() { return VersionRevisionBuf; }; 85 86 static char VersionRevisionBuf[100]; 87 88 static void Init(); 89 90 /* 91 * Returns number of available CPU cores or -1 if it could not be determined 92 */ 93 static int NumberOfCpuCores(); 94 }; 95 96 class WebUtil 97 { 98 public: 99 static uint32 DecodeBase64(char* inputBuffer, int inputBufferLength, char* outputBuffer); 100 101 /* 102 * Encodes string to be used as content of xml-tag. 103 */ 104 static CString XmlEncode(const char* raw); 105 106 /* 107 * Decodes string from xml. 108 * The string is decoded on the place overwriting the content of raw-data. 109 */ 110 static void XmlDecode(char* raw); 111 112 /* 113 * Returns pointer to tag-content and length of content in iValueLength 114 * The returned pointer points to the part of source-string, no additional strings are allocated. 115 */ 116 static const char* XmlFindTag(const char* xml, const char* tag, int* valueLength); 117 118 /* 119 * Parses tag-content into szValueBuf. 120 */ 121 static bool XmlParseTagValue(const char* xml, const char* tag, char* valueBuf, int valueBufSize, const char** tagEnd); 122 123 /* 124 * Replaces all tags with spaces effectively providing the text content only. 125 * The string is transformed in-place overwriting the previous content. 126 */ 127 static void XmlStripTags(char* xml); 128 129 /* 130 * Replaces all entities with spaces. 131 * The string is transformed in-place overwriting the previous content. 132 */ 133 static void XmlRemoveEntities(char* raw); 134 135 /* 136 * Creates JSON-string by replace the certain characters with escape-sequences. 137 */ 138 static CString JsonEncode(const char* raw); 139 140 /* 141 * Decodes JSON-string. 142 * The string is decoded on the place overwriting the content of raw-data. 143 */ 144 static void JsonDecode(char* raw); 145 146 /* 147 * Returns pointer to field-content and length of content in iValueLength 148 * The returned pointer points to the part of source-string, no additional strings are allocated. 149 */ 150 static const char* JsonFindField(const char* jsonText, const char* fieldName, int* valueLength); 151 152 /* 153 * Returns pointer to field-content and length of content in iValueLength 154 * The returned pointer points to the part of source-string, no additional strings are allocated. 155 */ 156 static const char* JsonNextValue(const char* jsonText, int* valueLength); 157 158 /* 159 * Unquote http quoted string. 160 * The string is decoded on the place overwriting the content of raw-data. 161 */ 162 static void HttpUnquote(char* raw); 163 164 /* 165 * Decodes URL-string. 166 * The string is decoded on the place overwriting the content of raw-data. 167 */ 168 static void UrlDecode(char* raw); 169 170 /* 171 * Makes valid URL by replacing of spaces with "%20". 172 */ 173 static CString UrlEncode(const char* raw); 174 175 /* 176 * Converts ISO-8859-1 (aka Latin-1) into UTF-8. 177 */ 178 static CString Latin1ToUtf8(const char* str); 179 180 static time_t ParseRfc822DateTime(const char* dateTimeStr); 181 }; 182 183 class URL 184 { 185 public: 186 URL(const char* address); IsValid()187 bool IsValid() { return m_valid; } GetAddress()188 const char* GetAddress() { return m_address; } GetProtocol()189 const char* GetProtocol() { return m_protocol; } GetUser()190 const char* GetUser() { return m_user; } GetPassword()191 const char* GetPassword() { return m_password; } GetHost()192 const char* GetHost() { return m_host; } GetResource()193 const char* GetResource() { return m_resource; } GetPort()194 int GetPort() { return m_port; } GetTls()195 bool GetTls() { return m_tls; } 196 197 private: 198 CString m_address; 199 CString m_protocol; 200 CString m_user; 201 CString m_password; 202 CString m_host; 203 CString m_resource; 204 int m_port = 0; 205 bool m_tls = false; 206 bool m_valid = false; 207 208 void ParseUrl(); 209 }; 210 211 class RegEx 212 { 213 public: 214 RegEx(const char *pattern, int matchBufSize = 100); 215 ~RegEx(); IsValid()216 bool IsValid() { return m_valid; } 217 bool Match(const char* str); 218 int GetMatchCount(); 219 int GetMatchStart(int index); 220 int GetMatchLen(int index); 221 222 private: 223 #ifdef HAVE_REGEX_H 224 regex_t m_context; 225 std::unique_ptr<regmatch_t[]> m_matches; 226 #endif 227 bool m_valid; 228 int m_matchBufSize; 229 }; 230 231 class WildMask 232 { 233 public: 234 WildMask(const char* pattern, bool wantsPositions = false): m_pattern(pattern)235 m_pattern(pattern), m_wantsPositions(wantsPositions) {} 236 bool Match(const char* text); GetMatchCount()237 int GetMatchCount() { return m_wildCount; } GetMatchStart(int index)238 int GetMatchStart(int index) { return m_wildStart[index]; } GetMatchLen(int index)239 int GetMatchLen(int index) { return m_wildLen[index]; } 240 241 private: 242 typedef std::vector<int> IntList; 243 244 CString m_pattern; 245 bool m_wantsPositions; 246 int m_wildCount; 247 IntList m_wildStart; 248 IntList m_wildLen; 249 250 void ExpandArray(); 251 }; 252 253 #ifndef DISABLE_GZIP 254 class ZLib 255 { 256 public: 257 /* 258 * calculates the size required for output buffer 259 */ 260 static uint32 GZipLen(int inputBufferLength); 261 262 /* 263 * compresses inputBuffer and returns the size of bytes written to 264 * outputBuffer or 0 if the buffer is too small or an error occured. 265 */ 266 static uint32 GZip(const void* inputBuffer, int inputBufferLength, void* outputBuffer, int outputBufferLength); 267 }; 268 269 class GUnzipStream 270 { 271 public: 272 enum EStatus 273 { 274 zlError, 275 zlFinished, 276 zlOK 277 }; 278 279 GUnzipStream(int BufferSize); 280 ~GUnzipStream(); 281 282 /* 283 * set next memory block for uncompression 284 */ 285 void Write(const void *inputBuffer, int inputBufferLength); 286 287 /* 288 * get next uncompressed memory block. 289 * iOutputBufferLength - the size of uncompressed block. if it is "0" the next compressed block must be provided via "Write". 290 */ 291 EStatus Read(const void **outputBuffer, int *outputBufferLength); 292 293 private: 294 z_stream m_zStream = {0}; 295 std::unique_ptr<Bytef[]> m_outputBuffer; 296 int m_bufferSize; 297 bool m_active = false; 298 }; 299 #endif 300 301 class Tokenizer 302 { 303 public: 304 Tokenizer(const char* dataString, const char* separators); 305 Tokenizer(char* dataString, const char* separators, bool inplaceBuf); 306 char* Next(); 307 308 private: 309 BString<1024> m_shortString; 310 CString m_longString; 311 char* m_dataString; 312 const char* m_separators; 313 char* m_savePtr = nullptr; 314 bool m_working = false; 315 }; 316 317 class Crc32 318 { 319 public: Crc32()320 Crc32() { Reset(); } 321 void Reset(); 322 void Append(uchar* block, uint32 length); 323 uint32 Finish(); 324 static uint32 Combine(uint32 crc1, uint32 crc2, uint32 len2); 325 326 private: 327 #if defined(WIN32) && !defined(_WIN64) 328 // VC++ in 32 bit mode can not "alignas(16)" dynamically allocated objects 329 alignas(8) uint32_t m_state[4 * 5 + 8]; // = YEncode::crc_state State()330 void* State() { void* p = &m_state; size_t s = sizeof(m_state); return std::align(16, 4 * 5, p, s); } 331 #else 332 alignas(16) uint32_t m_state[4 * 5]; // = YEncode::crc_state 333 void* State() { return &m_state; } 334 #endif 335 }; 336 337 #endif 338