2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
22 * (c) Copyright 2007-2008 by Intra2net AG
30 #include <cmath> // for round()
37 #include <boost/numeric/conversion/cast.hpp>
39 #include <stringfunc.hxx>
50 const std::string hexDigitsLower("0123456789abcdef");
51 const std::string hexDigitsUpper("0123456789ABCDEF");
56 char operator() (char c)
58 return std::toupper(c);
60 }; // eo struct UpperFunc
65 char operator() (char c)
67 return std::tolower(c);
69 }; // eo struct LowerFunc
72 } // eo namespace <anonymous>
77 * default list of Whitespaces (" \t\r\n");
79 const std::string Whitespaces = " \t\r\n";
82 * default list of lineendings ("\r\n");
84 const std::string LineEndings= "\r\n";
89 * @brief checks if a string begins with a given prefix.
90 * @param[in,out] str the string which is tested
91 * @param prefix the prefix which should be tested for.
92 * @return @a true iff the prefix is not empty and the string begins with that prefix.
94 bool has_prefix(const std::string& str, const std::string& prefix)
96 if (prefix.empty() || str.empty() || str.size() < prefix.size() )
100 return str.compare(0, prefix.size(), prefix) == 0;
101 } // eo has_prefix(const std::string&,const std::string&)
105 * @brief checks if a string ends with a given suffix.
106 * @param[in,out] str the string which is tested
107 * @param suffix the suffix which should be tested for.
108 * @return @a true iff the suffix is not empty and the string ends with that suffix.
110 bool has_suffix(const std::string& str, const std::string& suffix)
112 if (suffix.empty() || str.empty() || str.size() < suffix.size() )
116 return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
117 } // eo has_suffix(const std::string&,const std::string&)
121 * cut off characters from a given list from front and end of a string.
122 * @param[in,out] str the string which should be trimmed.
123 * @param charlist the list of characters to remove from beginning and end of string
124 * @return the result string.
126 std::string trim_mod(std::string& str, const std::string& charlist)
128 // first: trim the beginning:
129 std::string::size_type pos= str.find_first_not_of (charlist);
130 if (pos == std::string::npos)
132 // whole string consists of charlist (or is already empty)
138 // str starts with charlist
141 // now let's look at the tail:
142 pos= str.find_last_not_of(charlist) +1; // note: we already know there is at least one other char!
143 if ( pos < str.size() )
145 str.erase(pos, str.size()-pos);
148 } // eo trim_mod(std::string&,const std::string&)
153 * removes last character from a string when it is in a list of chars to be removed.
154 * @param[in,out] str the string.
155 * @param what the list of chars which will be tested for.
156 * @return the resulting string with last char removed (if applicable)
158 std::string chomp_mod(std::string& str, const std::string& what)
160 if (str.empty() || what.empty() )
164 if (what.find(str.at (str.size()-1) ) != std::string::npos)
166 str.erase(str.size() - 1);
169 } // eo chomp_mod(std::string&,const std::string&)
173 * @brief converts a string to lower case.
174 * @param[in,out] str the string to modify.
177 std::string to_lower_mod(std::string& str)
179 std::transform(str.begin(), str.end(), str.begin(), LowerFunc() );
181 } // eo to_lower_mod(std::string&)
185 * @brief converts a string to upper case.
186 * @param[in,out] str the string to modify.
189 std::string to_upper_mod(std::string& str)
191 std::transform( str.begin(), str.end(), str.begin(), UpperFunc() );
193 } // eo to_upper_mod(std::string&)
198 * cut off characters from a given list from front and end of a string.
199 * @param str the string which should be trimmed.
200 * @param charlist the list of characters to remove from beginning and end of string
201 * @return the result string.
203 std::string trim (const std::string& str, const std::string& charlist)
205 // first: trim the beginning:
206 std::string::size_type pos0= str.find_first_not_of(charlist);
207 if (pos0 == std::string::npos)
209 // whole string consists of charlist (or is already empty)
210 return std::string();
212 // now let's look at the end:
213 std::string::size_type pos1= str.find_last_not_of(charlist);
214 return str.substr(pos0, pos1 - pos0 + 1);
215 } // eo trim(const std:.string&,const std::string&)
219 * removes last character from a string when it is in a list of chars to be removed.
220 * @param str the string.
221 * @param what the list of chars which will be tested for.
222 * @return the resulting string with last char removed (if applicable)
224 std::string chomp (const std::string& str, const std::string& what)
226 if (str.empty() || what.empty() )
230 if (what.find(str.at (str.size()-1) ) != std::string::npos)
232 return str.substr(0, str.size()-1);
235 } // eo chomp(const std:.string&,const std::string&)
239 * @brief returns a lower case version of a given string.
240 * @param str the string
241 * @return the lower case version of the string
243 std::string to_lower (const std::string& str)
245 std::string result(str);
246 return to_lower_mod(result);
247 } // eo to_lower(const std::string&)
251 * @brief returns a upper case version of a given string.
252 * @param str the string
253 * @return the upper case version of the string
255 std::string to_upper(const std::string& str)
257 std::string result(str);
258 return to_upper_mod(result);
259 } // eo to_upper(const std::string&)
264 * @brief removes a given suffix from a string.
265 * @param str the string.
266 * @param suffix the suffix which should be removed if the string ends with it.
267 * @return the string without the suffix.
269 * If the string ends with the suffix, it is removed. If the the string doesn't end
270 * with the suffix the original string is returned.
272 std::string remove_suffix(const std::string& str, const std::string& suffix)
274 if (has_suffix(str,suffix) )
276 return str.substr(0, str.size()-suffix.size() );
279 } // eo remove_suffix(const std::string&,const std::string&)
284 * @brief removes a given prefix from a string.
285 * @param str the string.
286 * @param prefix the prefix which should be removed if the string begins with it.
287 * @return the string without the prefix.
289 * If the string begins with the prefix, it is removed. If the the string doesn't begin
290 * with the prefix the original string is returned.
292 std::string remove_prefix(const std::string& str, const std::string& prefix)
294 if (has_prefix(str,prefix) )
296 return str.substr( prefix.size() );
299 } // eo remove_prefix(const std::string&,const std::string&)
303 * split a string to key and value delimited by a given delimiter.
304 * The resulting key and value strings are trimmed (Whitespaces removed at beginning and end).
305 * @param str the string which should be splitted.
306 * @param[out] key the resulting key
307 * @param[out] value the resulting value
308 * @param delimiter the delimiter between key and value; default is '='.
309 * @return @a true if the split was successful.
312 const std::string& str,
317 std::string::size_type pos = str.find (delimiter);
318 if (pos == std::string::npos) return false;
319 key= str.substr(0,pos);
320 value= str.substr(pos+1);
324 } // eo pair_split(const std::string&,std::string&,std::string&,char)
328 * splits a string by given delimiter
330 * @param[in] str the string which should be splitted.
331 * @param[out] result the list resulting from splitting @a str.
332 * @param[in] delimiter the delimiter (word/phrase) at which @a str should be splitted.
333 * @param[in] omit_empty should empty parts not be stored?
334 * @param[in] trim_list list of characters the parts should be trimmed by.
335 * (empty string results in no trim)
338 const std::string& str,
339 std::list<std::string>& result,
340 const std::string& delimiter,
342 const std::string& trim_list
345 std::string::size_type pos, last_pos=0;
346 bool delimiter_found= false;
347 while ( last_pos < str.size() && last_pos != std::string::npos)
349 pos= str.find(delimiter, last_pos);
351 if (pos == std::string::npos)
353 part= str.substr(last_pos);
354 delimiter_found= false;
358 part= str.substr(last_pos, pos-last_pos);
359 delimiter_found=true;
361 if (pos != std::string::npos)
363 last_pos= pos+ delimiter.size();
367 last_pos= std::string::npos;
369 if (!trim_list.empty() ) trim_mod (part, trim_list);
370 if (omit_empty && part.empty() ) continue;
371 result.push_back( part );
373 // if the string ends with a delimiter we need to append an empty string if no omit_empty
375 // (this way we keep the split result consistent to a join operation)
376 if (delimiter_found && !omit_empty)
378 result.push_back("");
380 } // eo split_string(const std::string&,std::list< std::string >&,const std::string&,bool,const std::string&)
384 * splits a string by a given delimiter
385 * @param str the string which should be splitted.
386 * @param delimiter delimiter the delimiter (word/phrase) at which @a str should be splitted.
387 * @param[in] omit_empty should empty parts not be stored?
388 * @param[in] trim_list list of characters the parts should be trimmed by.
389 * (empty string results in no trim)
390 * @return the list resulting from splitting @a str.
392 std::list<std::string> split_string(
393 const std::string& str,
394 const std::string& delimiter,
396 const std::string& trim_list
399 std::list<std::string> result;
400 split_string(str, result, delimiter, omit_empty, trim_list);
402 } // eo split_string(const std::string&,const std::string&,bool,const std::string&)
406 * @brief joins a list of strings into a single string.
408 * This funtion is (basically) the reverse operation of @a split_string.
410 * @param parts the list of strings.
411 * @param delimiter the delimiter which is inserted between the strings.
412 * @return the joined string.
414 std::string join_string(
415 const std::list< std::string >& parts,
416 const std::string& delimiter
420 if (! parts.empty() )
422 std::list< std::string >::const_iterator it= parts.begin();
424 while ( ++it != parts.end() )
431 } // eo join_string(const std::list< std::string >&,const std::string&)
434 /** @brief same as join_string for list, except uses a vector */
435 std::string join_string(
436 const std::vector< std::string >& parts,
437 const std::string& delimiter
441 if (! parts.empty() )
443 std::vector< std::string >::const_iterator it= parts.begin();
445 while ( ++it != parts.end() )
452 } // eo join_string(const std::vector< std::string >&,const std::string&)
462 * @brief returns a hex string from a binary string.
463 * @param str the (binary) string
464 * @param upper_case_digits determine whether to use upper case characters for digits A-F.
465 * @return the string in hex notation.
467 std::string convert_binary_to_hex(
468 const std::string& str,
469 bool upper_case_digits
473 std::string hexDigits(upper_case_digits ? hexDigitsUpper : hexDigitsLower);
474 for ( std::string::const_iterator it= str.begin();
478 result.push_back( hexDigits[ ( (*it) >> 4) & 0x0f ] );
479 result.push_back( hexDigits[ (*it) & 0x0f ] );
482 } // eo convert_binary_to_hex(const std::string&,bool)
486 * @brief converts a hex digit string to binary string.
487 * @param str hex digit string
488 * @return the binary string.
490 * The hex digit string may contains white spaces or colons which are treated
491 * as delimiters between hex digit groups.
493 * @todo rework the handling of half nibbles (consistency)!
495 std::string convert_hex_to_binary(
496 const std::string& str
498 throw (std::runtime_error)
502 bool hasNibble= false;
503 bool lastWasWS= true;
504 for ( std::string::const_iterator it= str.begin();
508 std::string::size_type p = hexDigitsLower.find( *it );
509 if (p== std::string::npos)
511 p= hexDigitsUpper.find( *it );
513 if (p == std::string::npos)
515 if ( ( Whitespaces.find( *it ) != std::string::npos) // is it a whitespace?
516 or ( *it == ':') // or a colon?
519 // we treat that as a valid delimiter:
522 // 1 nibble before WS is treate as lower part:
531 if (p == std::string::npos )
533 throw runtime_error("illegal character in hex digit string: " + str);
547 //we already had a nibble, so a char is complete now:
548 result.push_back( c );
553 // this is the first nibble of a new char:
559 //well, there is one nibble left
560 // let's do some heuristics:
563 // if the preceeding character was a white space (or a colon)
564 // we treat the nibble as lower part:
565 //( this is consistent with shortened hex notations where leading zeros are not noted)
566 result.push_back( c );
570 // if it was part of a hex digit chain, we treat it as UPPER part (!!)
571 result.push_back( c << 4 );
575 } // eo convert_hex_to_binary(const std::string&)
578 } // eo namespace I2n
583 std::string iso_to_utf8(const std::string& isostring)
587 iconv_t i2utf8 = iconv_open("UTF-8", "ISO-8859-1");
589 if (iso_to_utf8 == (iconv_t)-1)
590 throw runtime_error("iconv can't convert from ISO-8859-1 to UTF-8");
592 size_t in_size=isostring.size();
593 size_t out_size=in_size*4;
595 char *buf = (char *)malloc(out_size+1);
597 throw runtime_error("out of memory for iconv buffer");
599 char *in = (char *)isostring.c_str();
601 iconv(i2utf8, &in, &in_size, &out, &out_size);
603 buf[isostring.size()*4-out_size]=0;
613 std::string utf8_to_iso(const std::string& utf8string)
617 iconv_t utf82iso = iconv_open("ISO-8859-1","UTF-8");
619 if (utf82iso == (iconv_t)-1)
620 throw runtime_error("iconv can't convert from UTF-8 to ISO-8859-1");
622 size_t in_size=utf8string.size();
623 size_t out_size=in_size;
625 char *buf = (char *)malloc(out_size+1);
627 throw runtime_error("out of memory for iconv buffer");
629 char *in = (char *)utf8string.c_str();
631 iconv(utf82iso, &in, &in_size, &out, &out_size);
633 buf[utf8string.size()-out_size]=0;
638 iconv_close(utf82iso);
643 wchar_t* utf8_to_wbuf(const std::string& utf8string)
645 iconv_t utf82wstr = iconv_open("UCS-4LE","UTF-8");
647 if (utf82wstr == (iconv_t)-1)
648 throw runtime_error("iconv can't convert from UTF-8 to UCS-4");
650 size_t in_size=utf8string.size();
651 size_t out_size= (in_size+1)*sizeof(wchar_t);
653 wchar_t *buf = (wchar_t *)malloc(out_size);
655 throw runtime_error("out of memory for iconv buffer");
657 char *in = (char *)utf8string.c_str();
658 char *out = (char*) buf;
659 if (iconv(utf82wstr, &in, &in_size, &out, &out_size) == (size_t)-1)
660 throw runtime_error("error converting char encodings");
662 buf[ ( (utf8string.size()+1)*sizeof(wchar_t)-out_size) /sizeof(wchar_t) ]=0;
664 iconv_close(utf82wstr);
669 std::string utf7imap_to_utf8(const std::string& utf7imapstring)
673 iconv_t utf7imap2utf8 = iconv_open("UTF-8","UTF-7-IMAP");
675 if (utf7imap2utf8 == (iconv_t)-1)
676 throw runtime_error("iconv can't convert from UTF-7-IMAP to UTF-8");
678 size_t in_size=utf7imapstring.size();
679 size_t out_size=in_size*4;
681 char *buf = (char *)malloc(out_size+1);
683 throw runtime_error("out of memory for iconv buffer");
685 char *in = (char *)utf7imapstring.c_str();
687 iconv(utf7imap2utf8, &in, &in_size, &out, &out_size);
689 buf[utf7imapstring.size()*4-out_size]=0;
694 iconv_close(utf7imap2utf8);
699 std::string utf8_to_utf7imap(const std::string& utf8string)
703 iconv_t utf82utf7imap = iconv_open("UTF-7-IMAP", "UTF-8");
705 if (utf82utf7imap == (iconv_t)-1)
706 throw runtime_error("iconv can't convert from UTF-7-IMAP to UTF-8");
708 // UTF-7 is base64 encoded, a buffer 10x as large
709 // as the utf-8 buffer should be enough. If not the string will be truncated.
710 size_t in_size=utf8string.size();
711 size_t out_size=in_size*10;
713 char *buf = (char *)malloc(out_size+1);
715 throw runtime_error("out of memory for iconv buffer");
717 char *in = (char *)utf8string.c_str();
719 iconv(utf82utf7imap, &in, &in_size, &out, &out_size);
721 buf[utf8string.size()*10-out_size]= 0;
726 iconv_close(utf82utf7imap);
731 // Tokenize string by (html) tags
732 void tokenize_by_tag(vector<pair<string,bool> > &tokenized, const std::string &input)
734 string::size_type pos, len = input.size();
735 bool inside_tag = false;
738 for (pos = 0; pos < len; pos++)
740 if (input[pos] == '<')
744 if (!current.empty() )
746 tokenized.push_back( make_pair(current, false) );
750 current += input[pos];
752 else if (input[pos] == '>' && inside_tag)
754 current += input[pos];
756 if (!current.empty() )
758 tokenized.push_back( make_pair(current, true) );
763 current += input[pos];
766 // String left over in buffer?
767 if (!current.empty() )
768 tokenized.push_back( make_pair(current, false) );
769 } // eo tokenize_by_tag
772 std::string strip_html_tags(const std::string &input)
774 // Pair first: string, second: isTag
775 vector<pair<string,bool> > tokenized;
776 tokenize_by_tag (tokenized, input);
779 vector<pair<string,bool> >::const_iterator token, tokens_end = tokenized.end();
780 for (token = tokenized.begin(); token != tokens_end; ++token)
782 output += token->first;
785 } // eo strip_html_tags
788 // Smart-encode HTML en
789 string smart_html_entities(const std::string &input)
791 // Pair first: string, second: isTag
792 vector<pair<string,bool> > tokenized;
793 tokenize_by_tag (tokenized, input);
796 vector<pair<string,bool> >::const_iterator token, tokens_end = tokenized.end();
797 for (token = tokenized.begin(); token != tokens_end; ++token)
799 // keep HTML tags as they are
801 output += token->first;
803 output += html_entities(token->first);
810 string::size_type find_8bit(const std::string &str)
812 string::size_type l=str.size();
813 for (string::size_type p=0; p < l; p++)
814 if (static_cast<unsigned char>(str[p]) > 127)
820 // encoded UTF-8 chars into HTML entities
821 string html_entities(std::string str)
824 replace_all (str, "&", "&");
825 replace_all (str, "<", "<");
826 replace_all (str, ">", ">");
827 replace_all (str, "\"", """);
828 replace_all (str, "'", "'");
829 replace_all (str, "/", "/");
832 replace_all (str, "\xC3\xA4", "ä");
833 replace_all (str, "\xC3\xB6", "ö");
834 replace_all (str, "\xC3\xBC", "ü");
835 replace_all (str, "\xC3\x84", "Ä");
836 replace_all (str, "\xC3\x96", "Ö");
837 replace_all (str, "\xC3\x9C", "Ü");
840 replace_all (str, "\xC3\x9F", "ß");
842 // conversion of remaining non-ASCII chars needed?
843 // just do if needed because of performance
844 if (find_8bit(str) != string::npos)
846 // convert to fixed-size encoding UTF-32
847 wchar_t* wbuf=utf8_to_wbuf(str);
848 ostringstream target;
850 // replace all non-ASCII chars with HTML representation
851 for (int p=0; wbuf[p] != 0; p++)
853 unsigned int c=wbuf[p];
856 target << static_cast<unsigned char>(c);
858 target << "&#" << c << ';';
867 } // eo html_entities(std::string)
869 // convert HTML entities to something that can be viewed on a basic text console (restricted to ASCII-7)
870 string html_entities_to_console(std::string str)
873 replace_all (str, "&", "&");
874 replace_all (str, "<", "<");
875 replace_all (str, ">", ">");
876 replace_all (str, """, "\"");
877 replace_all (str, "'", "'");
878 replace_all (str, "/", "/");
881 replace_all (str, "ä", "ae");
882 replace_all (str, "ö", "oe");
883 replace_all (str, "ü", "ue");
884 replace_all (str, "Ä", "Ae");
885 replace_all (str, "Ö", "Oe");
886 replace_all (str, "Ü", "Ue");
889 replace_all (str, "ß", "ss");
894 bool replace_all(string &base, const char *ist, const char *soll)
898 return replace_all(base,&i,&s);
901 bool replace_all(string &base, const string &ist, const char *soll)
904 return replace_all(base,&ist,&s);
907 bool replace_all(string &base, const string *ist, const string *soll)
909 return replace_all(base,*ist,*soll);
912 bool replace_all(string &base, const char *ist, const string *soll)
915 return replace_all(base,&i,soll);
918 bool replace_all(string &base, const string &ist, const string &soll)
920 bool found_ist = false;
921 string::size_type a=0;
924 throw runtime_error ("replace_all called with empty search string");
926 while ( (a=base.find(ist,a) ) != string::npos)
928 base.replace(a,ist.size(),soll);
937 * @brief replaces all characters that could be problematic or impose a security risk when being logged
938 * @param str the original string
939 * @param replace_with the character to replace the unsafe chars with
940 * @return a string that is safe to send to syslog or other logfiles
942 * All chars between 0x20 (space) and 0x7E (~) (including) are considered safe for logging.
943 * See e.g. RFC 5424, section 8.2 or the posix character class "printable".
944 * This eliminates all possible problems with NUL, control characters, 8 bit chars, UTF8.
947 std::string sanitize_for_logging(const std::string &str, const char replace_with)
949 std::string output=str;
951 const string::size_type len = output.size();
952 for (std::string::size_type p=0; p < len; p++)
953 if (output[p] < 0x20 || output[p] > 0x7E)
954 output[p]=replace_with;
960 string to_lower(const string &src)
964 string::size_type pos, end = dst.size();
965 for (pos = 0; pos < end; pos++)
966 dst[pos] = tolower(dst[pos]);
971 string to_upper(const string &src)
975 string::size_type pos, end = dst.size();
976 for (pos = 0; pos < end; pos++)
977 dst[pos] = toupper(dst[pos]);
983 const int MAX_UNIT_FORMAT_SYMBOLS = 6;
985 const string shortUnitFormatSymbols[MAX_UNIT_FORMAT_SYMBOLS] = {
994 const string longUnitFormatSymbols[MAX_UNIT_FORMAT_SYMBOLS] = {
996 i18n_noop(" KBytes"),
997 i18n_noop(" MBytes"),
998 i18n_noop(" GBytes"),
999 i18n_noop(" TBytes"),
1000 i18n_noop(" PBytes")
1004 long double rounding_upwards(
1005 const long double number,
1006 const int rounding_multiplier
1009 long double rounded_number;
1010 rounded_number = number * rounding_multiplier;
1011 rounded_number += 0.5;
1012 rounded_number = (int64_t) (rounded_number);
1013 rounded_number = (long double) (rounded_number) / (long double) (rounding_multiplier);
1015 return rounded_number;
1019 string nice_unit_format(
1020 const int64_t input,
1021 const UnitFormat format,
1025 // select the system of units (decimal or binary)
1027 if (base == UnitBase1000)
1036 long double size = input;
1038 // check the size of the input number to fit in the appropriate symbol
1040 while (size > multiple)
1042 size = size / multiple;
1045 // rollback to the previous values and stop the loop when cannot
1046 // represent the number length.
1047 if (sizecount >= MAX_UNIT_FORMAT_SYMBOLS)
1049 size = size * multiple;
1055 // round the input number "half up" to multiples of 10
1056 const int rounding_multiplier = 10;
1057 size = rounding_upwards(size, rounding_multiplier);
1059 // format the input number, placing the appropriate symbol
1061 out.setf (ios::fixed);
1062 if (format == ShortUnitFormat)
1065 out << size << i18n( shortUnitFormatSymbols[sizecount].c_str() );
1070 out << size << i18n( longUnitFormatSymbols[sizecount].c_str() );
1074 } // eo nice_unit_format(int input)
1077 string nice_unit_format(
1079 const UnitFormat format,
1083 // round as double and cast to int64_t
1084 // cast raised overflow error near max val of int64_t (~9.2e18, see unittest)
1085 int64_t input_casted_and_rounded =
1086 boost::numeric_cast<int64_t>( round(input) );
1089 return nice_unit_format( input_casted_and_rounded, format, base );
1090 } // eo nice_unit_format(double input)
1093 string escape(const string &s)
1096 string::size_type p;
1099 while ( (p=out.find_first_of("\"\\",p) ) !=out.npos)
1101 out.insert (p,"\\");
1106 while ( (p=out.find_first_of("\r",p) ) !=out.npos)
1108 out.replace (p,1,"\\r");
1113 while ( (p=out.find_first_of("\n",p) ) !=out.npos)
1115 out.replace (p,1,"\\n");
1122 } // eo scape(const std::string&)
1125 string descape(const string &s, int startpos, int &endpos)
1129 if (s.at(startpos) != '"')
1130 throw out_of_range("value not type escaped string");
1132 out=s.substr(startpos+1);
1133 string::size_type p=0;
1135 // search for the end of the string
1136 while ( (p=out.find("\"",p) ) !=out.npos)
1141 // the " might be escaped with a backslash
1142 while (e>=0 && out.at (e) =='\\')
1144 if (escaped == false)
1158 // we now have the end of the string
1159 out=out.substr(0,p);
1161 // tell calling prog about the endposition
1162 endpos=startpos+p+1;
1164 // descape all \ stuff inside the string now
1166 while ( (p=out.find_first_of("\\",p) ) !=out.npos)
1168 switch (out.at(p+1) )
1171 out.replace(p,2,"\r");
1174 out.replace(p,2,"\n");
1183 } // eo descape(const std::string&,int,int&)
1186 string escape_shellarg(const string &input)
1188 string output = "'";
1189 string::const_iterator it, it_end = input.end();
1190 for (it = input.begin(); it != it_end; ++it)