1 /*
2  * util.cpp
3  * libmsn
4  *
5  * Created by Mark Rowe on Mon Mar 22 2004.
6  * Copyright (c) 2004 Mark Rowe. All rights reserved.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22 
23 #include <msn/util.h>
24 #include <errno.h>
25 #include <cstdlib>
26 #include <cctype>
27 #include <cstring>
28 
29 namespace MSN
30 {
splitServerAddress(const std::string & address,int default_port)31     std::pair<std::string, int> splitServerAddress(const std::string & address, int default_port)
32     {
33         size_t pos;
34         std::string host = address;
35         int port = default_port;
36 
37         if ((pos = address.find(":")) != std::string::npos)
38         {
39             std::string port_s = address.substr(pos + 1);
40             host = address.substr(0, pos);
41             port = decimalFromString(port_s);
42         }
43 
44         if (host == "" || port < 0)
45             throw std::runtime_error("Invalid zero-length address or negative port number!");
46 
47         return std::make_pair(host, port);
48     }
49 
decodeURL(const std::string & s)50     std::string decodeURL(const std::string & s)
51     {
52         std::string out;
53         std::string::const_iterator i;
54 
55         for (i = s.begin(); i != s.end(); i++)
56         {
57             if (*i == '%')
58             {
59                 char entity[3] = {*(++i), *(++i), 0};
60                 int c = strtol(entity, NULL, 16);
61                 out += c;
62             }
63             else
64                 out += *i;
65         }
66         return out;
67     }
68 
encodeURL(const std::string & s)69     std::string encodeURL(const std::string & s)
70     {
71         std::string out;
72         std::string::const_iterator i;
73 
74         for (i = s.begin(); i != s.end(); i++)
75         {
76             if(!(isalpha(*i) || isdigit(*i)))
77             {
78                 unsigned char high_nibble = ((unsigned char) *i) >> 4;
79                 unsigned char low_nibble = ((unsigned char) *i) & 0x0F;
80                 out += '%';
81                 out += (high_nibble < 0x0A ? '0' + high_nibble : 'a' + high_nibble - 0x0A);
82                 out += (low_nibble < 0x0A ? '0' + low_nibble : 'a' + low_nibble - 0x0A);
83 
84                 continue;
85             }
86             out += *i;
87         }
88 
89         return out;
90     }
91 
splitString(const std::string & s,const std::string & sep,bool suppressBlanks)92     std::vector<std::string> splitString(const std::string & s, const std::string & sep, bool suppressBlanks)
93     {
94         std::vector<std::string> array;
95         size_t position, last_position;
96 
97         last_position = position = 0;
98         while (position + sep.size() <= s.size())
99         {
100             if (s[position] == sep[0] && s.substr(position, sep.size()) == sep)
101             {
102                 if (!suppressBlanks || position - last_position > 0)
103                     array.push_back(s.substr(last_position, position - last_position));
104                 last_position = position = position + sep.size();
105             }
106             else
107                 position++;
108         }
109         if (!suppressBlanks || last_position - s.size())
110             array.push_back(s.substr(last_position));
111 
112         return array;
113     }
114 
nocase_cmp(const std::string & s1,const std::string & s2)115     int nocase_cmp(const std::string & s1, const std::string& s2)
116     {
117         std::string::const_iterator it1, it2;
118 
119         for (it1 = s1.begin(), it2 = s2.begin();
120              it1 != s1.end() && it2 != s2.end();
121              ++it1, ++it2)
122         {
123             if (std::toupper(*it1) != std::toupper(*it2))
124                 return std::toupper(*it1) - std::toupper(*it2);
125         }
126         size_t size1 = s1.size(), size2 = s2.size();
127         return (int) (size1 - size2);
128     }
129 
decimalFromString(const std::string & s)130     unsigned int decimalFromString(const std::string & s) throw (std::logic_error)
131     {
132         unsigned int result = strtol(s.c_str(), NULL, 10);
133         errno = 0;
134         if (result == 0 && errno != 0)
135             throw std::logic_error(strerror(errno));
136         return result;
137     }
138 }
139