![](https://seccdn.libravatar.org/avatar/128a7b98d536a9cf9b4d4d5a90d63475.jpg?s=120&d=mm&r=g)
Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package trurl for openSUSE:Factory checked in at 2024-06-03 17:43:24 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/trurl (Old) and /work/SRC/openSUSE:Factory/.trurl.new.24587 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "trurl" Mon Jun 3 17:43:24 2024 rev:12 rq:1178135 version:0.13 Changes: -------- --- /work/SRC/openSUSE:Factory/trurl/trurl.changes 2024-04-23 18:57:21.157232951 +0200 +++ /work/SRC/openSUSE:Factory/.trurl.new.24587/trurl.changes 2024-06-03 17:43:30.635138445 +0200 @@ -1,0 +2,10 @@ +Wed May 15 15:47:08 UTC 2024 - Martin Hauke <mardnh@gmx.de> + +- Update to version 0.13 + * Free allocated pointer on OOM error. + * short options need no space separation for the argument anymore + * trurl.1: use present tense. + * trurl: only append the first iterate loop. + * fix Coverity nits. + +------------------------------------------------------------------- Old: ---- trurl-0.12.tar.gz New: ---- trurl-0.13.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ trurl.spec ++++++ --- /var/tmp/diff_new_pack.hND1uu/_old 2024-06-03 17:43:31.271161885 +0200 +++ /var/tmp/diff_new_pack.hND1uu/_new 2024-06-03 17:43:31.271161885 +0200 @@ -18,7 +18,7 @@ Name: trurl -Version: 0.12 +Version: 0.13 Release: 0 Summary: Command line tool for URL parsing and manipulation License: MIT ++++++ trurl-0.12.tar.gz -> trurl-0.13.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/trurl-trurl-0.12/.github/workflows/codeql.yml new/trurl-trurl-0.13/.github/workflows/codeql.yml --- old/trurl-trurl-0.12/.github/workflows/codeql.yml 2024-04-18 22:13:05.000000000 +0200 +++ new/trurl-trurl-0.13/.github/workflows/codeql.yml 2024-05-15 08:23:20.000000000 +0200 @@ -34,11 +34,11 @@ steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} @@ -51,6 +51,6 @@ run: make - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/trurl-trurl-0.12/.github/workflows/codespell.yml new/trurl-trurl-0.13/.github/workflows/codespell.yml --- old/trurl-trurl-0.12/.github/workflows/codespell.yml 2024-04-18 22:13:05.000000000 +0200 +++ new/trurl-trurl-0.13/.github/workflows/codespell.yml 2024-05-15 08:23:20.000000000 +0200 @@ -5,7 +5,7 @@ runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: install codespell run: | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/trurl-trurl-0.12/.github/workflows/curl-for-win.yml new/trurl-trurl-0.13/.github/workflows/curl-for-win.yml --- old/trurl-trurl-0.12/.github/workflows/curl-for-win.yml 2024-04-18 22:13:05.000000000 +0200 +++ new/trurl-trurl-0.13/.github/workflows/curl-for-win.yml 2024-05-15 08:23:20.000000000 +0200 @@ -49,7 +49,7 @@ - name: 'list dependencies' run: cat urls.txt - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: 'trurl-windows' retention-days: 5 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/trurl-trurl-0.12/.github/workflows/makefile.yml new/trurl-trurl-0.13/.github/workflows/makefile.yml --- old/trurl-trurl-0.12/.github/workflows/makefile.yml 2024-04-18 22:13:05.000000000 +0200 +++ new/trurl-trurl-0.13/.github/workflows/makefile.yml 2024-05-15 08:23:20.000000000 +0200 @@ -25,7 +25,7 @@ LDFLAGS="-fsanitize=address,undefined,signed-integer-overflow -g" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: install libcurl run: | @@ -48,7 +48,7 @@ runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: install cygwin uses: cygwin/cygwin-install-action@master @@ -68,7 +68,7 @@ runs-on: macos-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: make run: make diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/trurl-trurl-0.12/.github/workflows/reuse.yml new/trurl-trurl-0.13/.github/workflows/reuse.yml --- old/trurl-trurl-0.12/.github/workflows/reuse.yml 2024-04-18 22:13:05.000000000 +0200 +++ new/trurl-trurl-0.13/.github/workflows/reuse.yml 2024-05-15 08:23:20.000000000 +0200 @@ -24,6 +24,6 @@ check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: REUSE Compliance Check uses: fsfe/reuse-action@v1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/trurl-trurl-0.12/CONTRIBUTING.md new/trurl-trurl-0.13/CONTRIBUTING.md --- old/trurl-trurl-0.12/CONTRIBUTING.md 2024-04-18 22:13:05.000000000 +0200 +++ new/trurl-trurl-0.13/CONTRIBUTING.md 2024-05-15 08:23:20.000000000 +0200 @@ -36,7 +36,7 @@ `test.py` will also skip tests that require a specific curl runtime or buildtime. ### Adding tests -tests are located in [tests.json](https://github.com/curl/trurl/blob/master/tests.json). This file is an array of json objects when outline an input and what the expected +Tests are located in [tests.json](https://github.com/curl/trurl/blob/master/tests.json). This file is an array of json objects when outline an input and what the expected output should be. Below is a simple example of a single test: ```json { @@ -72,7 +72,7 @@ } ``` trurl may also return json. It you are adding a test that returns json to stdout, write the json directly instead of a string in the examples above. Below is an example -of what stdout should be if it is a json test, where `"input"` is what trul accepts from the command line and `"expected"` is what trurl should return. +of what stdout should be if it is a json test, where `"input"` is what trurl accepts from the command line and `"expected"` is what trurl should return. ```json "expected": { "stdout": [ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/trurl-trurl-0.12/RELEASE-NOTES new/trurl-trurl-0.13/RELEASE-NOTES --- old/trurl-trurl-0.12/RELEASE-NOTES 2024-04-18 22:13:05.000000000 +0200 +++ new/trurl-trurl-0.13/RELEASE-NOTES 2024-05-15 08:23:20.000000000 +0200 @@ -1,17 +1,17 @@ -# trurl 0.12 +# trurl 0.13 ## What's Changed -- This is the same as 0.11 but with the version string set correctly - -- check valgrind function by @eh-san in #273 -- Added UTF-8 detection to test runner by @jacobmealey in #276 -- use of free() instead of curl_free() by @bagder in #283 -- output the list of components correctly in the help output by @bagder in #282 -- if query is not updated, leave it untouched by @bagder in #284 -- expand the warning on "internal problem" by @bagder in #285 -- error when using an unrecognized URL component by @bagder in #286 + - (also) support --flag=argument style for long options + - fix unchecked return values from libcurl calls + - fixed typos + - free allocated pointer on OOM error + - memdupdec: free memory in OOM exit path + - only --append in the first iterate loop + - short options need no space separation for the argument anymore + - support ?= for set, to only do it if not already set + - trurl.1: use present tense Contributors to this release: - Daniel Stenberg, Jacob Mealey, Ehsan + Daniel Gustafsson, Daniel Stenberg, Jacob Mealey, Viktor Szakats diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/trurl-trurl-0.12/tests.json new/trurl-trurl-0.13/tests.json --- old/trurl-trurl-0.12/tests.json 2024-04-18 22:13:05.000000000 +0200 +++ new/trurl-trurl-0.13/tests.json 2024-05-15 08:23:20.000000000 +0200 @@ -151,6 +151,32 @@ { "input": { "arguments": [ + "-shost=moo", + "-sscheme=http" + ] + }, + "expected": { + "stdout": "http://moo/\n", + "stderr": "", + "returncode": 0 + } + }, + { + "input": { + "arguments": [ + "--set=host=moo", + "--set=scheme=http" + ] + }, + "expected": { + "stdout": "http://moo/\n", + "stderr": "", + "returncode": 0 + } + }, + { + "input": { + "arguments": [ "-s", "host=moo", "-s", @@ -322,6 +348,20 @@ { "input": { "arguments": [ + "--url", + "https://curl.se/we/are.html", + "-g{path}" + ] + }, + "expected": { + "stdout": "/we/are.html\n", + "stderr": "", + "returncode": 0 + } + }, + { + "input": { + "arguments": [ "--default-port", "--url", "imap://curl.se/we/are.html", @@ -2444,5 +2484,65 @@ "stderr": "", "returncode": 0 } + }, + { + "input": { + "arguments": [ + "example.com:88", + "--set", + "port?=99" + ] + }, + "expected": { + "stdout": "http://example.com:88/\n", + "stderr": "", + "returncode": 0 + } + }, + { + "input": { + "arguments": [ + "example.com", + "--set", + "port?=99" + ] + }, + "expected": { + "stdout": "http://example.com:99/\n", + "stderr": "", + "returncode": 0 + } + }, + { + "input": { + "arguments": [ + "example.com", + "--append", + "query=add", + "--iterate", + "scheme=http ftp" + ] + }, + "expected": { + "stdout": "http://example.com/?add\nftp://example.com/?add\n", + "stderr": "", + "returncode": 0 + } + }, + { + "input": { + "arguments": [ + "example.com", + "--append", + "path=add", + "--iterate", + "scheme=http ftp" + ] + }, + "expected": { + "stdout": "http://example.com/add\nftp://example.com/add\n", + "stderr": "", + "returncode": 0 + } } ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/trurl-trurl-0.12/trurl.1 new/trurl-trurl-0.13/trurl.1 --- old/trurl-trurl-0.12/trurl.1 2024-04-18 22:13:05.000000000 +0200 +++ new/trurl-trurl-0.13/trurl.1 2024-05-15 08:23:20.000000000 +0200 @@ -55,6 +55,8 @@ options; any argument after the end of options is interpreted as a URL argument even if it starts with a dash. +Long options can be provided either as "--flag argument" or as +"--flag=argument". .IP "-a, --append [component]=[data]" Append data to a component. This can only append data to the path and the query components. @@ -64,16 +66,16 @@ For query, this URL encodes and appends the new segment to the query, separated with an ampersand (&). If the appended segment contains an equal -sign ('=') that one will be kept verbatim and both sides of the first -occurrence will be URL encoded separately. +sign ('=') that one is kept verbatim and both sides of the first +occurrence are URL encoded separately. .IP "--accept-space" -When set, trurl will try to accept spaces as part of the URL and instead URL +When set, trurl tries to accept spaces as part of the URL and instead URL encode such occurrences accordingly. According to RFC 3986, a space cannot legally be part of a URL. This option provides a best-effort to convert the provided string into a valid URL. .IP "--default-port" -When set, trurl will use the scheme's default port number for URLs with a known +When set, trurl uses the scheme's default port number for URLs with a known scheme, and without an explicit port number. Note that trurl only knows default port numbers for URL schemes that are @@ -86,9 +88,9 @@ Read URLs to work on from the given file. Use the file name "-" (a single minus) to tell trurl to read the URLs from stdin. -Each line needs to be a single valid URL. trurl will remove one carriage return -character at the end of the line if present, trim off all the trailing space and -tab characters, and skip all empty (after trimming) lines. +Each line needs to be a single valid URL. trurl removes one carriage return +character at the end of the line if present, trims off all the trailing space +and tab characters, and skips all empty (after trimming) lines. The maximum line length supported in a file like this is 4094 bytes. Lines that exceed that length are skipped, and a warning is printed to stderr when they are @@ -103,7 +105,7 @@ The following component names are available (case sensitive): url, scheme, user, password, options, host, port, path, query, fragment and zoneid. -\fB{component}\fP will expand to nothing if the given component does +\fB{component}\fP expands to nothing if the given component does not have a value. Components are shown URL decoded by default. If you instead write the @@ -114,36 +116,36 @@ If \fBdefault:\fP is specified, like "{default:url}" or "{default:port}", and the port is not explicitly specified in the URL, -the scheme's default port will be output if it is known. +the scheme's default port is output if it is known. If \fBpuny:\fP is specified, like "{puny:url}" or "{puny:host}", the -"punycoded" version of the host name will be used in the output. This +"punycoded" version of the host name is used in the output. This option is mutually exclusive with \fBidn:\fP. If \fBidn:\fP is specified like "{idn:url}" or "{idn:host}", the International -Domain Name version of the host name will be used in the output if it is provided as a correctly encoded punycode version. This -option is mutually exclusive with \fBpuny:\fP. +Domain Name version of the host name is used in the output if it is provided as +a correctly encoded punycode version. This option is mutually exclusive with \fBpuny:\fP. If \fI--default-port\fP is specified, all formats are expanded as if they used \fIdefault:\fP; and if \fI--punycode\fP is used, all formats are expanded as if they used \fIpuny:\fP. Also note that "{url}" is affected by the \fI--keep-port\fP option. -Hosts provided as IPv6 numerical addresses will be provided within square +Hosts provided as IPv6 numerical addresses are provided within square brackets. Like "[fe80::20c:29ff:fe9c:409b]". -Hosts provided as IPv4 numerical addresses will be "normalized" and provided +Hosts provided as IPv4 numerical addresses are "normalized" and provided as four dot-separated decimal numbers when output. You can access specific keys in the query string using the format -\fB{query:key}\fP. Then the value of the first matching key will be output +\fB{query:key}\fP. Then the value of the first matching key is output using a case sensitive match. When extracting a URL decoded query key that -contains %00, such octet will be replaced with a single period '.' in the +contains %00, such octet is replaced with a single period '.' in the output. You can access specific keys in the query string and out all values using the -format \fB{query-all:key}\fP. This looks for 'key' case sensitively and will -output all values for that key space-separated. +format \fB{query-all:key}\fP. This looks for 'key' case sensitively and +outputs all values for that key space-separated. The "format" string supports the following backslash sequences: @@ -159,7 +161,7 @@ \&\\[ - an open bracket that does not start a variable -All other text in the format string will be shown as-is. +All other text in the format string is shown as-is. .IP "-h, --help" Show the help output. .IP "--iterate [component]=[item1 item2 ...]" @@ -169,15 +171,15 @@ over should be separated by single spaces. .IP "--json" Outputs all set components of the URLs as JSON objects. All components of the -URL that have data will get populated in the parts object using their -component names. See below for details on the format. +URL that have data get populated in the parts object using their component +names. See below for details on the format. .IP "--keep-port" By default, trurl removes default port numbers from URLs with a known scheme even if they are explicitly specified in the input URL. This options, makes trurl not remove them. .IP "--no-guess-scheme" Disables libcurl's scheme guessing feature. URLs that do not contain a scheme -will be treated as invalid URLs. +are treated as invalid URLs. .IP "--punycode" Uses the "punycoded" version of the host name, which is how International Domain Names are converted into plain ASCII. If the host name is not using IDN, the @@ -195,43 +197,47 @@ .IP "--redirect [URL]" Redirect the URL to this new location. The redirection is performed on the base URL, so, if no base URL is specified, -no redirection will be performed. +no redirection is performed. .IP "--replace [data]" Replaces a URL query. data can either take the form of a single value, or as a key/value pair in the shape \fIfoo=bar\fP. If replace is called on an item that isn't in the list of -queries trurl will ignore that item. +queries trurl ignores that item. .IP "--force-replace [data]" -Works the same as \fI--replace\fP, but trurl will append a missing query string if +Works the same as \fI--replace\fP, but trurl appends a missing query string if it is not in the query list already. .IP "-s, --set [component][:]=[data]" -Set this URL component. Setting blank string ("") will clear the component +Set this URL component. Setting blank string ("") clears the component from the URL. The following components can be set: url, scheme, user, password, options, host, port, path, query, fragment and zoneid. If a simple "="-assignment is used, the data is URL encoded when applied. If -":=" is used, the data is assumed to already be URL encoded and will be stored -as-is. +":=" is used, the data is assumed to already be URL encoded and stored as-is. -If no URL or \fI--url-file\fP argument is provided, trurl will try to create +If "?=" is used, the set is only performed if the component is not already +set. It avoids overwriting any already set data. + +You can also combine : and ? into "?:=" if desired. + +If no URL or \fI--url-file\fP argument is provided, trurl tries to create a URL using the components provided by the \fI--set\fP options. If not enough -components are specified, this will fail. +components are specified, this fails. .IP "--sort-query" The "variable=content" tuplets in the query component are sorted in a case insensitive alphabetical order. This helps making URLs identical that otherwise only had their query pairs in different orders. .IP "--url [URL]" Set the input URL to work with. The URL may be provided without a scheme, -which then typically is not actually a legal URL but trurl will try to figure +which then typically is not actually a legal URL but trurl tries to figure out what is meant and guess what scheme to use (unless \fI--no-guess-scheme\fP is used). -Providing multiple URLs will make trurl act on all URLs in a serial fashion. +Providing multiple URLs makes trurl act on all URLs in a serial fashion. -If the URL cannot be parsed for whatever reason, trurl will simply move on to +If the URL cannot be parsed for whatever reason, trurl simply moves on to the next provided URL - unless \fI--verify\fP is used. .IP "--urlencode" Outputs URL encoded version of components by default when using \fI--get\fP or @@ -292,7 +298,7 @@ .B "port" The provided port number as a string. If the port number was not provided in the URL, but the scheme is a known one, and \fI--default-port\fP is in use, the -default port for that scheme will be provided here. +default port for that scheme is provided here. .TP .B "path" The path. Including the leading slash. @@ -335,7 +341,7 @@ https://curl.se/we/here.html .fi .IP "Change port number" -This also shows how trurl will remove dot-dot sequences +This also shows how trurl removes dot-dot sequences .nf $ trurl --url https://curl.se/we/../are.html --set port=8080 https://curl.se:8080/are.html diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/trurl-trurl-0.12/trurl.c new/trurl-trurl-0.13/trurl.c --- old/trurl-trurl-0.12/trurl.c 2024-04-18 22:13:05.000000000 +0200 +++ new/trurl-trurl-0.13/trurl.c 2024-05-15 08:23:20.000000000 +0200 @@ -488,13 +488,26 @@ if(n) o->replace_list = n; } -static bool checkoptarg(struct option *o, const char *str, + +static bool longarg(const char *flag, const char *check) +{ + /* the given flag might end with an equals sign */ + size_t len = strlen(flag); + return (!strcmp(flag, check) || + (!strncmp(flag, check, len) && check[len] == '=')); +} + +static bool checkoptarg(struct option *o, const char *flag, const char *given, const char *arg) { - if(!strcmp(str, given)) { + bool shortopt = false; + if((flag[0] == '-') && (flag[1] != '-')) + shortopt = true; + if((!shortopt && longarg(flag, given)) || + (!strncmp(flag, given, 2) && shortopt)) { if(!arg) - errorf(o, ERROR_ARG, "Missing argument for %s", str); + errorf(o, ERROR_ARG, "Missing argument for %s", flag); return true; } return false; @@ -505,8 +518,21 @@ const char *arg, bool *usedarg) { + bool gap = true; *usedarg = false; + if((flag[0] == '-') && (flag[1] != '-') && flag[2]) { + arg = (char *)&flag[2]; + gap = false; + } + else if((flag[0] == '-') && (flag[1] == '-')) { + char *equals = strchr(&flag[2], '='); + if(equals) { + arg = (char *)&equals[1]; + gap = false; + } + } + if(!strcmp("--", flag)) o->end_of_options = true; else if(!strcmp("-v", flag) || !strcmp("--version", flag)) @@ -515,32 +541,32 @@ help(); else if(checkoptarg(o, "--url", flag, arg)) { urladd(o, arg); - *usedarg = true; + *usedarg = gap; } else if(checkoptarg(o, "-f", flag, arg) || checkoptarg(o, "--url-file", flag, arg)) { urlfile(o, arg); - *usedarg = true; + *usedarg = gap; } else if(checkoptarg(o, "-a", flag, arg) || checkoptarg(o, "--append", flag, arg)) { appendadd(o, arg); - *usedarg = true; + *usedarg = gap; } else if(checkoptarg(o, "-s", flag, arg) || checkoptarg(o, "--set", flag, arg)) { setadd(o, arg); - *usedarg = true; + *usedarg = gap; } else if(checkoptarg(o, "--iterate", flag, arg)) { iteradd(o, arg); - *usedarg = true; + *usedarg = gap; } else if(checkoptarg(o, "--redirect", flag, arg)) { if(o->redirect) errorf(o, ERROR_FLAG, "only one --redirect is supported"); o->redirect = arg; - *usedarg = true; + *usedarg = gap; } else if(checkoptarg(o, "--query-separator", flag, arg)) { if(o->qsep) @@ -549,11 +575,11 @@ errorf(o, ERROR_FLAG, "only single-letter query separators are supported"); o->qsep = arg; - *usedarg = true; + *usedarg = gap; } else if(checkoptarg(o, "--trim", flag, arg)) { trimadd(o, arg); - *usedarg = true; + *usedarg = gap; } else if(checkoptarg(o, "-g", flag, arg) || checkoptarg(o, "--get", flag, arg)) { @@ -561,13 +587,13 @@ errorf(o, ERROR_FLAG, "only one --get is supported"); if(o->jsonout) errorf(o, ERROR_FLAG, - "--get is mututally exclusive with --json"); + "--get is mutually exclusive with --json"); o->format = arg; - *usedarg = true; + *usedarg = gap; } else if(!strcmp("--json", flag)) { if(o->format) - errorf(o, ERROR_FLAG, "--json is mututally exclusive with --get"); + errorf(o, ERROR_FLAG, "--json is mutually exclusive with --get"); o->jsonout = true; } else if(!strcmp("--verify", flag)) @@ -606,12 +632,12 @@ o->quiet_warnings = true; else if(!strcmp("--replace", flag)) { replaceadd(o, arg); - *usedarg = true; + *usedarg = gap; } else if(!strcmp("--force-replace", flag)) { replaceadd(o, arg); o->force_replace = true; - *usedarg = true; + *usedarg = gap; } else return 1; /* unrecognized option */ @@ -873,20 +899,47 @@ if(ptr && (ptr > setline)) { size_t vlen = ptr - setline; bool urlencode = true; + bool conditional = false; bool found = false; - if(ptr[-1] == ':') { - urlencode = false; - vlen--; + if(vlen) { + int back = -1; + size_t reqlen = 1; + while(vlen > reqlen) { + if(ptr[back] == ':') { + urlencode = false; + vlen--; + } + else if(ptr[back] == '?') { + conditional = true; + vlen--; + } + else + break; + reqlen++; + back--; + } } v = comp2var(setline, vlen); if(v) { - CURLUcode rc; + CURLUcode rc = CURLUE_OK; + bool skip = false; if((v->part == CURLUPART_HOST) && ('[' == ptr[1])) /* when setting an IPv6 numerical address, disable URL encoding */ urlencode = false; - rc = curl_url_set(uh, v->part, ptr[1] ? &ptr[1] : NULL, - (o->curl ? 0 : CURLU_NON_SUPPORT_SCHEME)| - (urlencode ? CURLU_URLENCODE : 0) ); + + if(conditional) { + char *piece; + rc = curl_url_get(uh, v->part, &piece, 0); + if(!rc) { + skip = true; + curl_free(piece); + } + } + + if(!skip) + rc = curl_url_set(uh, v->part, ptr[1] ? &ptr[1] : NULL, + (o->curl ? 0 : CURLU_NON_SUPPORT_SCHEME)| + (urlencode ? CURLU_URLENCODE : 0) ); if(rc) warnf("Error setting %s: %s", v->name, curl_url_strerror(rc)); found = true; @@ -1122,18 +1175,21 @@ char *p; int plen; right = strurldecode(sep + 1, (int)(len - (sep - source) - 1), - &right_len); + &right_len); /* convert null bytes to periods */ for(plen = right_len, p = right; plen; plen--, p++) { if(!*p && !json) { *p = REPLACE_NULL_BYTE; } - } + } } str = malloc(sizeof(char) * (left_len + (sep?(right_len + 1):0))); - if(!str) + if(!str) { + curl_free(right); + curl_free(left); return NULL; + } memcpy(str, left, left_len); if(sep) { str[left_len] = '='; @@ -1143,6 +1199,7 @@ curl_free(left); ret = malloc(sizeof(struct string)); if(!ret) { + free(str); return NULL; } ret->str = str; @@ -1342,6 +1399,7 @@ struct curl_slist *iter) { CURLU *uh = iinfo->uh; + bool first_lap = true; if(!uh) { uh = curl_url(); if(!uh) @@ -1431,9 +1489,10 @@ wlen = strlen(w); iinfo->ptr = NULL; } - curl_msnprintf(iterbuf, sizeof(iterbuf), "%.*s%s=%.*s", (int)plen, part, - urlencode ? "" : ":", - (int)wlen, w); + (void)curl_msnprintf(iterbuf, sizeof(iterbuf), + "%.*s%s=%.*s", (int)plen, part, + urlencode ? "" : ":", + (int)wlen, w); setone(uh, iterbuf, o); if(iter->next) { struct iterinfo info; @@ -1444,29 +1503,33 @@ } } - /* append path segments */ - for(p = o->append_path; p; p = p->next) { - char *apath = p->data; - char *opath; - char *npath; - size_t olen; - /* extract the current path */ - curl_url_get(uh, CURLUPART_PATH, &opath, 0); - - /* does the existing path end with a slash, then don't - add one in between */ - olen = strlen(opath); - - /* append the new segment */ - npath = curl_maprintf("%s%s%s", opath, - opath[olen-1] == '/' ? "" : "/", - apath); - if(npath) { - /* set the new path */ - curl_url_set(uh, CURLUPART_PATH, npath, 0); + if(first_lap) { + /* append path segments */ + for(p = o->append_path; p; p = p->next) { + char *apath = p->data; + char *opath; + char *npath; + size_t olen; + /* extract the current path */ + if(curl_url_get(uh, CURLUPART_PATH, &opath, 0)) + errorf(o, ERROR_ITER, "out of memory"); + + /* does the existing path end with a slash, then don't + add one in between */ + olen = strlen(opath); + + /* append the new segment */ + npath = curl_maprintf("%s%s%s", opath, + opath[olen-1] == '/' ? "" : "/", + apath); + if(npath) { + /* set the new path */ + if(curl_url_set(uh, CURLUPART_PATH, npath, 0)) + errorf(o, ERROR_ITER, "out of memory"); + } + curl_free(npath); + curl_free(opath); } - curl_free(npath); - curl_free(opath); } extractqpairs(uh, o); @@ -1477,10 +1540,12 @@ /* replace parts */ replace(o); - /* append query segments */ - for(p = o->append_query; p; p = p->next) { - addqpair(p->data, strlen(p->data), o->jsonout); - query_is_modified = true; + if(first_lap) { + /* append query segments */ + for(p = o->append_query; p; p = p->next) { + addqpair(p->data, strlen(p->data), o->jsonout); + query_is_modified = true; + } } sortquery(o); @@ -1549,6 +1614,7 @@ o->urls++; + first_lap = false; } while(iinfo->ptr); if(!iinfo->uh) curl_url_cleanup(uh); @@ -1567,8 +1633,12 @@ bool usedarg = false; if(!o.end_of_options && argv[0][0] == '-') { /* dash-dash prefixed */ - if(getarg(&o, argv[0], argv[1], &usedarg)) - errorf(&o, ERROR_FLAG, "unknown option: %s", argv[0]); + if(getarg(&o, argv[0], argv[1], &usedarg)) { + /* if the long option ends with an equals sign, cut it there, + if it is a short option, show just two letters */ + size_t not_e = argv[0][1] == '-' ? strcspn(argv[0], "=") : 2; + errorf(&o, ERROR_FLAG, "unknown option: %.*s", (int)not_e, argv[0]); + } } else { /* this is a URL */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/trurl-trurl-0.12/version.h new/trurl-trurl-0.13/version.h --- old/trurl-trurl-0.12/version.h 2024-04-18 22:13:05.000000000 +0200 +++ new/trurl-trurl-0.13/version.h 2024-05-15 08:23:20.000000000 +0200 @@ -24,6 +24,6 @@ * ***************************************************************************/ -#define TRURL_VERSION_TXT "0.12" +#define TRURL_VERSION_TXT "0.13" #endif