1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
// SPDX-License-Identifier: 0BSD
#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <cstring>
extern "C" {
#include "quote.h"
}
static char * quote(const char * beg, const char * end, char * cur) {
*cur++ = '\'';
for(; beg != end; ++beg)
if(*beg == '\'') {
*cur++ = '\'';
*cur++ = '\\';
*cur++ = '\'';
*cur++ = '\'';
} else
*cur++ = *beg;
*cur++ = '\'';
return cur;
}
/* Turn "abc %s def %s", "qwe'rt" into "abc 'qwe'\''rt' def %s"
* or "ghi", "qwe'rt" into "ghi 'qwe'\''rt'"
*/
extern "C" char * quotesub(const char * execline, size_t execlinelen, const char * url, size_t urllen) {
assert(execline);
assert(url);
auto pct_s = static_cast<const char *>(memmem(execline, execlinelen, "%s", 2));
// %s SPC ' ' NUL
auto space = execlinelen + (pct_s ? -2 : 1) + 1 + urllen + (std::count(url, url + urllen, '\'') * 3) + 1 + 1;
auto ret = reinterpret_cast<char *>(std::malloc(space)), cur = ret;
if(pct_s) {
cur = std::copy(execline, pct_s, cur);
cur = quote(url, url + urllen, cur);
cur = std::copy(pct_s + 2, execline + execlinelen, cur);
} else {
cur = std::copy(execline, execline + execlinelen, cur);
*cur++ = ' ';
cur = quote(url, url + urllen, cur);
}
*cur++ = '\0';
return ret;
}
#if TEST
#include <cstdio>
int main() {
for(auto && [line, exp] : {std::pair{"abc %s def %s", "abc 'qwe'\\''rt' def %s"}, std::pair{"ghi", "ghi 'qwe'\\''rt'"}}) {
auto res = quotesub(line, std::strlen(line), "qwe'rt", std::strlen("qwe'rt"));
std::printf("%s %s\n", line, res);
assert(!std::strcmp(res, exp));
}
}
#endif
|