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>
40 #define PAGE_WIDTH_LENGTH 80
42 static const std::string base64_chars =
43 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
44 "abcdefghijklmnopqrstuvwxyz"
48 string functions::getVersion() throw() {
49 static const int version = ANNA_VERSION;
51 int mainVersion = (version & 0xff00) >> 8;
52 int subVersion = (version & 0xff);
54 sprintf(aux, "%d.%d", mainVersion, subVersion);
56 return result += getArchitecture();
60 (1) Solo coge los dos primeros digitos del numero de release
62 string functions::getArchitecture() throw() {
64 WHEN_MULTITHREAD(result = "/MT");
65 WHEN_SINGLETHREAD(result = "/ST");
79 char* release = anna_strchr(un.release, '.'); // (1)
82 if((release = anna_strchr(release + 1, '.')) != NULL)
92 string functions::asString(const int number)
95 sprintf(aux, "%d", number);
99 string functions::asString(const S64 number)
102 //sprintf(aux, "%lld", number);
104 sprintf (aux, "%ld", number);
106 sprintf (aux, "%lld", number);
111 string functions::asString(const unsigned int number)
114 sprintf(aux, "%u", number);
118 string functions::asString(const U64 number)
121 //sprintf(aux, "%llu", number);
123 sprintf (aux, "%lu", number);
125 sprintf (aux, "%llu", number);
130 string functions::asString(const float number, const char* format)
133 sprintf(aux, format, number);
137 string functions::asString(const double number, const char* format)
140 sprintf(aux, format, number);
144 string functions::asDateTime(const Second &second)
146 char aux [DateTimeSizeString];
147 return std::string(asDateTime(second, aux));
150 const char* functions::asDateTime(const Second &second, char* result)
152 struct tm* tt = localtime((time_t*) & second);
154 result, "%02d/%02d/%4d %02d:%02d:%02d",
155 tt->tm_mday, tt->tm_mon + 1, tt->tm_year + 1900,
156 tt->tm_hour, tt->tm_min, tt->tm_sec
161 std::string functions::asString(const DataBlock& dataBlock, const int characterByLine)
163 return dataBlock.asString(characterByLine);
166 string functions::asHexString(const int number)
169 sprintf(aux, "0x%x", number);
173 string functions::asHexString(const S64 number)
176 //sprintf(aux, "0x%llx", number);
178 sprintf (aux, "0x%lx", number);
180 sprintf (aux, "0x%llx", number);
185 // from a version by Allen Holub (see Andrew Binstock, "Hashing Revisited"
186 // Dr. Dobb's Journal, April 1996)
187 S64 functions::hash(const char* p)
189 static const int long_bits = sizeof(S64) << 3;
190 static const int one_eighth = long_bits >> 3;
191 static const int three_fourths = long_bits * 3 / 4;
192 static const S64 high_bits = ((S64)(~0L)) << (long_bits - one_eighth);
197 result = (result << one_eighth) + *p ++;
199 if((temp = result & high_bits) != 0)
200 result = (result ^(temp >> three_fourths)) &~ high_bits;
207 std::string functions::asHexString(const DataBlock& dataBlock)
209 const char* buffer = dataBlock.getData();
210 const int size = dataBlock.getSize();
214 for(int ii = 0; ii < size; ii ++) {
215 byte = (buffer [ii] & 0xf0) >> 4;
216 result += (byte >= 0 && byte <= 9) ? (byte + '0') : ((byte - 0xa) + 'a');
217 byte = (buffer [ii] & 0x0f);
218 result += (byte >= 0 && byte <= 9) ? (byte + '0') : ((byte - 0xa) + 'a');
225 * Gets the original value obtained with #asHexString (const DataBlock&).
226 * \param hexString String which contains the buffer. The format is an hexadecimal octet sequence representation (i.e. 'af012fb3', with even number of digits).
227 * The input shall be preprocessed to comply with that format (e.g. colon or any other non-hex digit must be removed).
228 * \param target DataBlock for string decode.
229 * \return DataBlock corresponding to the provided string.
232 DataBlock& functions::fromHexString(const std::string& hexString, DataBlock& target)
233 throw(RuntimeException) {
235 if((hexString.length() % 2) != 0)
236 throw RuntimeException("functions::fromHexString | Invalid string length", ANNA_FILE_LOCATION);
239 const char* src = hexString.data();
243 for(int ii = 1, maxii = hexString.length(); ii < maxii; ii += 2) {
244 if(isxdigit(aux = src [ii - 1]) == 0)
245 throw RuntimeException("Invalid HexString", ANNA_FILE_LOCATION);
247 hex = ((aux >= '0' && aux <= '9') ? (aux - '0') : ((aux - 'a') + 0x0a)) << 4;
249 if(isxdigit(aux = src [ii]) == 0)
250 throw RuntimeException("Invalid HexString", ANNA_FILE_LOCATION);
252 hex |= (aux >= '0' && aux <= '9') ? (aux - '0') : ((aux - 'a') + 0x0a);
259 string functions::asString(const char* format, ...)
263 va_start(ap, format);
264 vsnprintf(aux, sizeof(aux), format, ap);
269 void functions::sleep(const Millisecond &millisecond)
273 req.tv_sec = millisecond.getValue() / 1000; // segundos
274 req.tv_nsec = (millisecond.getValue() % 1000); // milisegundos
275 req.tv_nsec *= 1000000; // mili = 10e-3, nano=10-9
278 while((r = nanosleep(&req, &rem)) != 0) {
282 string msg(asText("functions::sleep | timespec { sec: ", (int) req.tv_sec));
283 msg += functions::asText("| nsec: ", (int) req.tv_nsec);
285 RuntimeException ex(msg, errno, ANNA_FILE_LOCATION);
292 bool functions::asBool(const char* str)
293 throw(RuntimeException) {
297 if(strcasecmp(str, "true") == 0 || anna_strcmp(str, "1") == 0)
300 if(strcasecmp(str, "false") == 0 || anna_strcmp(str, "0") == 0)
303 string msg("anna::funcions::asBool | Cannot interpret '");
305 msg += "' as boolean";
306 throw RuntimeException(msg, ANNA_FILE_LOCATION);
309 S64 functions::asInteger64(const char* str)
312 //sscanf(str, "%lld", &number);
314 sscanf (str, "%ld", &number);
316 sscanf (str, "%lld", &number);
321 pthread_t functions::getCurrentThread()
323 WHEN_MULTITHREAD(return pthread_self());
324 WHEN_SINGLETHREAD(return 0);
327 bool functions::isLike(const char* pattern, const std::string& _value)
328 throw(RuntimeException) {
329 const char* value = _value.c_str();
333 if((ret = regcomp(&preg, pattern, REG_EXTENDED)) != 0) {
335 string msg("anna::functions::isLike | ");
336 msg += " | Pattern: ";
342 if(regerror(ret, &preg, err, sizeof(err)))
345 msg += "Invalid pattern";
347 throw RuntimeException(msg, ANNA_FILE_LOCATION);
350 const bool result = (regexec(&preg, value, 0, NULL, 0) == 0) ? true : false;
357 S64 functions::merge(const char* whatis, const int n1, const int n2, const int bitShift)
358 throw(RuntimeException) {
359 if(bitShift > intBitSize) {
360 string msg(functions::asString("%s | N1: 0x%x | N2: 0x%x | bitShift: %d | bitShift must be less than %d", whatis, n1, n2, bitShift, intBitSize));
361 throw RuntimeException(msg, ANNA_FILE_LOCATION);
364 if((bitsize(n1) + bitShift) > int64BitSize) {
365 string msg(functions::asString("%s | N1: 0x%x | N2: 0x%x | bitShift: %d | N1 overload", whatis, n1, n2, bitShift));
366 throw RuntimeException(msg, ANNA_FILE_LOCATION);
369 if(bitsize(n2) > bitShift) {
370 string msg(functions::asString("%s | N1: 0x%x | N2: 0x%x | bitShift: %d | N2 overload", whatis, n1, n2, bitShift));
371 throw RuntimeException(msg, ANNA_FILE_LOCATION);
378 if(bitShift == intBitSize) {
380 string msg(functions::asString("%s | N1: 0x%x | N2: 0x%x | bitShift: %d | ", whatis, n1, n2, bitShift));
381 msg += functions::asHexString(result);
382 Logger::information(msg, ANNA_FILE_LOCATION);
391 * Basado en el algoritmo de http://www-graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup
393 int functions::log2(const unsigned int v)
395 static const signed char LogTable256[] = {
396 -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
397 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
398 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
399 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
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 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
403 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
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,
410 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
411 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
413 int r = -1; // r will be lg(v)
414 unsigned int t, tt; // temporaries
417 r = ((t = tt >> 8)) ? 24 + LogTable256[t] : 16 + LogTable256[tt];
419 r = (t = v >> 8) ? 8 + LogTable256[t] : LogTable256[v];
425 std::string functions::entriesAsString(int number, const char * wordForSingular, const char * wordForPlural) throw() {
427 std::string singular = (wordForSingular ? wordForSingular : "entry");
428 std::string plural = (wordForPlural ? wordForPlural : "entries");
430 if(wordForSingular && !wordForPlural)
431 plural = singular + "s";
433 result += ((number != 0) ? anna::functions::asString(number) : "no");
435 result += ((number != 1) ? plural : singular);
440 std::string functions::justify(const std::string & title, TextJustifyMode::_v mode, char filler) throw() {
442 int d_size = title.size();
443 int repeat = PAGE_WIDTH_LENGTH - d_size - 1;
446 if(mode == TextJustifyMode::Center) {
447 repeat = (repeat - 1) / 2;
448 adjust = (2 * (repeat + 1) + d_size != PAGE_WIDTH_LENGTH);
451 if((mode == TextJustifyMode::Right) || (mode == TextJustifyMode::Center)) {
452 for(int k = 0; k < (repeat + (adjust ? 1 : 0)); k++) result += filler;
459 if((mode == TextJustifyMode::Left) || (mode == TextJustifyMode::Center)) {
462 for(int k = 0; k < repeat; k++) result += filler;
469 std::string functions::highlight(const std::string & title, TextHighlightMode::_v mode, char filler, bool appendCR) throw() {
471 int ou_repeat = title.size();
472 int lr_repeat = PAGE_WIDTH_LENGTH - ou_repeat - 1;
475 if(mode == TextHighlightMode::LeftAndRightline) {
476 lr_repeat = (lr_repeat - 1) / 2;
477 adjust = (2 * (lr_repeat + 1) + ou_repeat != PAGE_WIDTH_LENGTH);
480 if((mode == TextHighlightMode::Leftline) || (mode == TextHighlightMode::LeftAndRightline)) {
481 for(int k = 0; k < (lr_repeat + (adjust ? 1 : 0)); k++) result += filler;
486 if((mode == TextHighlightMode::Overline) || (mode == TextHighlightMode::OverAndUnderline)) {
487 for(int k = 0; k < ou_repeat; k++) result += filler;
494 if((mode == TextHighlightMode::Underline) || (mode == TextHighlightMode::OverAndUnderline)) {
497 for(int k = 0; k < ou_repeat; k++) result += filler;
500 if((mode == TextHighlightMode::Rightline) || (mode == TextHighlightMode::LeftAndRightline)) {
503 for(int k = 0; k < lr_repeat; k++) result += filler;
506 if(appendCR) result += "\n";
512 std::string functions::tab(const std::string & text, int tabSpaces) throw() {
514 size_t pos, from = 0;
515 std::string tab, crTab = "\n";
517 for(int k = 0; k < tabSpaces; k++) tab += " ";
523 while(((pos = result.find('\n', from)) != std::string::npos) && (pos != (result.size() - 1)/*exclude last CR if exists*/)) {
524 result.replace(pos, 1, crTab);
532 bool functions::endsWith(const std::string & pattern, const std::string & suffix, std::string & preffix) throw() {
535 if(pattern.size() < suffix.size()) return false;
537 size_t pos = pattern.rfind(suffix);
539 if(pos == std::string::npos) return false;
541 preffix.assign(pattern.c_str(), pos);
542 return (pos == (pattern.size() - suffix.size()));
546 bool functions::startsWith(const std::string & pattern, const std::string & preffix, std::string & suffix) throw() {
549 if(pattern.size() < preffix.size()) return false;
551 if(pattern.find(preffix) != 0) return false;
553 suffix.assign(pattern.c_str(), preffix.size(), pattern.size() - preffix.size());
558 std::string functions::replace(const std::string & text, const char *item, const char *target, bool all) throw() {
559 std::string result = text;
561 if(!item || !target) return result; // protection for NULL strings provided
563 size_t lengthReplaced = strlen(item);
564 size_t pos = result.find(item);
566 while(pos != std::string::npos) {
567 result.replace(pos, lengthReplaced, target);
571 pos = result.find(item);
578 std::string functions::addQuotationMarks(const std::string & str) throw() {
579 std::string result = "'";
586 std::string functions::addQuotationMarks(const char * str) throw() {
587 std::string result = "'";
588 result += (str ? str : "<null>");
594 std::string functions::addQuotationMarks(const int & integer) throw() {
595 std::string result = "'";
596 result += anna::functions::asString(integer);
602 std::string functions::vectorToStringRepresentation(const std::vector<int> & v, const char separator) throw() {
603 std::string result = "";
606 std::vector<int>::const_iterator iter;
607 std::vector<int>::const_iterator iter_min(v.begin());
608 std::vector<int>::const_iterator iter_max(v.end());
610 for(iter = iter_min; iter != iter_max; iter++) {
611 result += anna::functions::asString(*iter);
615 // Delete the last space: starts at 'size()-1', take 1 caracter:
616 result.erase(result.size() - 1, 1);
623 std::string functions::vectorToStringRepresentation(const std::vector<std::string> & v, const char separator) throw() {
624 std::string result = "";
627 std::vector<std::string>::const_iterator iter;
628 std::vector<std::string>::const_iterator iter_min(v.begin());
629 std::vector<std::string>::const_iterator iter_max(v.end());
631 for(iter = iter_min; iter != iter_max; iter++) {
636 // Delete the last space: starts at 'size()-1', take 1 caracter:
637 result.erase(result.size() - 1, 1);
644 std::string functions::socketLiteralAsString(const std::string & address, int port) throw() {
645 std::string result = address;
647 result += anna::functions::asString(port);
652 std::string functions::asAsciiString(const char * buffer, int size, bool & isFullyPrintable) throw() {
654 // Supposed printable by default:
655 isFullyPrintable = true;
657 if(size == 0 || !buffer) {
659 isFullyPrintable = false;
663 for(int k = 0; k < size; k ++) {
664 unsigned char c = (unsigned char) buffer [k];
665 int printable = isprint(c);
666 result += (printable ? (char) c : '.');
668 if(!printable) isFullyPrintable = false;
675 std::string functions::getHostname() throw() {
677 std::string result = "<hostname>";
679 if(gethostname(aux, sizeof aux) == 0 /*success*/)
685 std::string functions::getDomainname() throw() {
687 std::string result = "<domainname>";
689 if(getdomainname(aux, sizeof aux) == 0 /*success*/)
695 std::string functions::getFQDN(const char *hostname, const char *domainname) throw() {
696 std::string hn = hostname ? hostname : (functions::getHostname());
697 std::string dn = domainname ? domainname : (functions::getDomainname());
698 // FQDN is limited to 255 bytes, with aditional restriction: 63 bytes label within a domain name.
700 if(hn == "") return dn;
702 if(dn == "") return hn;
704 std::string label(hn, 0, 63);
705 std::string fqdn(label + "." + dn, 0, 255);
709 std::string functions::getHostnameIP() throw() {
710 std::string result = "";
712 struct in_addr **addr_list;
714 gethostname(hostname, sizeof hostname);
716 if((he = gethostbyname(hostname)) != NULL) {
717 // Official name: he->h_name
719 addr_list = (struct in_addr **)he->h_addr_list;
721 for(int i = 0; addr_list[i] != NULL; i++) {
722 //printf("%s ", inet_ntoa(*addr_list[i]));
723 result = inet_ntoa(*addr_list[i]);
732 anna::DataBlock functions::rawIpPresentationAsRaw(const std::string & rawPresentation) throw(anna::RuntimeException) {
733 int length = rawPresentation.size();
735 if(length != 8 && length != 32)
736 throw anna::RuntimeException("functions::rawIpPresentationAsRaw | Expected 8 or 32-sized raw IP presentation provided", ANNA_FILE_LOCATION);
738 anna::DataBlock result(true);
740 char rByte[3]; // readable byte
743 for(int k = 0; k < length; k += 2) {
744 rByte[0] = rawPresentation[k];
745 rByte[1] = rawPresentation[k + 1];
746 sscanf(rByte, "%x", &byte);
754 std::string functions::rawIpAsRawIpPresentation(const anna::DataBlock & db) throw(anna::RuntimeException) {
755 int length = db.getSize();
757 if(length != 4 && length != 16)
758 throw anna::RuntimeException("functions::rawIpAsRawIpPresentation | Expected 4 or 16-sized raw IP DataBlock provided", ANNA_FILE_LOCATION);
760 std::string result = "";
762 char rByte[3]; // readable byte
765 for(int k = 0; k < length; k++) {
766 byte = (unsigned char)db[k];
767 sprintf(rByte, "%.2X", byte);
779 // 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:
780 // A typical example of an IPv6 address is
781 // 2001:0db8:85a3:0000:0000:8a2e:0370:7334
782 // The hexadecimal digits are case-insensitive.
784 // The 128-bit IPv6 address can be abbreviated with the following rules:
785 // -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
786 // -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
787 // 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.
789 // 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.
790 // AsÃ, las siguientes son representaciones posibles de una misma dirección:
792 // 2001:0DB8:0000:0000:0000:0000:1428:57ab
793 // 2001:0DB8:0000:0000:0000::1428:57ab
794 // 2001:0DB8:0:0:0:0:1428:57ab
795 // 2001:0DB8:0::0:1428:57ab
796 // 2001:0DB8::1428:57ab
797 // son todas válidas y significan lo mismo, pero
800 // no es válida porque no queda claro cuántos grupos nulos hay en cada lado.
802 // Los ceros iniciales en un grupo también se pueden omitir:
803 // 2001:0DB8:02de::0e13
806 // Si la dirección es una dirección IPv4 empotrada (mapped), los últimos 32 bits pueden escribirse en base decimal, asÃ:
807 // ::ffff:192.168.89.9
810 // No se debe confundir con:
814 // El formato ::ffff:1.2.3.4 se denomina dirección IPv4 mapeada, y el formato ::1.2.3.4 dirección IPv4 compatible.
815 // Las direcciones IPv4 pueden ser transformadas fácilmente al formato IPv6. Por ejemplo, si la dirección decimal IPv4 es 135.75.43.52
816 // (en hexadecimal, 0x874B2B34), puede ser convertida a 0000:0000:0000:0000:0000:0000:874B:2B34 o ::874B:2B34. Entonces, uno puede usar
817 // 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
818 // casi no está siendo utilizada en la práctica, aunque los estándares no la han declarado obsoleta.
820 // http://tools.ietf.org/html/rfc5952: canonical text representation recommendation
822 bool functions::isIPv4(const std::string & ip, IPv4Type::_v ipv4Type) throw() {
823 if(ipv4Type == IPv4Type::Estrict) {
824 // La expresión regular no controla si hay mas de 3 puntos:
827 for(int k = 0; k < ip.length(); k++)
828 if(ip[k] == '.') n_dot++;
833 bool ipv4 = anna::functions::isLike(s_REGEXP_IPv4_ADDRESSES, ip);
834 bool colon = (ip.find(":") != std::string::npos);
835 return (ipv4 && !colon);
838 if(ipv4Type == IPv4Type::Compatible) {
839 std::string pureIPv4 = ip;
840 bool firstDoubleColon = (ip.find("::") == 0);
842 if(firstDoubleColon) {
843 pureIPv4.erase(0, 2);
844 bool anotherColon = (pureIPv4.find(":") != std::string::npos);
846 if(anotherColon) return (false);
848 return (anna::functions::isLike(s_REGEXP_IPv4_ADDRESSES, pureIPv4));
852 if(ipv4Type == IPv4Type::Mapped) {
853 size_t posLastColon = ip.rfind(":");
855 if(posLastColon == std::string::npos)
858 if(!isIPv4(ip.substr(posLastColon + 1)))
861 unsigned char buf[sizeof(struct in6_addr)];
862 int s = inet_pton(AF_INET6, ip.c_str(), buf);
872 bool functions::isIPv6(const std::string & ip) throw() {
873 // Chequeo de digitos permitidos:
874 for(int k = 0; k < ip.length(); k++) {
875 bool digit = isdigit(ip[k]);
876 bool hex = ((ip[k] == 'a') ||
888 bool colon = (ip[k] == ':');
890 if(!digit && !hex && !colon)
894 return (anna::functions::isLike(s_REGEXP_IPv6_ADDRESSES, ip));
898 std::string functions::IPv4To6(const std::string & ip) throw(anna::RuntimeException) {
899 if(!isIPv4(ip, IPv4Type::Estrict) && !isIPv4(ip, IPv4Type::Compatible) && !isIPv4(ip, IPv4Type::Mapped))
900 throw anna::RuntimeException("functions::IPv4To6 | Expected IPv4, IPv4-compatible or IPv4-mapped address format", ANNA_FILE_LOCATION);
902 std::string result, pureIPv4;
903 bool firstDoubleColon = (ip.find("::") == 0);
905 if(firstDoubleColon) {
907 size_t ipv4_pos = ip.rfind(":") /* last ocurrence */ + 1;
908 pureIPv4 = ip.substr(ipv4_pos);
911 size_t posColon = ip.find(":");
913 if(posColon == 0) // first colon
914 throw anna::RuntimeException("functions::IPv4To6 | Invalid IPv4 address format", ANNA_FILE_LOCATION);
916 if(posColon != std::string::npos) // any colon
917 return ip; // seems to be IPv6 already?
919 throw anna::RuntimeException("functions::IPv4To6 | Unreconized IPv4 address format", ANNA_FILE_LOCATION);
925 // Number of ocurrences for '.'
928 for(int k = 0; k < pureIPv4.length(); k++)
929 if(pureIPv4[k] == '.') n_dot++;
932 throw anna::RuntimeException("functions::IPv4To6 | Wrong IPv4 address format (more than three dots!)", ANNA_FILE_LOCATION);
935 anna::Tokenizer::const_iterator tok_it;
937 tok.apply(pureIPv4, ".");
941 for(tok_it = tok.begin(); tok_it != tok.end(); tok_it ++) {
942 token = anna::Tokenizer::data(tok_it);
943 v[cnt] = atoi(anna::Tokenizer::data(tok_it));
945 if(v[cnt] < 0 || v[cnt] > 255)
946 throw anna::RuntimeException("functions::IPv4To6 | Wrong IPv4 address format (any value out of range 0-255)", ANNA_FILE_LOCATION);
951 if(isIPv4(ip, IPv4Type::Compatible))
952 result = anna::functions::asString("::%04x:%04x", v[0] * 256 + v[1], v[2] * 256 + v[3]);
954 result = anna::functions::asString("::ffff:%04x:%04x", v[0] * 256 + v[1], v[2] * 256 + v[3]);
960 std::string functions::normalizeIP(const std::string & ip) throw(anna::RuntimeException) {
961 std::string result = ip;
962 // std::transform(result.begin(), result.end(), result.begin(), (int (*)(int))std::tolower);
963 std::transform(result.begin(), result.end(), result.begin(), ::tolower);
965 if(isIPv4(ip, IPv4Type::Estrict) || isIPv4(ip, IPv4Type::Compatible) || isIPv4(ip, IPv4Type::Mapped))
966 result = IPv4To6(result);
968 size_t pos = result.find("::"); // zeroes simplification group
969 size_t rpos = result.rfind("::"); // zeroes simplification group
972 throw anna::RuntimeException("functions::normalizeIP | Wrong IPv6 address format (more than one simplification group '::')", ANNA_FILE_LOCATION);
974 if(pos != std::string::npos) { // zeroes exists
975 // string ( size_t n, char c ) -> content is initialized as a string formed by a repetition of character c, n times.
976 // Number of ocurrences for ':'
979 for(int k = 0; k < result.length(); k++)
980 if(result[k] == ':') n_colon++;
982 // Generate equivalent to '::'
983 std::string equiv_str;
985 for(int k = 0; k < (8 - n_colon); k++)
989 // Replace with equivalent:
990 result.replace(pos, 2, equiv_str);
992 // Special case: IP began with '::'
993 if(result[0] == ':') {
994 result.insert(0, "0");
997 // Special case: IP was only '::'
998 if(result[result.length() - 1] == ':') {
1003 // Protection: it must be seven colons:
1006 for(int k = 0; k < result.length(); k++)
1007 if(result[k] == ':') n_colon++;
1010 throw anna::RuntimeException("functions::normalizeIP | Wrong IPv6 address format (missing any 16-bit group)", ANNA_FILE_LOCATION);
1012 // Padding with zeroes at left
1013 anna::Tokenizer ipStr;
1014 anna::Tokenizer::const_iterator ipStr_it;
1016 ipStr.apply(result, ":");
1019 for(ipStr_it = ipStr.begin(); ipStr_it != ipStr.end(); ipStr_it ++) {
1020 token = anna::Tokenizer::data(ipStr_it);
1022 while(token.length() < 4) token.insert(0, "0");
1029 size_t lastPos = result.length() - 1;
1030 result.erase(lastPos, 1);
1032 // Chequeo de digitos permitidos:
1033 for(int k = 0; k < result.length(); k++) {
1034 bool digit = isdigit(result[k]);
1035 bool hex = ((result[k] == 'a') ||
1036 (result[k] == 'b') ||
1037 (result[k] == 'c') ||
1038 (result[k] == 'd') ||
1039 (result[k] == 'e') ||
1040 (result[k] == 'f'));
1041 bool colon = (result[k] == ':');
1043 if(!digit && !hex && !colon) {
1044 throw anna::RuntimeException("functions::normalizeIP | Invalid address format (only digits (0-9) and hex digits are allowed)", ANNA_FILE_LOCATION);
1052 bool functions::sameIP(const std::string & ip1, const std::string & ip2) throw(anna::RuntimeException) {
1053 //if (ip1 == ip2) return true; it should validate wrong-format addresses
1054 return (normalizeIP(ip1) == normalizeIP(ip2));
1058 bool functions::matchIPv6(const std::string & _ipv6, const std::string & preffixedIpv6) throw(anna::RuntimeException) {
1059 size_t preffixPos = preffixedIpv6.find("/");
1061 if(preffixPos == std::string::npos)
1062 return (sameIP(_ipv6, preffixedIpv6));
1064 std::string ipv6 = _ipv6;
1066 if(isIPv4(_ipv6, IPv4Type::Estrict) || isIPv4(_ipv6, IPv4Type::Compatible) || isIPv4(_ipv6, IPv4Type::Mapped)) ipv6 = IPv4To6(_ipv6);
1068 std::string _ipv6_2 = preffixedIpv6.substr(0, preffixPos);
1069 std::string ipv6_2 = _ipv6_2;
1071 if(isIPv4(_ipv6_2, IPv4Type::Estrict) || isIPv4(_ipv6_2, IPv4Type::Compatible) || isIPv4(_ipv6_2, IPv4Type::Mapped)) ipv6_2 = IPv4To6(_ipv6_2);
1073 std::string preffix = preffixedIpv6.substr(preffixPos + 1);
1074 int ipv6_2_preffixLength = atoi(preffix.c_str());
1076 if(ipv6_2_preffixLength < 0 || ipv6_2_preffixLength > 128)
1077 throw anna::RuntimeException("functions::matchIPv6 | Invalid Ipv6 preffix length: out of range [0,128]", ANNA_FILE_LOCATION);
1079 // No restriction, all ipv6_2 ignored (special and not usual case)
1080 if(ipv6_2_preffixLength == 0) return true;
1083 int spare = ipv6_2_preffixLength /* bits */ % 8; // bytes
1084 int incompletedRestrictionBytes = ipv6_2_preffixLength / 8;
1085 int completedRestrictionBytes = incompletedRestrictionBytes + ((spare != 0) ? 1 : 0);
1086 char mask = 0xFF << (8 - spare);
1088 anna::DataBlock rawIP1 = ipAsRaw(ipv6);
1089 anna::DataBlock restrictedIP1(true);
1090 restrictedIP1.assign(rawIP1.getData(), incompletedRestrictionBytes);
1092 if(spare != 0) restrictedIP1 += rawIP1[incompletedRestrictionBytes] & mask;
1095 anna::DataBlock rawIP2 = ipAsRaw(ipv6_2);
1096 anna::DataBlock realIP2(true);
1097 realIP2.assign(rawIP2.getData(), incompletedRestrictionBytes);
1099 if(spare != 0) realIP2 += rawIP2[incompletedRestrictionBytes] & mask;
1102 int n = memcmp(restrictedIP1.getData(), realIP2.getData(), completedRestrictionBytes);
1107 anna::DataBlock functions::ipAsRaw(const std::string & ip) throw(anna::RuntimeException) {
1108 anna::DataBlock result(true);
1111 unsigned char buf[sizeof(struct in6_addr)];
1112 int s = inet_pton(AF_INET, ip.c_str(), buf);
1115 result += (S8)buf[0];
1116 result += (S8)buf[1];
1117 result += (S8)buf[2];
1118 result += (S8)buf[3];
1120 if(s < 0) perror("inet_pton");
1122 throw anna::RuntimeException("functions::ipAsRaw | Wrong IPv4 address format", ANNA_FILE_LOCATION);
1125 unsigned char buf[sizeof(struct in6_addr)];
1126 int s = inet_pton(AF_INET6, ip.c_str(), buf);
1129 result += (S8)buf[0];
1130 result += (S8)buf[1];
1131 result += (S8)buf[2];
1132 result += (S8)buf[3];
1133 result += (S8)buf[4];
1134 result += (S8)buf[5];
1135 result += (S8)buf[6];
1136 result += (S8)buf[7];
1137 result += (S8)buf[8];
1138 result += (S8)buf[9];
1139 result += (S8)buf[10];
1140 result += (S8)buf[11];
1141 result += (S8)buf[12];
1142 result += (S8)buf[13];
1143 result += (S8)buf[14];
1144 result += (S8)buf[15];
1146 if(s < 0) perror("inet_pton");
1148 throw anna::RuntimeException("functions::ipAsRaw | Wrong IPv6 address format", ANNA_FILE_LOCATION);
1154 // anna::DataBlock result(true);
1157 // if (isIPv4(ip)) {
1159 // 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/)
1160 // sscanf(ip.c_str(), "%d.%d.%d.%d", &dec1, &dec2, &dec3, &dec4);
1161 // result += (S8)dec1;
1162 // result += (S8)dec2;
1163 // result += (S8)dec3;
1164 // result += (S8)dec4;
1168 // 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/)
1169 // sscanf(normalizeIP(ip).c_str(), "%X:%X:%X:%X:%X:%X:%X:%X", &hex1, &hex2, &hex3, &hex4, &hex5, &hex6, &hex7, &hex8);
1170 // result += ((S8)(hex1 >> 8));
1171 // result += ((S8)(hex1 & 0x00FF));
1172 // result += ((S8)(hex2 >> 8));
1173 // result += ((S8)(hex2 & 0x00FF));
1174 // result += ((S8)(hex3 >> 8));
1175 // result += ((S8)(hex3 & 0x00FF));
1176 // result += ((S8)(hex4 >> 8));
1177 // result += ((S8)(hex4 & 0x00FF));
1178 // result += ((S8)(hex5 >> 8));
1179 // result += ((S8)(hex5 & 0x00FF));
1180 // result += ((S8)(hex6 >> 8));
1181 // result += ((S8)(hex6 & 0x00FF));
1182 // result += ((S8)(hex7 >> 8));
1183 // result += ((S8)(hex7 & 0x00FF));
1184 // result += ((S8)(hex8 >> 8));
1185 // result += ((S8)(hex8 & 0x00FF));
1193 std::string functions::rawIpAsString(const char *buffer, int bufferLength, bool normalize) throw(anna::RuntimeException) {
1194 std::string result = "";
1195 char str[INET6_ADDRSTRLEN];
1197 if(bufferLength == 4) {
1198 if(inet_ntop(AF_INET, buffer, str, INET_ADDRSTRLEN) != NULL)
1200 } else if(bufferLength == 16) {
1201 if(inet_ntop(AF_INET6, buffer, str, INET6_ADDRSTRLEN) != NULL)
1204 throw anna::RuntimeException("functions::rawIpAsString | Unreconized IP address format (only 4-byte for IPv4, and 16-byte for IPv6 are allowed)", ANNA_FILE_LOCATION);
1207 throw anna::RuntimeException("functions::rawIpAsString | Wrong IP address serialization (check range value)", ANNA_FILE_LOCATION);
1209 return (normalize ? normalizeIP(result) : result);
1211 // std::string result;
1214 // if (bufferLength == 4) { // IPv4
1215 // result = anna::functions::asString("%d.%d.%d.%d", (U8)buffer[0], (U8)buffer[1], (U8)buffer[2], (U8)buffer[3]);
1217 // else if (bufferLength == 16) { // IPv6
1218 // result = anna::functions::asString("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
1219 // ((((U8)buffer[0]) << 8) & 0xFF00 /* same as (U16 cast)*/) +
1220 // (((U8)buffer[1]) & 0x00FF),
1221 // ((((U8)buffer[2]) << 8) & 0xFF00) +
1222 // (((U8)buffer[3]) & 0x00FF),
1223 // ((((U8)buffer[4]) << 8) & 0xFF00) +
1224 // (((U8)buffer[5]) & 0x00FF),
1225 // ((((U8)buffer[6]) << 8) & 0xFF00) +
1226 // (((U8)buffer[7]) & 0x00FF),
1227 // ((((U8)buffer[8]) << 8) & 0xFF00) +
1228 // (((U8)buffer[9]) & 0x00FF),
1229 // ((((U8)buffer[10]) << 8) & 0xFF00) +
1230 // (((U8)buffer[11]) & 0x00FF),
1231 // ((((U8)buffer[12]) << 8) & 0xFF00) +
1232 // (((U8)buffer[13]) & 0x00FF),
1233 // ((((U8)buffer[14]) << 8) & 0xFF00) +
1234 // (((U8)buffer[15]) & 0x00FF));
1237 // throw anna::RuntimeException("functions::rawIpAsString | Unreconized IP address format (only 4-byte for IPv4, and 16-byte for IPv6 are allowed)", ANNA_FILE_LOCATION);
1240 // return (normalize ? normalizeIP(result):result);
1244 void functions::getAddressAndPortFromSocketLiteral(const std::string &literal, std::string &address, int &port) throw() {
1245 size_t pos = literal.find_last_of(":");
1246 size_t lastPos = literal.size() - 1;
1247 address = ""; port = -1; // assume error
1249 if((pos != std::string::npos) && (pos != lastPos)) {
1250 address = literal.substr(0, pos);
1251 port = atoi(literal.substr(pos + 1, lastPos).c_str());
1256 socket_v functions::getSocketVectorFromString(const std::string & list) throw() {
1258 std::string address;
1260 anna::Tokenizer lst;
1261 lst.apply(list, ",");
1263 if(lst.size() < 1) return result;
1265 anna::Tokenizer::const_iterator tok_min(lst.begin());
1266 anna::Tokenizer::const_iterator tok_max(lst.end());
1267 anna::Tokenizer::const_iterator tok_iter;
1269 for(tok_iter = tok_min; tok_iter != tok_max; tok_iter++) {
1270 getAddressAndPortFromSocketLiteral(anna::Tokenizer::data(tok_iter), address, port);
1272 if(port == -1) { result.clear(); return result; }
1274 result.push_back(socket_t(address, port));
1280 std::string functions::socketVectorAsString(const socket_v & socketVector) throw() {
1283 socket_v_it it_min(socketVector.begin());
1284 socket_v_it it_max(socketVector.end());
1286 for(it = it_min; it != it_max; it++) {
1287 result += anna::functions::asString("%s:%d,", (*it).first.c_str(), (*it).second);
1290 result.erase(result.size() - 1, 1); // remove last comma
1294 bool functions::littleEndian()
1297 char *p = (char *) &i;
1298 if (p[0] == 1) return true;
1302 const char* functions::codeInteger(char* result, const int n)
1305 char* w((char*) &aux);
1307 *(result + 1) = *(w + 1);
1308 *(result + 2) = *(w + 2);
1309 *(result + 3) = *(w + 3);
1313 const char* functions::codeShort(char* result, const short int n)
1315 short int aux(htons(n));
1316 char* w((char*) &aux);
1318 *(result + 1) = *(w + 1);
1322 const char* functions::codeInteger64(char* result, const S64 n)
1324 S64 aux(0xffffffff);
1328 n2 = (aux >> 32) & 0xffffffff;
1329 codeInteger(result, n2);
1330 n2 = n & 0xffffffff;
1331 codeInteger(result + sizeof(int), n2);
1336 const char* functions::codeFloat(char* result, const float n)
1339 anna_memcpy(&ii, &n, sizeof(n));
1340 return functions::codeInteger(result, ii);
1344 const char* functions::codeDouble(char* result, const double n)
1347 anna_memcpy(&ii, &n, sizeof(n));
1348 return functions::codeInteger64(result, ii);
1351 int functions::decodeInteger(const char* data)
1354 char* w((char*) &result);
1356 *(w + 1) = *(data + 1);
1357 *(w + 2) = *(data + 2);
1358 *(w + 3) = *(data + 3);
1359 return ntohl(result);
1362 short int functions::decodeShort(const char* data)
1365 char* w((char*) &result);
1367 *(w + 1) = *(data + 1);
1368 return ntohs(result);
1371 S64 functions::decodeInteger64(const char* data)
1373 S64 result(decodeInteger(data));
1375 return result |= (decodeInteger(data + sizeof(int)) & 0xffffffff);
1379 float functions::decodeFloat(const char* data)
1382 int ii = functions::decodeInteger(data);
1383 anna_memcpy(&result, &ii, sizeof(result));
1388 double functions::decodeDouble(const char* data)
1391 S64 ii = functions::decodeInteger64(data);
1392 anna_memcpy(&result, &ii, sizeof(result));
1398 void functions::decodeIsupNumber(const char *buffer, int length, isup_number_t & isupNumber, bool calledOrCalling) throw(anna::RuntimeException) {
1399 #define DECODE2BYTES_INDX_VALUETYPE(buffer,indx,value_type) ((((value_type)buffer[indx] << 8) & 0xFF00) + ((value_type)buffer[indx+1] & 0x00FF))
1401 isupNumber.OddEven = (short)((buffer[0] >> 7) & 0x01);
1402 bool filler = isupNumber.OddEven;
1404 if(filler && ((buffer [length - 1] & 0xf0) != 0x00))
1405 throw anna::RuntimeException("functions::decodeIsupNumber | Isup number filler must be '0000'", ANNA_FILE_LOCATION);
1407 isupNumber.NatureOfAddress = (short)(buffer[0] & 0x7F);
1408 isupNumber.NumberingPlan = (short)((buffer[1] >> 4) & 0x07);
1410 if(calledOrCalling) {
1411 isupNumber.InternalNetworkNumber = (short)((buffer[1] >> 7) & 0x01);
1413 isupNumber.NumberIncomplete = (short)((buffer[1] >> 7) & 0x01);
1414 isupNumber.AddressPresentationRestricted = (short)((buffer[1] >> 2) & 0x03);
1415 isupNumber.Screening = (short)(buffer[1] & 0x03);
1419 isupNumber.Digits = "";
1422 for(int k = 2; k < length; k ++) {
1423 byte = (buffer [k] & 0x0f);
1424 isupNumber.Digits += (byte >= 0 && byte <= 9) ? (byte + '0') : ((byte - 0xa) + 'a');
1425 byte = (buffer [k] & 0xf0) >> 4;
1426 isupNumber.Digits += (byte >= 0 && byte <= 9) ? (byte + '0') : ((byte - 0xa) + 'a');
1429 if(filler) isupNumber.Digits.erase(isupNumber.Digits.size() - 1, 1); // remove filler
1433 void functions::codeIsupNumber(const isup_number_t & isupNumber, bool calledOrCalling, std::string & target) throw(anna::RuntimeException) {
1435 if(isupNumber.OddEven < 0 || isupNumber.OddEven > 1)
1436 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'OddEven' field out of range [0,1]", ANNA_FILE_LOCATION);
1438 bool odd = isupNumber.OddEven;
1439 bool oddDigits = (isupNumber.Digits.size() % 2);
1441 if(odd != oddDigits)
1442 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'OddEven' field doesn't correspond to the number of digits on 'Digits' field", ANNA_FILE_LOCATION);
1444 if(isupNumber.NatureOfAddress < 0 || isupNumber.NatureOfAddress > 127)
1445 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'NatureOfAddress' field out of range [0,127]", ANNA_FILE_LOCATION);
1447 if(isupNumber.NumberingPlan < 0 || isupNumber.NumberingPlan > 7)
1448 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'NumberingPlan' field out of range [0,7]", ANNA_FILE_LOCATION);
1450 if(calledOrCalling) {
1451 if(isupNumber.NumberIncomplete != 0)
1452 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'NumberIncomplete' field present on Called Party Number !", ANNA_FILE_LOCATION);
1454 if(isupNumber.AddressPresentationRestricted != 0)
1455 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'AddressPresentationRestricted' field present on Called Party Number !", ANNA_FILE_LOCATION);
1457 if(isupNumber.Screening != 0)
1458 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Screening' field present on Called Party Number !", ANNA_FILE_LOCATION);
1460 if(isupNumber.InternalNetworkNumber < 0 || isupNumber.InternalNetworkNumber > 1)
1461 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'InternalNetworkNumber' field out of range [0,1]", ANNA_FILE_LOCATION);
1463 if(isupNumber.InternalNetworkNumber != 0)
1464 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'InternalNetworkNumber' field present on Calling Party Number !", ANNA_FILE_LOCATION);
1466 if(isupNumber.NumberIncomplete < 0 || isupNumber.NumberIncomplete > 1)
1467 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'NumberIncomplete' field out of range [0,1]", ANNA_FILE_LOCATION);
1469 if(isupNumber.AddressPresentationRestricted < 0 || isupNumber.AddressPresentationRestricted > 3)
1470 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'AddressPresentationRestricted' field out of range [0,3]", ANNA_FILE_LOCATION);
1472 if(isupNumber.Screening < 0 || isupNumber.Screening > 3)
1473 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Screening' field out of range [0,3]", ANNA_FILE_LOCATION);
1478 bool filler = isupNumber.OddEven;
1479 bool hasDigits = (isupNumber.Digits.size() > 0);
1480 byte = filler ? 0x80 : 0x00;
1481 byte |= isupNumber.NatureOfAddress;
1484 if(calledOrCalling) {
1485 byte = isupNumber.InternalNetworkNumber << 7;
1486 byte |= (isupNumber.NumberingPlan << 4);
1488 byte = isupNumber.NumberIncomplete << 7;
1489 byte |= (isupNumber.NumberingPlan << 4);
1490 byte |= (isupNumber.AddressPresentationRestricted << 2);
1491 byte |= isupNumber.Screening;
1497 std::string dtlc = isupNumber.Digits; // digits to lower case
1498 //std::transform(dtlc.begin(), dtlc.end(), dtlc.begin(), std::tolower);
1499 const char *digits = dtlc.c_str();
1501 for(int k = 1; k < isupNumber.Digits.size(); k += 2) {
1502 if(isxdigit(byte = digits [k - 1]) == 0)
1503 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Digits' field contains invalid digits (non hexadecimal)", ANNA_FILE_LOCATION);
1505 hex = (byte >= '0' && byte <= '9') ? (byte - '0') : ((byte - 'a') + 0x0a);
1507 if(isxdigit(byte = digits [k]) == 0)
1508 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Digits' field contains invalid digits (non hexadecimal)", ANNA_FILE_LOCATION);
1510 hex |= ((byte >= '0' && byte <= '9') ? (byte - '0') : ((byte - 'a') + 0x0a)) << 4;
1514 if(hasDigits && filler) {
1515 if(isxdigit(byte = digits [isupNumber.Digits.size() - 1]) == 0)
1516 throw anna::RuntimeException("functions::codeIsupNumber | Isup number 'Digits' field contains invalid digits (non hexadecimal)", ANNA_FILE_LOCATION);
1518 target += ((byte >= '0' && byte <= '9') ? (byte - '0') : ((byte - 'a') + 0x0a));
1523 void functions::codeIsupNumber(const isup_number_t & isupNumber, bool calledOrCalling, char * buffer, int & length) throw(anna::RuntimeException) {
1525 codeIsupNumber(isupNumber, calledOrCalling, target);
1526 length = target.size();
1527 memcpy(buffer, target.c_str(), length);
1531 static inline bool is_base64(U8 c) {
1532 return (isalnum(c) || (c == '+') || (c == '/'));
1535 std::string functions::encodeBase64(const U8* buf, unsigned int bufLen) {
1543 char_array_3[i++] = *(buf++);
1545 char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
1546 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
1547 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
1548 char_array_4[3] = char_array_3[2] & 0x3f;
1550 for(i = 0; (i <4) ; i++)
1551 ret += base64_chars[char_array_4[i]];
1558 for(j = i; j < 3; j++)
1559 char_array_3[j] = '\0';
1561 char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
1562 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
1563 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
1564 char_array_4[3] = char_array_3[2] & 0x3f;
1566 for (j = 0; (j < i + 1); j++)
1567 ret += base64_chars[char_array_4[j]];
1576 std::string functions::decodeBase64(const std::string & encodedString) {
1577 int in_len = encodedString.size();
1581 U8 char_array_4[4], char_array_3[3];
1584 while (in_len-- && ( encodedString[in_] != '=') && is_base64(encodedString[in_])) {
1585 char_array_4[i++] = encodedString[in_]; in_++;
1587 for (i = 0; i <4; i++)
1588 char_array_4[i] = base64_chars.find(char_array_4[i]);
1590 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
1591 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
1592 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
1594 for (i = 0; (i < 3); i++)
1595 ret += char_array_3[i];
1601 for (j = i; j <4; j++)
1602 char_array_4[j] = 0;
1604 for (j = 0; j <4; j++)
1605 char_array_4[j] = base64_chars.find(char_array_4[j]);
1607 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
1608 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
1609 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
1611 for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
1617 bool functions::getContentFromFile(const std::string &pathfile, std::string &content) throw(anna::RuntimeException) {
1619 std::ifstream inFile(pathfile.c_str(), std::ifstream::in);
1620 if(!inFile.good()) {
1621 throw RuntimeException(anna::functions::asString("Unable to open file '%s'", pathfile.c_str()), ANNA_FILE_LOCATION);
1624 std::stringstream strStream;
1625 strStream << inFile.rdbuf(); //read the file
1626 content = strStream.str(); // holds the content of the file