1 // ANNA - Anna is Not Nothingness Anymore //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
17 #include <sys/types.h>
19 #include <sys/utsname.h>
20 #include <arpa/inet.h>
21 #include <sys/socket.h> // extraccion de IP del hostname
22 #include <netinet/in.h> // extraccion de IP del hostname
23 #include <netdb.h> // extraccion de IP del hostname
24 #include <unistd.h> // gethostname
26 #include <anna/core/functions.hpp>
27 #include <anna/core/DataBlock.hpp>
28 #include <anna/core/tracing/Logger.hpp>
29 #include <anna/core/util/Second.hpp>
30 #include <anna/core/util/Tokenizer.hpp>
38 #define PAGE_WIDTH_LENGTH 80
40 static const std::string base64_chars =
41 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
42 "abcdefghijklmnopqrstuvwxyz"
46 string functions::getVersion() throw() {
47 static const int version = ANNA_VERSION;
49 int mainVersion = (version & 0xff00) >> 8;
50 int subVersion = (version & 0xff);
52 sprintf(aux, "%d.%d", mainVersion, subVersion);
54 return result += getArchitecture();
58 (1) Solo coge los dos primeros digitos del numero de release
60 string functions::getArchitecture() throw() {
62 WHEN_MULTITHREAD(result = "/MT");
63 WHEN_SINGLETHREAD(result = "/ST");
77 char* release = anna_strchr(un.release, '.'); // (1)
80 if((release = anna_strchr(release + 1, '.')) != NULL)
90 string functions::asString(const int number)
93 sprintf(aux, "%d", number);
97 string functions::asString(const S64 number)
100 //sprintf(aux, "%lld", number);
102 sprintf (aux, "%ld", number);
104 sprintf (aux, "%lld", number);
109 string functions::asString(const unsigned int number)
112 sprintf(aux, "%u", number);
116 string functions::asString(const U64 number)
119 //sprintf(aux, "%llu", number);
121 sprintf (aux, "%lu", number);
123 sprintf (aux, "%llu", number);
128 string functions::asString(const float number, const char* format)
131 sprintf(aux, format, number);
135 string functions::asString(const double number, const char* format)
138 sprintf(aux, format, number);
142 string functions::asDateTime(const Second &second)
144 char aux [DateTimeSizeString];
145 return std::string(asDateTime(second, aux));
148 const char* functions::asDateTime(const Second &second, char* result)
150 struct tm* tt = localtime((time_t*) & second);
152 result, "%02d/%02d/%4d %02d:%02d:%02d",
153 tt->tm_mday, tt->tm_mon + 1, tt->tm_year + 1900,
154 tt->tm_hour, tt->tm_min, tt->tm_sec
159 std::string functions::asString(const DataBlock& dataBlock, const int characterByLine)
161 return dataBlock.asString(characterByLine);
164 string functions::asHexString(const int number)
167 sprintf(aux, "0x%x", number);
171 string functions::asHexString(const S64 number)
174 //sprintf(aux, "0x%llx", number);
176 sprintf (aux, "0x%lx", number);
178 sprintf (aux, "0x%llx", number);
183 // from a version by Allen Holub (see Andrew Binstock, "Hashing Revisited"
184 // Dr. Dobb's Journal, April 1996)
185 S64 functions::hash(const char* p)
187 static const int long_bits = sizeof(S64) << 3;
188 static const int one_eighth = long_bits >> 3;
189 static const int three_fourths = long_bits * 3 / 4;
190 static const S64 high_bits = ((S64)(~0L)) << (long_bits - one_eighth);
195 result = (result << one_eighth) + *p ++;
197 if((temp = result & high_bits) != 0)
198 result = (result ^(temp >> three_fourths)) &~ high_bits;
205 std::string functions::asHexString(const DataBlock& dataBlock)
207 const char* buffer = dataBlock.getData();
208 const int size = dataBlock.getSize();
212 for(int ii = 0; ii < size; ii ++) {
213 byte = (buffer [ii] & 0xf0) >> 4;
214 result += (byte >= 0 && byte <= 9) ? (byte + '0') : ((byte - 0xa) + 'a');
215 byte = (buffer [ii] & 0x0f);
216 result += (byte >= 0 && byte <= 9) ? (byte + '0') : ((byte - 0xa) + 'a');
223 * Gets the original value obtained with #asHexString (const DataBlock&).
224 * \param hexString String which contains the buffer. The format is an hexadecimal octet sequence representation (i.e. 'af012fb3', with even number of digits).
225 * The input shall be preprocessed to comply with that format (e.g. colon or any other non-hex digit must be removed).
226 * \param target DataBlock for string decode.
227 * \return DataBlock corresponding to the provided string.
230 DataBlock& functions::fromHexString(const std::string& hexString, DataBlock& target)
231 throw(RuntimeException) {
233 if((hexString.length() % 2) != 0)
234 throw RuntimeException("functions::fromHexString | Invalid string length", ANNA_FILE_LOCATION);
237 const char* src = hexString.data();
241 for(int ii = 1, maxii = hexString.length(); ii < maxii; ii += 2) {
242 if(isxdigit(aux = src [ii - 1]) == 0)
243 throw RuntimeException("Invalid HexString", ANNA_FILE_LOCATION);
245 hex = ((aux >= '0' && aux <= '9') ? (aux - '0') : ((aux - 'a') + 0x0a)) << 4;
247 if(isxdigit(aux = src [ii]) == 0)
248 throw RuntimeException("Invalid HexString", ANNA_FILE_LOCATION);
250 hex |= (aux >= '0' && aux <= '9') ? (aux - '0') : ((aux - 'a') + 0x0a);
257 string functions::asString(const char* format, ...)
261 va_start(ap, format);
262 vsnprintf(aux, sizeof(aux), format, ap);
267 void functions::sleep(const Millisecond &millisecond)
271 req.tv_sec = millisecond.getValue() / 1000; // segundos
272 req.tv_nsec = (millisecond.getValue() % 1000); // milisegundos
273 req.tv_nsec *= 1000000; // mili = 10e-3, nano=10-9
276 while((r = nanosleep(&req, &rem)) != 0) {
280 string msg(asText("functions::sleep | timespec { sec: ", (int) req.tv_sec));
281 msg += functions::asText("| nsec: ", (int) req.tv_nsec);
283 RuntimeException ex(msg, errno, ANNA_FILE_LOCATION);
290 bool functions::asBool(const char* str)
291 throw(RuntimeException) {
295 if(strcasecmp(str, "true") == 0 || anna_strcmp(str, "1") == 0)
298 if(strcasecmp(str, "false") == 0 || anna_strcmp(str, "0") == 0)
301 string msg("anna::funcions::asBool | Cannot interpret '");
303 msg += "' as boolean";
304 throw RuntimeException(msg, ANNA_FILE_LOCATION);
307 S64 functions::asInteger64(const char* str)
310 //sscanf(str, "%lld", &number);
312 sscanf (str, "%ld", &number);
314 sscanf (str, "%lld", &number);
319 pthread_t functions::getCurrentThread()
321 WHEN_MULTITHREAD(return pthread_self());
322 WHEN_SINGLETHREAD(return 0);
325 bool functions::isLike(const char* pattern, const std::string& _value)
326 throw(RuntimeException) {
327 const char* value = _value.c_str();
331 if((ret = regcomp(&preg, pattern, REG_EXTENDED)) != 0) {
333 string msg("anna::functions::isLike | ");
334 msg += " | Pattern: ";
340 if(regerror(ret, &preg, err, sizeof(err)))
343 msg += "Invalid pattern";
345 throw RuntimeException(msg, ANNA_FILE_LOCATION);
348 const bool result = (regexec(&preg, value, 0, NULL, 0) == 0) ? true : false;
355 S64 functions::merge(const char* whatis, const int n1, const int n2, const int bitShift)
356 throw(RuntimeException) {
357 if(bitShift > intBitSize) {
358 string msg(functions::asString("%s | N1: 0x%x | N2: 0x%x | bitShift: %d | bitShift must be less than %d", whatis, n1, n2, bitShift, intBitSize));
359 throw RuntimeException(msg, ANNA_FILE_LOCATION);
362 if((bitsize(n1) + bitShift) > int64BitSize) {
363 string msg(functions::asString("%s | N1: 0x%x | N2: 0x%x | bitShift: %d | N1 overload", whatis, n1, n2, bitShift));
364 throw RuntimeException(msg, ANNA_FILE_LOCATION);
367 if(bitsize(n2) > bitShift) {
368 string msg(functions::asString("%s | N1: 0x%x | N2: 0x%x | bitShift: %d | N2 overload", whatis, n1, n2, bitShift));
369 throw RuntimeException(msg, ANNA_FILE_LOCATION);
376 if(bitShift == intBitSize) {
378 string msg(functions::asString("%s | N1: 0x%x | N2: 0x%x | bitShift: %d | ", whatis, n1, n2, bitShift));
379 msg += functions::asHexString(result);
380 Logger::information(msg, ANNA_FILE_LOCATION);
389 * Basado en el algoritmo de http://www-graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup
391 int functions::log2(const unsigned int v)
393 static const signed char LogTable256[] = {
394 -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
395 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
396 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
397 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
398 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
399 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
400 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
401 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
402 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
403 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
404 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
405 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
406 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
407 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
408 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
409 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
411 int r = -1; // r will be lg(v)
412 unsigned int t, tt; // temporaries
415 r = ((t = tt >> 8)) ? 24 + LogTable256[t] : 16 + LogTable256[tt];
417 r = (t = v >> 8) ? 8 + LogTable256[t] : LogTable256[v];
423 std::string functions::entriesAsString(int number, const char * wordForSingular, const char * wordForPlural) throw() {
425 std::string singular = (wordForSingular ? wordForSingular : "entry");
426 std::string plural = (wordForPlural ? wordForPlural : "entries");
428 if(wordForSingular && !wordForPlural)
429 plural = singular + "s";
431 result += ((number != 0) ? anna::functions::asString(number) : "no");
433 result += ((number != 1) ? plural : singular);
438 std::string functions::justify(const std::string & title, TextJustifyMode::_v mode, char filler) throw() {
440 int d_size = title.size();
441 int repeat = PAGE_WIDTH_LENGTH - d_size - 1;
444 if(mode == TextJustifyMode::Center) {
445 repeat = (repeat - 1) / 2;
446 adjust = (2 * (repeat + 1) + d_size != PAGE_WIDTH_LENGTH);
449 if((mode == TextJustifyMode::Right) || (mode == TextJustifyMode::Center)) {
450 for(int k = 0; k < (repeat + (adjust ? 1 : 0)); k++) result += filler;
457 if((mode == TextJustifyMode::Left) || (mode == TextJustifyMode::Center)) {
460 for(int k = 0; k < repeat; k++) result += filler;
467 std::string functions::highlight(const std::string & title, TextHighlightMode::_v mode, char filler, bool appendCR) throw() {
469 int ou_repeat = title.size();
470 int lr_repeat = PAGE_WIDTH_LENGTH - ou_repeat - 1;
473 if(mode == TextHighlightMode::LeftAndRightline) {
474 lr_repeat = (lr_repeat - 1) / 2;
475 adjust = (2 * (lr_repeat + 1) + ou_repeat != PAGE_WIDTH_LENGTH);
478 if((mode == TextHighlightMode::Leftline) || (mode == TextHighlightMode::LeftAndRightline)) {
479 for(int k = 0; k < (lr_repeat + (adjust ? 1 : 0)); k++) result += filler;
484 if((mode == TextHighlightMode::Overline) || (mode == TextHighlightMode::OverAndUnderline)) {
485 for(int k = 0; k < ou_repeat; k++) result += filler;
492 if((mode == TextHighlightMode::Underline) || (mode == TextHighlightMode::OverAndUnderline)) {
495 for(int k = 0; k < ou_repeat; k++) result += filler;
498 if((mode == TextHighlightMode::Rightline) || (mode == TextHighlightMode::LeftAndRightline)) {
501 for(int k = 0; k < lr_repeat; k++) result += filler;
504 if(appendCR) result += "\n";
510 std::string functions::tab(const std::string & text, int tabSpaces) throw() {
512 size_t pos, from = 0;
513 std::string tab, crTab = "\n";
515 for(int k = 0; k < tabSpaces; k++) tab += " ";
521 while(((pos = result.find('\n', from)) != std::string::npos) && (pos != (result.size() - 1)/*exclude last CR if exists*/)) {
522 result.replace(pos, 1, crTab);
530 bool functions::endsWith(const std::string & pattern, const std::string & suffix, std::string & preffix) throw() {
533 if(pattern.size() < suffix.size()) return false;
535 size_t pos = pattern.rfind(suffix);
537 if(pos == std::string::npos) return false;
539 preffix.assign(pattern.c_str(), pos);
540 return (pos == (pattern.size() - suffix.size()));
544 bool functions::startsWith(const std::string & pattern, const std::string & preffix, std::string & suffix) throw() {
547 if(pattern.size() < preffix.size()) return false;
549 if(pattern.find(preffix) != 0) return false;
551 suffix.assign(pattern.c_str(), preffix.size(), pattern.size() - preffix.size());
556 std::string functions::replace(const std::string & text, const char *item, const char *target, bool all) throw() {
557 std::string result = text;
559 if(!item || !target) return result; // protection for NULL strings provided
561 size_t lengthReplaced = strlen(item);
562 size_t pos = result.find(item);
564 while(pos != std::string::npos) {
565 result.replace(pos, lengthReplaced, target);
569 pos = result.find(item);
576 std::string functions::addQuotationMarks(const std::string & str) throw() {
577 std::string result = "'";
584 std::string functions::addQuotationMarks(const char * str) throw() {
585 std::string result = "'";
586 result += (str ? str : "<null>");
592 std::string functions::addQuotationMarks(const int & integer) throw() {
593 std::string result = "'";
594 result += anna::functions::asString(integer);
600 std::string functions::vectorToStringRepresentation(const std::vector<int> & v, const char separator) throw() {
601 std::string result = "";
604 std::vector<int>::const_iterator iter;
605 std::vector<int>::const_iterator iter_min(v.begin());
606 std::vector<int>::const_iterator iter_max(v.end());
608 for(iter = iter_min; iter != iter_max; iter++) {
609 result += anna::functions::asString(*iter);
613 // Delete the last space: starts at 'size()-1', take 1 caracter:
614 result.erase(result.size() - 1, 1);
621 std::string functions::vectorToStringRepresentation(const std::vector<std::string> & v, const char separator) throw() {
622 std::string result = "";
625 std::vector<std::string>::const_iterator iter;
626 std::vector<std::string>::const_iterator iter_min(v.begin());
627 std::vector<std::string>::const_iterator iter_max(v.end());
629 for(iter = iter_min; iter != iter_max; iter++) {
634 // Delete the last space: starts at 'size()-1', take 1 caracter:
635 result.erase(result.size() - 1, 1);
642 std::string functions::socketLiteralAsString(const std::string & address, int port) throw() {
643 std::string result = address;
645 result += anna::functions::asString(port);
650 std::string functions::asAsciiString(const char * buffer, int size, bool & isFullyPrintable) throw() {
652 // Supposed printable by default:
653 isFullyPrintable = true;
655 if(size == 0 || !buffer) {
657 isFullyPrintable = false;
661 for(int k = 0; k < size; k ++) {
662 unsigned char c = (unsigned char) buffer [k];
663 int printable = isprint(c);
664 result += (printable ? (char) c : '.');
666 if(!printable) isFullyPrintable = false;
673 std::string functions::getHostname() throw() {
675 std::string result = "<hostname>";
677 if(gethostname(aux, sizeof aux) == 0 /*success*/)
683 std::string functions::getDomainname() throw() {
685 std::string result = "<domainname>";
687 if(getdomainname(aux, sizeof aux) == 0 /*success*/)
693 std::string functions::getFQDN(const char *hostname, const char *domainname) throw() {
694 std::string hn = hostname ? hostname : (functions::getHostname());
695 std::string dn = domainname ? domainname : (functions::getDomainname());
696 // FQDN is limited to 255 bytes, with aditional restriction: 63 bytes label within a domain name.
698 if(hn == "") return dn;
700 if(dn == "") return hn;
702 std::string label(hn, 0, 63);
703 std::string fqdn(label + "." + dn, 0, 255);
707 std::string functions::getHostnameIP() throw() {
708 std::string result = "";
710 struct in_addr **addr_list;
712 gethostname(hostname, sizeof hostname);
714 if((he = gethostbyname(hostname)) != NULL) {
715 // Official name: he->h_name
717 addr_list = (struct in_addr **)he->h_addr_list;
719 for(int i = 0; addr_list[i] != NULL; i++) {
720 //printf("%s ", inet_ntoa(*addr_list[i]));
721 result = inet_ntoa(*addr_list[i]);
730 anna::DataBlock functions::rawIpPresentationAsRaw(const std::string & rawPresentation) throw(anna::RuntimeException) {
731 int length = rawPresentation.size();
733 if(length != 8 && length != 32)
734 throw anna::RuntimeException("functions::rawIpPresentationAsRaw | Expected 8 or 32-sized raw IP presentation provided", ANNA_FILE_LOCATION);
736 anna::DataBlock result(true);
738 char rByte[3]; // readable byte
741 for(int k = 0; k < length; k += 2) {
742 rByte[0] = rawPresentation[k];
743 rByte[1] = rawPresentation[k + 1];
744 sscanf(rByte, "%x", &byte);
752 std::string functions::rawIpAsRawIpPresentation(const anna::DataBlock & db) throw(anna::RuntimeException) {
753 int length = db.getSize();
755 if(length != 4 && length != 16)
756 throw anna::RuntimeException("functions::rawIpAsRawIpPresentation | Expected 4 or 16-sized raw IP DataBlock provided", ANNA_FILE_LOCATION);
758 std::string result = "";
760 char rByte[3]; // readable byte
763 for(int k = 0; k < length; k++) {
764 byte = (unsigned char)db[k];
765 sprintf(rByte, "%.2X", byte);
777 // IPv6 addresses have two logical parts: a 64-bit network prefix, and a 64-bit host address part. (The host address is often automatically generated from the interface MAC address.[34]) An IPv6 address is represented by 8 groups of 16-bit hexadecimal values separated by colons (:) shown as follows:
778 // A typical example of an IPv6 address is
779 // 2001:0db8:85a3:0000:0000:8a2e:0370:7334
780 // The hexadecimal digits are case-insensitive.
782 // The 128-bit IPv6 address can be abbreviated with the following rules:
783 // -Rule one: Leading zeroes within a 16-bit value may be omitted. For example, the address fe80:0000:0000:0000:0202:b3ff:fe1e:8329 may be written as fe80:0:0:0:202:b3ff:fe1e:8329
784 // -Rule two: A single occurrence of consecutive groups of zeroes within an address may be replaced by a double colon. For example, fe80:0:0:0:202:b3ff:fe1e:8329 becomes fe80::202:b3ff:fe1e:8329
785 // A single IPv6 address can be represented in several different ways, such as 2001:db8::1:0:0:1 and 2001:0DB8:0:0:1::1. RFC 5952 recommends a canonical textual representation.
787 // Si la dirección tiene más de una serie de grupos nulos consecutivos la compresión sólo se permite en uno de ellos.
788 // AsÃ, las siguientes son representaciones posibles de una misma dirección:
790 // 2001:0DB8:0000:0000:0000:0000:1428:57ab
791 // 2001:0DB8:0000:0000:0000::1428:57ab
792 // 2001:0DB8:0:0:0:0:1428:57ab
793 // 2001:0DB8:0::0:1428:57ab
794 // 2001:0DB8::1428:57ab
795 // son todas válidas y significan lo mismo, pero
798 // no es válida porque no queda claro cuántos grupos nulos hay en cada lado.
800 // Los ceros iniciales en un grupo también se pueden omitir:
801 // 2001:0DB8:02de::0e13
804 // Si la dirección es una dirección IPv4 empotrada (mapped), los últimos 32 bits pueden escribirse en base decimal, asÃ:
805 // ::ffff:192.168.89.9
808 // No se debe confundir con:
812 // El formato ::ffff:1.2.3.4 se denomina dirección IPv4 mapeada, y el formato ::1.2.3.4 dirección IPv4 compatible.
813 // Las direcciones IPv4 pueden ser transformadas fácilmente al formato IPv6. Por ejemplo, si la dirección decimal IPv4 es 135.75.43.52
814 // (en hexadecimal, 0x874B2B34), puede ser convertida a 0000:0000:0000:0000:0000:0000:874B:2B34 o ::874B:2B34. Entonces, uno puede usar
815 // la notación mixta dirección IPv4 compatible, en cuyo caso la dirección deberÃa ser ::135.75.43.52. Este tipo de dirección IPv4 compatible
816 // casi no está siendo utilizada en la práctica, aunque los estándares no la han declarado obsoleta.
818 // http://tools.ietf.org/html/rfc5952: canonical text representation recommendation
820 bool functions::isIPv4(const std::string & ip, IPv4Type::_v ipv4Type) throw() {
821 if(ipv4Type == IPv4Type::Estrict) {
822 // La expresión regular no controla si hay mas de 3 puntos:
825 for(int k = 0; k < ip.length(); k++)
826 if(ip[k] == '.') n_dot++;
831 bool ipv4 = anna::functions::isLike(s_REGEXP_IPv4_ADDRESSES, ip);
832 bool colon = (ip.find(":") != std::string::npos);
833 return (ipv4 && !colon);
836 if(ipv4Type == IPv4Type::Compatible) {
837 std::string pureIPv4 = ip;
838 bool firstDoubleColon = (ip.find("::") == 0);
840 if(firstDoubleColon) {
841 pureIPv4.erase(0, 2);
842 bool anotherColon = (pureIPv4.find(":") != std::string::npos);
844 if(anotherColon) return (false);
846 return (anna::functions::isLike(s_REGEXP_IPv4_ADDRESSES, pureIPv4));
850 if(ipv4Type == IPv4Type::Mapped) {
851 size_t posLastColon = ip.rfind(":");
853 if(posLastColon == std::string::npos)
856 if(!isIPv4(ip.substr(posLastColon + 1)))
859 unsigned char buf[sizeof(struct in6_addr)];
860 int s = inet_pton(AF_INET6, ip.c_str(), buf);
870 bool functions::isIPv6(const std::string & ip) throw() {
871 // Chequeo de digitos permitidos:
872 for(int k = 0; k < ip.length(); k++) {
873 bool digit = isdigit(ip[k]);
874 bool hex = ((ip[k] == 'a') ||
886 bool colon = (ip[k] == ':');
888 if(!digit && !hex && !colon)
892 return (anna::functions::isLike(s_REGEXP_IPv6_ADDRESSES, ip));
896 std::string functions::IPv4To6(const std::string & ip) throw(anna::RuntimeException) {
897 if(!isIPv4(ip, IPv4Type::Estrict) && !isIPv4(ip, IPv4Type::Compatible) && !isIPv4(ip, IPv4Type::Mapped))
898 throw anna::RuntimeException("functions::IPv4To6 | Expected IPv4, IPv4-compatible or IPv4-mapped address format", ANNA_FILE_LOCATION);
900 std::string result, pureIPv4;
901 bool firstDoubleColon = (ip.find("::") == 0);
903 if(firstDoubleColon) {
905 size_t ipv4_pos = ip.rfind(":") /* last ocurrence */ + 1;
906 pureIPv4 = ip.substr(ipv4_pos);
909 size_t posColon = ip.find(":");
911 if(posColon == 0) // first colon
912 throw anna::RuntimeException("functions::IPv4To6 | Invalid IPv4 address format", ANNA_FILE_LOCATION);
914 if(posColon != std::string::npos) // any colon
915 return ip; // seems to be IPv6 already?
917 throw anna::RuntimeException("functions::IPv4To6 | Unreconized IPv4 address format", ANNA_FILE_LOCATION);
923 // Number of ocurrences for '.'
926 for(int k = 0; k < pureIPv4.length(); k++)
927 if(pureIPv4[k] == '.') n_dot++;
930 throw anna::RuntimeException("functions::IPv4To6 | Wrong IPv4 address format (more than three dots!)", ANNA_FILE_LOCATION);
933 anna::Tokenizer::const_iterator tok_it;
935 tok.apply(pureIPv4, ".");
939 for(tok_it = tok.begin(); tok_it != tok.end(); tok_it ++) {
940 token = anna::Tokenizer::data(tok_it);
941 v[cnt] = atoi(anna::Tokenizer::data(tok_it));
943 if(v[cnt] < 0 || v[cnt] > 255)
944 throw anna::RuntimeException("functions::IPv4To6 | Wrong IPv4 address format (any value out of range 0-255)", ANNA_FILE_LOCATION);
949 if(isIPv4(ip, IPv4Type::Compatible))
950 result = anna::functions::asString("::%04x:%04x", v[0] * 256 + v[1], v[2] * 256 + v[3]);
952 result = anna::functions::asString("::ffff:%04x:%04x", v[0] * 256 + v[1], v[2] * 256 + v[3]);
958 std::string functions::normalizeIP(const std::string & ip) throw(anna::RuntimeException) {
959 std::string result = ip;
960 // std::transform(result.begin(), result.end(), result.begin(), (int (*)(int))std::tolower);
961 std::transform(result.begin(), result.end(), result.begin(), ::tolower);
963 if(isIPv4(ip, IPv4Type::Estrict) || isIPv4(ip, IPv4Type::Compatible) || isIPv4(ip, IPv4Type::Mapped))
964 result = IPv4To6(result);
966 size_t pos = result.find("::"); // zeroes simplification group
967 size_t rpos = result.rfind("::"); // zeroes simplification group
970 throw anna::RuntimeException("functions::normalizeIP | Wrong IPv6 address format (more than one simplification group '::')", ANNA_FILE_LOCATION);
972 if(pos != std::string::npos) { // zeroes exists
973 // string ( size_t n, char c ) -> content is initialized as a string formed by a repetition of character c, n times.
974 // Number of ocurrences for ':'
977 for(int k = 0; k < result.length(); k++)
978 if(result[k] == ':') n_colon++;
980 // Generate equivalent to '::'
981 std::string equiv_str;
983 for(int k = 0; k < (8 - n_colon); k++)
987 // Replace with equivalent:
988 result.replace(pos, 2, equiv_str);
990 // Special case: IP began with '::'
991 if(result[0] == ':') {
992 result.insert(0, "0");
995 // Special case: IP was only '::'
996 if(result[result.length() - 1] == ':') {
1001 // Protection: it must be seven colons:
1004 for(int k = 0; k < result.length(); k++)
1005 if(result[k] == ':') n_colon++;
1008 throw anna::RuntimeException("functions::normalizeIP | Wrong IPv6 address format (missing any 16-bit group)", ANNA_FILE_LOCATION);
1010 // Padding with zeroes at left
1011 anna::Tokenizer ipStr;
1012 anna::Tokenizer::const_iterator ipStr_it;
1014 ipStr.apply(result, ":");
1017 for(ipStr_it = ipStr.begin(); ipStr_it != ipStr.end(); ipStr_it ++) {
1018 token = anna::Tokenizer::data(ipStr_it);
1020 while(token.length() < 4) token.insert(0, "0");
1027 size_t lastPos = result.length() - 1;
1028 result.erase(lastPos, 1);
1030 // Chequeo de digitos permitidos:
1031 for(int k = 0; k < result.length(); k++) {
1032 bool digit = isdigit(result[k]);
1033 bool hex = ((result[k] == 'a') ||
1034 (result[k] == 'b') ||
1035 (result[k] == 'c') ||
1036 (result[k] == 'd') ||
1037 (result[k] == 'e') ||
1038 (result[k] == 'f'));
1039 bool colon = (result[k] == ':');
1041 if(!digit && !hex && !colon) {
1042 throw anna::RuntimeException("functions::normalizeIP | Invalid address format (only digits (0-9) and hex digits are allowed)", ANNA_FILE_LOCATION);
1050 bool functions::sameIP(const std::string & ip1, const std::string & ip2) throw(anna::RuntimeException) {
1051 //if (ip1 == ip2) return true; it should validate wrong-format addresses
1052 return (normalizeIP(ip1) == normalizeIP(ip2));
1056 bool functions::matchIPv6(const std::string & _ipv6, const std::string & preffixedIpv6) throw(anna::RuntimeException) {
1057 size_t preffixPos = preffixedIpv6.find("/");
1059 if(preffixPos == std::string::npos)
1060 return (sameIP(_ipv6, preffixedIpv6));
1062 std::string ipv6 = _ipv6;
1064 if(isIPv4(_ipv6, IPv4Type::Estrict) || isIPv4(_ipv6, IPv4Type::Compatible) || isIPv4(_ipv6, IPv4Type::Mapped)) ipv6 = IPv4To6(_ipv6);
1066 std::string _ipv6_2 = preffixedIpv6.substr(0, preffixPos);
1067 std::string ipv6_2 = _ipv6_2;
1069 if(isIPv4(_ipv6_2, IPv4Type::Estrict) || isIPv4(_ipv6_2, IPv4Type::Compatible) || isIPv4(_ipv6_2, IPv4Type::Mapped)) ipv6_2 = IPv4To6(_ipv6_2);
1071 std::string preffix = preffixedIpv6.substr(preffixPos + 1);
1072 int ipv6_2_preffixLength = atoi(preffix.c_str());
1074 if(ipv6_2_preffixLength < 0 || ipv6_2_preffixLength > 128)
1075 throw anna::RuntimeException("functions::matchIPv6 | Invalid Ipv6 preffix length: out of range [0,128]", ANNA_FILE_LOCATION);
1077 // No restriction, all ipv6_2 ignored (special and not usual case)
1078 if(ipv6_2_preffixLength == 0) return true;
1081 int spare = ipv6_2_preffixLength /* bits */ % 8; // bytes
1082 int incompletedRestrictionBytes = ipv6_2_preffixLength / 8;
1083 int completedRestrictionBytes = incompletedRestrictionBytes + ((spare != 0) ? 1 : 0);
1084 char mask = 0xFF << (8 - spare);
1086 anna::DataBlock rawIP1 = ipAsRaw(ipv6);
1087 anna::DataBlock restrictedIP1(true);
1088 restrictedIP1.assign(rawIP1.getData(), incompletedRestrictionBytes);
1090 if(spare != 0) restrictedIP1 += rawIP1[incompletedRestrictionBytes] & mask;
1093 anna::DataBlock rawIP2 = ipAsRaw(ipv6_2);
1094 anna::DataBlock realIP2(true);
1095 realIP2.assign(rawIP2.getData(), incompletedRestrictionBytes);
1097 if(spare != 0) realIP2 += rawIP2[incompletedRestrictionBytes] & mask;
1100 int n = memcmp(restrictedIP1.getData(), realIP2.getData(), completedRestrictionBytes);
1105 anna::DataBlock functions::ipAsRaw(const std::string & ip) throw(anna::RuntimeException) {
1106 anna::DataBlock result(true);
1109 unsigned char buf[sizeof(struct in6_addr)];
1110 int s = inet_pton(AF_INET, ip.c_str(), buf);
1113 result += (S8)buf[0];
1114 result += (S8)buf[1];
1115 result += (S8)buf[2];
1116 result += (S8)buf[3];
1118 if(s < 0) perror("inet_pton");
1120 throw anna::RuntimeException("functions::ipAsRaw | Wrong IPv4 address format", ANNA_FILE_LOCATION);
1123 unsigned char buf[sizeof(struct in6_addr)];
1124 int s = inet_pton(AF_INET6, ip.c_str(), buf);
1127 result += (S8)buf[0];
1128 result += (S8)buf[1];
1129 result += (S8)buf[2];
1130 result += (S8)buf[3];
1131 result += (S8)buf[4];
1132 result += (S8)buf[5];
1133 result += (S8)buf[6];
1134 result += (S8)buf[7];
1135 result += (S8)buf[8];
1136 result += (S8)buf[9];
1137 result += (S8)buf[10];
1138 result += (S8)buf[11];
1139 result += (S8)buf[12];
1140 result += (S8)buf[13];
1141 result += (S8)buf[14];
1142 result += (S8)buf[15];
1144 if(s < 0) perror("inet_pton");
1146 throw anna::RuntimeException("functions::ipAsRaw | Wrong IPv6 address format", ANNA_FILE_LOCATION);
1152 // anna::DataBlock result(true);
1155 // if (isIPv4(ip)) {
1157 // int dec1, dec2, dec3, dec4; // U32 type is valid, 'int' better: argument for %d must be 'int *' (http://www.cplusplus.com/reference/clibrary/cstdio/sscanf/)
1158 // sscanf(ip.c_str(), "%d.%d.%d.%d", &dec1, &dec2, &dec3, &dec4);
1159 // result += (S8)dec1;
1160 // result += (S8)dec2;
1161 // result += (S8)dec3;
1162 // result += (S8)dec4;
1166 // int hex1, hex2, hex3, hex4, hex5, hex6, hex7, hex8; // U16 type is not valid: argument for %X must be 'int *' (http://www.cplusplus.com/reference/clibrary/cstdio/sscanf/)
1167 // sscanf(normalizeIP(ip).c_str(), "%X:%X:%X:%X:%X:%X:%X:%X", &hex1, &hex2, &hex3, &hex4, &hex5, &hex6, &hex7, &hex8);
1168 // result += ((S8)(hex1 >> 8));
1169 // result += ((S8)(hex1 & 0x00FF));
1170 // result += ((S8)(hex2 >> 8));
1171 // result += ((S8)(hex2 & 0x00FF));
1172 // result += ((S8)(hex3 >> 8));
1173 // result += ((S8)(hex3 & 0x00FF));
1174 // result += ((S8)(hex4 >> 8));
1175 // result += ((S8)(hex4 & 0x00FF));
1176 // result += ((S8)(hex5 >> 8));
1177 // result += ((S8)(hex5 & 0x00FF));
1178 // result += ((S8)(hex6 >> 8));
1179 // result += ((S8)(hex6 & 0x00FF));
1180 // result += ((S8)(hex7 >> 8));
1181 // result += ((S8)(hex7 & 0x00FF));
1182 // result += ((S8)(hex8 >> 8));
1183 // result += ((S8)(hex8 & 0x00FF));
1191 std::string functions::rawIpAsString(const char *buffer, int bufferLength, bool normalize) throw(anna::RuntimeException) {
1192 std::string result = "";
1193 char str[INET6_ADDRSTRLEN];
1195 if(bufferLength == 4) {
1196 if(inet_ntop(AF_INET, buffer, str, INET_ADDRSTRLEN) != NULL)
1198 } else if(bufferLength == 16) {
1199 if(inet_ntop(AF_INET6, buffer, str, INET6_ADDRSTRLEN) != NULL)
1202 throw anna::RuntimeException("functions::rawIpAsString | Unreconized IP address format (only 4-byte for IPv4, and 16-byte for IPv6 are allowed)", ANNA_FILE_LOCATION);
1205 throw anna::RuntimeException("functions::rawIpAsString | Wrong IP address serialization (check range value)", ANNA_FILE_LOCATION);
1207 return (normalize ? normalizeIP(result) : result);
1209 // std::string result;
1212 // if (bufferLength == 4) { // IPv4
1213 // result = anna::functions::asString("%d.%d.%d.%d", (U8)buffer[0], (U8)buffer[1], (U8)buffer[2], (U8)buffer[3]);
1215 // else if (bufferLength == 16) { // IPv6
1216 // result = anna::functions::asString("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
1217 // ((((U8)buffer[0]) << 8) & 0xFF00 /* same as (U16 cast)*/) +
1218 // (((U8)buffer[1]) & 0x00FF),
1219 // ((((U8)buffer[2]) << 8) & 0xFF00) +
1220 // (((U8)buffer[3]) & 0x00FF),
1221 // ((((U8)buffer[4]) << 8) & 0xFF00) +
1222 // (((U8)buffer[5]) & 0x00FF),
1223 // ((((U8)buffer[6]) << 8) & 0xFF00) +
1224 // (((U8)buffer[7]) & 0x00FF),
1225 // ((((U8)buffer[8]) << 8) & 0xFF00) +
1226 // (((U8)buffer[9]) & 0x00FF),
1227 // ((((U8)buffer[10]) << 8) & 0xFF00) +
1228 // (((U8)buffer[11]) & 0x00FF),
1229 // ((((U8)buffer[12]) << 8) & 0xFF00) +
1230 // (((U8)buffer[13]) & 0x00FF),
1231 // ((((U8)buffer[14]) << 8) & 0xFF00) +
1232 // (((U8)buffer[15]) & 0x00FF));
1235 // throw anna::RuntimeException("functions::rawIpAsString | Unreconized IP address format (only 4-byte for IPv4, and 16-byte for IPv6 are allowed)", ANNA_FILE_LOCATION);
1238 // return (normalize ? normalizeIP(result):result);
1242 void functions::getAddressAndPortFromSocketLiteral(const std::string &literal, std::string &address, int &port) throw() {
1243 size_t pos = literal.find_last_of(":");
1244 size_t lastPos = literal.size() - 1;
1245 address = ""; port = -1; // assume error
1247 if((pos != std::string::npos) && (pos != lastPos)) {
1248 address = literal.substr(0, pos);
1249 port = atoi(literal.substr(pos + 1, lastPos).c_str());
1254 socket_v functions::getSocketVectorFromString(const std::string & list) throw() {
1256 std::string address;
1258 anna::Tokenizer lst;
1259 lst.apply(list, ",");
1261 if(lst.size() < 1) return result;
1263 anna::Tokenizer::const_iterator tok_min(lst.begin());
1264 anna::Tokenizer::const_iterator tok_max(lst.end());
1265 anna::Tokenizer::const_iterator tok_iter;
1267 for(tok_iter = tok_min; tok_iter != tok_max; tok_iter++) {
1268 getAddressAndPortFromSocketLiteral(anna::Tokenizer::data(tok_iter), address, port);
1270 if(port == -1) { result.clear(); return result; }
1272 result.push_back(socket_t(address, port));
1278 std::string functions::socketVectorAsString(const socket_v & socketVector) throw() {
1281 socket_v_it it_min(socketVector.begin());
1282 socket_v_it it_max(socketVector.end());
1284 for(it = it_min; it != it_max; it++) {
1285 result += anna::functions::asString("%s:%d,", (*it).first.c_str(), (*it).second);
1288 result.erase(result.size() - 1, 1); // remove last comma
1292 bool functions::littleEndian()
1295 char *p = (char *) &i;
1296 if (p[0] == 1) return true;
1300 const char* functions::codeInteger(char* result, const int n)
1303 char* w((char*) &aux);
1305 *(result + 1) = *(w + 1);
1306 *(result + 2) = *(w + 2);
1307 *(result + 3) = *(w + 3);
1311 const char* functions::codeShort(char* result, const short int n)
1313 short int aux(htons(n));
1314 char* w((char*) &aux);
1316 *(result + 1) = *(w + 1);
1320 const char* functions::codeInteger64(char* result, const S64 n)
1322 S64 aux(0xffffffff);
1326 n2 = (aux >> 32) & 0xffffffff;
1327 codeInteger(result, n2);
1328 n2 = n & 0xffffffff;
1329 codeInteger(result + sizeof(int), n2);
1334 const char* functions::codeFloat(char* result, const float n)
1337 anna_memcpy(&ii, &n, sizeof(n));
1338 return functions::codeInteger(result, ii);
1342 const char* functions::codeDouble(char* result, const double n)
1345 anna_memcpy(&ii, &n, sizeof(n));
1346 return functions::codeInteger64(result, ii);
1349 int functions::decodeInteger(const char* data)
1352 char* w((char*) &result);
1354 *(w + 1) = *(data + 1);
1355 *(w + 2) = *(data + 2);
1356 *(w + 3) = *(data + 3);
1357 return ntohl(result);
1360 short int functions::decodeShort(const char* data)
1363 char* w((char*) &result);
1365 *(w + 1) = *(data + 1);
1366 return ntohs(result);
1369 S64 functions::decodeInteger64(const char* data)
1371 S64 result(decodeInteger(data));
1373 return result |= (decodeInteger(data + sizeof(int)) & 0xffffffff);
1377 float functions::decodeFloat(const char* data)
1380 int ii = functions::decodeInteger(data);
1381 anna_memcpy(&result, &ii, sizeof(result));
1386 double functions::decodeDouble(const char* data)
1389 S64 ii = functions::decodeInteger64(data);
1390 anna_memcpy(&result, &ii, sizeof(result));
1396 void functions::decodeIsupNumber(const char *buffer, int length, isup_number_t & isupNumber, bool calledOrCalling) throw(anna::RuntimeException) {
1397 #define DECODE2BYTES_INDX_VALUETYPE(buffer,indx,value_type) ((((value_type)buffer[indx] << 8) & 0xFF00) + ((value_type)buffer[indx+1] & 0x00FF))
1399 isupNumber.OddEven = (short)((buffer[0] >> 7) & 0x01);
1400 bool filler = isupNumber.OddEven;
1402 if(filler && ((buffer [length - 1] & 0xf0) != 0x00))
1403 throw anna::RuntimeException("functions::decodeIsupNumber | Isup number filler must be '0000'", ANNA_FILE_LOCATION);
1405 isupNumber.NatureOfAddress = (short)(buffer[0] & 0x7F);
1406 isupNumber.NumberingPlan = (short)((buffer[1] >> 4) & 0x07);
1408 if(calledOrCalling) {
1409 isupNumber.InternalNetworkNumber = (short)((buffer[1] >> 7) & 0x01);
1411 isupNumber.NumberIncomplete = (short)((buffer[1] >> 7) & 0x01);
1412 isupNumber.AddressPresentationRestricted = (short)((buffer[1] >> 2) & 0x03);
1413 isupNumber.Screening = (short)(buffer[1] & 0x03);
1417 isupNumber.Digits = "";
1420 for(int k = 2; k < length; k ++) {
1421 byte = (buffer [k] & 0x0f);
1422 isupNumber.Digits += (byte >= 0 && byte <= 9) ? (byte + '0') : ((byte - 0xa) + 'a');
1423 byte = (buffer [k] & 0xf0) >> 4;
1424 isupNumber.Digits += (byte >= 0 && byte <= 9) ? (byte + '0') : ((byte - 0xa) + 'a');
1427 if(filler) isupNumber.Digits.erase(isupNumber.Digits.size() - 1, 1); // remove filler
1431 void functions::codeIsupNumber(const isup_number_t & isupNumber, bool calledOrCalling, std::string & target) throw(anna::RuntimeException) {
1433 if(isupNumber.OddEven < 0 || isupNumber.OddEven > 1)
1434 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'OddEven' field out of range [0,1]", ANNA_FILE_LOCATION);
1436 bool odd = isupNumber.OddEven;
1437 bool oddDigits = (isupNumber.Digits.size() % 2);
1439 if(odd != oddDigits)
1440 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'OddEven' field doesn't correspond to the number of digits on 'Digits' field", ANNA_FILE_LOCATION);
1442 if(isupNumber.NatureOfAddress < 0 || isupNumber.NatureOfAddress > 127)
1443 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'NatureOfAddress' field out of range [0,127]", ANNA_FILE_LOCATION);
1445 if(isupNumber.NumberingPlan < 0 || isupNumber.NumberingPlan > 7)
1446 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'NumberingPlan' field out of range [0,7]", ANNA_FILE_LOCATION);
1448 if(calledOrCalling) {
1449 if(isupNumber.NumberIncomplete != 0)
1450 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'NumberIncomplete' field present on Called Party Number !", ANNA_FILE_LOCATION);
1452 if(isupNumber.AddressPresentationRestricted != 0)
1453 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'AddressPresentationRestricted' field present on Called Party Number !", ANNA_FILE_LOCATION);
1455 if(isupNumber.Screening != 0)
1456 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Screening' field present on Called Party Number !", ANNA_FILE_LOCATION);
1458 if(isupNumber.InternalNetworkNumber < 0 || isupNumber.InternalNetworkNumber > 1)
1459 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'InternalNetworkNumber' field out of range [0,1]", ANNA_FILE_LOCATION);
1461 if(isupNumber.InternalNetworkNumber != 0)
1462 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'InternalNetworkNumber' field present on Calling Party Number !", ANNA_FILE_LOCATION);
1464 if(isupNumber.NumberIncomplete < 0 || isupNumber.NumberIncomplete > 1)
1465 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'NumberIncomplete' field out of range [0,1]", ANNA_FILE_LOCATION);
1467 if(isupNumber.AddressPresentationRestricted < 0 || isupNumber.AddressPresentationRestricted > 3)
1468 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'AddressPresentationRestricted' field out of range [0,3]", ANNA_FILE_LOCATION);
1470 if(isupNumber.Screening < 0 || isupNumber.Screening > 3)
1471 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Screening' field out of range [0,3]", ANNA_FILE_LOCATION);
1476 bool filler = isupNumber.OddEven;
1477 bool hasDigits = (isupNumber.Digits.size() > 0);
1478 byte = filler ? 0x80 : 0x00;
1479 byte |= isupNumber.NatureOfAddress;
1482 if(calledOrCalling) {
1483 byte = isupNumber.InternalNetworkNumber << 7;
1484 byte |= (isupNumber.NumberingPlan << 4);
1486 byte = isupNumber.NumberIncomplete << 7;
1487 byte |= (isupNumber.NumberingPlan << 4);
1488 byte |= (isupNumber.AddressPresentationRestricted << 2);
1489 byte |= isupNumber.Screening;
1495 std::string dtlc = isupNumber.Digits; // digits to lower case
1496 //std::transform(dtlc.begin(), dtlc.end(), dtlc.begin(), std::tolower);
1497 const char *digits = dtlc.c_str();
1499 for(int k = 1; k < isupNumber.Digits.size(); k += 2) {
1500 if(isxdigit(byte = digits [k - 1]) == 0)
1501 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Digits' field contains invalid digits (non hexadecimal)", ANNA_FILE_LOCATION);
1503 hex = (byte >= '0' && byte <= '9') ? (byte - '0') : ((byte - 'a') + 0x0a);
1505 if(isxdigit(byte = digits [k]) == 0)
1506 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Digits' field contains invalid digits (non hexadecimal)", ANNA_FILE_LOCATION);
1508 hex |= ((byte >= '0' && byte <= '9') ? (byte - '0') : ((byte - 'a') + 0x0a)) << 4;
1512 if(hasDigits && filler) {
1513 if(isxdigit(byte = digits [isupNumber.Digits.size() - 1]) == 0)
1514 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Digits' field contains invalid digits (non hexadecimal)", ANNA_FILE_LOCATION);
1516 target += ((byte >= '0' && byte <= '9') ? (byte - '0') : ((byte - 'a') + 0x0a));
1521 void functions::codeIsupNumber(const isup_number_t & isupNumber, bool calledOrCalling, char * buffer, int & length) throw(anna::RuntimeException) {
1523 codeIsupNumber(isupNumber, calledOrCalling, target);
1524 length = target.size();
1525 memcpy(buffer, target.c_str(), length);
1529 static inline bool is_base64(U8 c) {
1530 return (isalnum(c) || (c == '+') || (c == '/'));
1533 std::string functions::encodeBase64(const U8* buf, unsigned int bufLen) {
1541 char_array_3[i++] = *(buf++);
1543 char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
1544 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
1545 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
1546 char_array_4[3] = char_array_3[2] & 0x3f;
1548 for(i = 0; (i <4) ; i++)
1549 ret += base64_chars[char_array_4[i]];
1556 for(j = i; j < 3; j++)
1557 char_array_3[j] = '\0';
1559 char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
1560 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
1561 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
1562 char_array_4[3] = char_array_3[2] & 0x3f;
1564 for (j = 0; (j < i + 1); j++)
1565 ret += base64_chars[char_array_4[j]];
1574 std::string functions::decodeBase64(const std::string & encodedString) {
1575 int in_len = encodedString.size();
1579 U8 char_array_4[4], char_array_3[3];
1582 while (in_len-- && ( encodedString[in_] != '=') && is_base64(encodedString[in_])) {
1583 char_array_4[i++] = encodedString[in_]; in_++;
1585 for (i = 0; i <4; i++)
1586 char_array_4[i] = base64_chars.find(char_array_4[i]);
1588 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
1589 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
1590 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
1592 for (i = 0; (i < 3); i++)
1593 ret += char_array_3[i];
1599 for (j = i; j <4; j++)
1600 char_array_4[j] = 0;
1602 for (j = 0; j <4; j++)
1603 char_array_4[j] = base64_chars.find(char_array_4[j]);
1605 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
1606 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
1607 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
1609 for (j = 0; (j < i - 1); j++) ret += char_array_3[j];