- diff --git a/cygwin/utils/mount_sshnfs/mount_sshnfs.ksh b/cygwin/utils/mount_sshnfs/mount_sshnfs.ksh
- index c1dc4b5..be96ec0 100644
- --- a/cygwin/utils/mount_sshnfs/mount_sshnfs.ksh
- +++ b/cygwin/utils/mount_sshnfs/mount_sshnfs.ksh
- @@ -240,6 +240,16 @@ function netstat_find_next_free_local_tcp_port
- }
- +function urldecodestr
- +{
- + nameref out=$1
- + typeset s="$2"
- + s="${s//$'\\'/$'\\\\'}"
- + s="${s//+/ }"
- + out="${ printf "${s//~(E)(?:%([[:xdigit:]][[:xdigit:]]))/\\x}" ; }"
- + return 0
- +}
- +
- #
- # parse_rfc1738_url - parse RFC 1838 URLs
- #
- @@ -253,6 +263,7 @@ function parse_rfc1738_url
- typeset url="$2"
- typeset leftover
- nameref data="$1" # output compound variable
- + typeset url_param_str
- # ~(E) is POSIX extended regular expression matching (instead
- # of shell pattern), "x" means "multiline", "l" means "left
- @@ -271,7 +282,9 @@ function parse_rfc1738_url
- (?::([[:digit:]]+))? # port (optional)
- )
- )
- - (?:\/(.*?))?/X}" # path (optional)
- + (?:\/(.*?))? # path (optional)
- + (?:\?(.*?))? # URL parameters (optional)
- + /X}"
- # All parsed data should be captured via eregex in .sh.match - if
- # there is anything left (except the 'X') then the input string did
- @@ -291,8 +304,34 @@ function parse_rfc1738_url
- [[ "${.sh.match[7]-}" != '' ]] && integer data.port="${.sh.match[7]}"
- [[ "${.sh.match[8]-}" != '' ]] && data.uripath="${.sh.match[8]}"
- + if [[ "${.sh.match[9]-}" != '' ]] ; then
- + compound -a data.parameters
- +
- + url_param_str="${.sh.match[9]-}"
- +
- + while [[ "$url_param_str" != '' ]] ; do
- + leftover="${url_param_str/~(Elrx)(?:(.+?)(?:=(.+?))?)(?:&(.*))?/X}"
- +
- + # save matches because urldecodestr uses .sh.match, too
- + typeset dp_name
- + typeset dp_value
- + typeset dp_next="${.sh.match[3]-}"
- +
- + urldecodestr dp_name "${.sh.match[1]-}"
- + urldecodestr dp_value "${.sh.match[1]-}"
- +
- + data.parameters+=(
- + name="${dp_name}"
- + value="${dp_value}"
- + )
- +
- + # next parameter
- + url_param_str="${dp_next}"
- + done
- + fi
- +
- if [[ -v data.uripath ]] ; then
- - data.path="${ printf "${data.uripath//~(E)(?:%([[:xdigit:]][[:xdigit:]]))/\\x}" ; }"
- + urldecodestr data.path "${data.uripath}"
- fi
- return 0
- @@ -367,7 +406,7 @@ function cmd_mount
- # fixme: Need better text layout for $ mount_sshnfs mount --man #
- typeset -r mount_sshnfs_cmdmount_usage=$'+
- - [-?\n@(#)\$Id: mount_sshnfs mount (Roland Mainz) 2024-01-31 \$\n]
- + [-?\n@(#)\$Id: mount_sshnfs mount (Roland Mainz) 2024-07-08 \$\n]
- [-author?Roland Mainz <roland.mainz@nrubsig.org>]
- [+NAME?mount_sshnfs mount - mount NFSv4 filesystem through ssh
- tunnel]
- @@ -733,7 +772,7 @@ function cmd_umount
- typeset mydebug=false # fixme: should be "bool" for ksh93v
- # fixme: Need better text layout for $ mount_sshnfs mount --man #
- typeset -r mount_sshnfs_cmdumount_usage=$'+
- - [-?\n@(#)\$Id: mount_sshnfs umount (Roland Mainz) 2024-01-31 \$\n]
- + [-?\n@(#)\$Id: mount_sshnfs umount (Roland Mainz) 2024-07-08 \$\n]
- [-author?Roland Mainz <roland.mainz@nrubsig.org>]
- [+NAME?mount_sshnfs umount - unmount NFSv4 filesystem mounted
- via mount_sshnfs mount]
- @@ -837,7 +876,7 @@ function main
- # fixme: Need better text layout for $ mount_sshnfs --man #
- typeset -r mount_sshnfs_usage=$'+
- - [-?\n@(#)\$Id: mount_sshnfs (Roland Mainz) 2024-01-31 \$\n]
- + [-?\n@(#)\$Id: mount_sshnfs (Roland Mainz) 2024-07-08 \$\n]
- [-author?Roland Mainz <roland.mainz@nrubsig.org>]
- [+NAME?mount_sshnfs - mount/umount NFSv4 filesystem via ssh
- tunnel]
- diff --git a/cygwin/utils/nfsurlconv/nfsurlconv.ksh b/cygwin/utils/nfsurlconv/nfsurlconv.ksh
- index 97db401..1a28bfe 100644
- --- a/cygwin/utils/nfsurlconv/nfsurlconv.ksh
- +++ b/cygwin/utils/nfsurlconv/nfsurlconv.ksh
- @@ -38,6 +38,16 @@ function usage
- return 2
- }
- +function urldecodestr
- +{
- + nameref out=$1
- + typeset s="$2"
- + s="${s//$'\\'/$'\\\\'}"
- + s="${s//+/ }"
- + out="${ printf "${s//~(E)(?:%([[:xdigit:]][[:xdigit:]]))/\\x}" ; }"
- + return 0
- +}
- +
- #
- # parse_rfc1738_url - parse RFC 1838 URLs
- #
- @@ -51,6 +61,7 @@ function parse_rfc1738_url
- typeset url="$2"
- typeset leftover
- nameref data="$1" # output compound variable
- + typeset url_param_str
- # ~(E) is POSIX extended regular expression matching (instead
- # of shell pattern), "x" means "multiline", "l" means "left
- @@ -69,7 +80,9 @@ function parse_rfc1738_url
- (?::([[:digit:]]+))? # port (optional)
- )
- )
- - (?:\/(.*?))?/X}" # path (optional)
- + (?:\/(.*?))? # path (optional)
- + (?:\?(.*?))? # URL parameters (optional)
- + /X}"
- # All parsed data should be captured via eregex in .sh.match - if
- # there is anything left (except the 'X') then the input string did
- @@ -89,8 +102,34 @@ function parse_rfc1738_url
- [[ "${.sh.match[7]-}" != '' ]] && integer data.port="${.sh.match[7]}"
- [[ "${.sh.match[8]-}" != '' ]] && data.uripath="${.sh.match[8]}"
- + if [[ "${.sh.match[9]-}" != '' ]] ; then
- + compound -a data.parameters
- +
- + url_param_str="${.sh.match[9]-}"
- +
- + while [[ "$url_param_str" != '' ]] ; do
- + leftover="${url_param_str/~(Elrx)(?:(.+?)(?:=(.+?))?)(?:&(.*))?/X}"
- +
- + # save matches because urldecodestr uses .sh.match, too
- + typeset dp_name
- + typeset dp_value
- + typeset dp_next="${.sh.match[3]-}"
- +
- + urldecodestr dp_name "${.sh.match[1]-}"
- + urldecodestr dp_value "${.sh.match[1]-}"
- +
- + data.parameters+=(
- + name="${dp_name}"
- + value="${dp_value}"
- + )
- +
- + # next parameter
- + url_param_str="${dp_next}"
- + done
- + fi
- +
- if [[ -v data.uripath ]] ; then
- - data.path="${ printf "${data.uripath//~(E)(?:%([[:xdigit:]][[:xdigit:]]))/\\x}" ; }"
- + urldecodestr data.path "${data.uripath}"
- fi
- return 0
- @@ -207,7 +246,7 @@ function main
- # fixme: Need better text layout for $ nfsurlconv --man #
- typeset -r nfsurlconv_usage=$'+
- - [-?\n@(#)\$Id: nfsurlconv (Roland Mainz) 2024-01-31 \$\n]
- + [-?\n@(#)\$Id: nfsurlconv (Roland Mainz) 2024-07-08 \$\n]
- [-author?Roland Mainz <roland.mainz@nrubsig.org>]
- [+NAME?nfsurlconv - convert hostname,port,path from/to a nfs://-URL]
- [+DESCRIPTION?\bnfsurlconv\b convert { hostname, port, path } from/to a nfs://-URL.]
- @@ -238,6 +277,14 @@ path=/a/b/c
- hostport=bbb
- path=/a/b/c
- ]
- +}
- + [+?Example 4:][+?Convert URL nfs://bbb:12049//a/b/c?param1=pvalue1¶m2=pvalue2 to ( hostport=, path=, urlparameter= )]{
- +[+\n$ nfsurlconv.ksh url2hostportpath "nfs:://bbb::12049//a/b/c??param1=pvalue1¶m2=pvalue2"
- +hostport=bbb::12049
- +path=/a/b/c
- +urlparameter=( name=param1 value=pvalue1 )
- +urlparameter=( name=param2 value=pvalue2 )
- +]
- }
- }
- [+SEE ALSO?\bksh93\b(1),\bssh\b(1),\bmount.nfs\b(8),\bnfs\b(5)]
- @@ -299,6 +346,13 @@ path=/a/b/c
- printf 'hostname=%s\n' "${urldata.host}"
- printf 'port=%s\n' "${urldata.port-2049}"
- printf 'path=%s\n' "${urldata.path-}"
- + if [[ -v urldata.parameters ]] ; then
- + for (( i=0 ; i < ${#urldata.parameters[@]} ; i++ )) ; do
- + printf 'urlparameter=( name=%q value=%q )\n' \
- + "${urldata.parameters[i].name}" \
- + "${urldata.parameters[i].value}"
- + done
- + fi
- return 0
- ;;
- 'url2hostportpath')
- @@ -307,6 +361,13 @@ path=/a/b/c
- parse_sshnfs_url urldata "${@:2:1}" || return 1
- printf 'hostport=%s\n' "${urldata.hostport}"
- printf 'path=%s\n' "${urldata.path-}"
- + if [[ -v urldata.parameters ]] ; then
- + for (( i=0 ; i < ${#urldata.parameters[@]} ; i++ )) ; do
- + printf 'urlparameter=( name=%q value=%q )\n' \
- + "${urldata.parameters[i].name}" \
- + "${urldata.parameters[i].value}"
- + done
- + fi
- return 0
- ;;
- 'url2compound')
- diff --git a/cygwin/utils/sshnfs/sshnfs.ksh b/cygwin/utils/sshnfs/sshnfs.ksh
- index bfccabb..21d08f0 100644
- --- a/cygwin/utils/sshnfs/sshnfs.ksh
- +++ b/cygwin/utils/sshnfs/sshnfs.ksh
- @@ -222,6 +222,16 @@ function netstat_find_next_free_local_tcp_port
- }
- +function urldecodestr
- +{
- + nameref out=$1
- + typeset s="$2"
- + s="${s//$'\\'/$'\\\\'}"
- + s="${s//+/ }"
- + out="${ printf "${s//~(E)(?:%([[:xdigit:]][[:xdigit:]]))/\\x}" ; }"
- + return 0
- +}
- +
- #
- # parse_rfc1738_url - parse RFC 1838 URLs
- #
- @@ -235,6 +245,7 @@ function parse_rfc1738_url
- typeset url="$2"
- typeset leftover
- nameref data="$1" # output compound variable
- + typeset url_param_str
- # ~(E) is POSIX extended regular expression matching (instead
- # of shell pattern), "x" means "multiline", "l" means "left
- @@ -253,7 +264,9 @@ function parse_rfc1738_url
- (?::([[:digit:]]+))? # port (optional)
- )
- )
- - (?:\/(.*?))?/X}" # path (optional)
- + (?:\/(.*?))? # path (optional)
- + (?:\?(.*?))? # URL parameters (optional)
- + /X}"
- # All parsed data should be captured via eregex in .sh.match - if
- # there is anything left (except the 'X') then the input string did
- @@ -273,8 +286,34 @@ function parse_rfc1738_url
- [[ "${.sh.match[7]-}" != '' ]] && integer data.port="${.sh.match[7]}"
- [[ "${.sh.match[8]-}" != '' ]] && data.uripath="${.sh.match[8]}"
- + if [[ "${.sh.match[9]-}" != '' ]] ; then
- + compound -a data.parameters
- +
- + url_param_str="${.sh.match[9]-}"
- +
- + while [[ "$url_param_str" != '' ]] ; do
- + leftover="${url_param_str/~(Elrx)(?:(.+?)(?:=(.+?))?)(?:&(.*))?/X}"
- +
- + # save matches because urldecodestr uses .sh.match, too
- + typeset dp_name
- + typeset dp_value
- + typeset dp_next="${.sh.match[3]-}"
- +
- + urldecodestr dp_name "${.sh.match[1]-}"
- + urldecodestr dp_value "${.sh.match[1]-}"
- +
- + data.parameters+=(
- + name="${dp_name}"
- + value="${dp_value}"
- + )
- +
- + # next parameter
- + url_param_str="${dp_next}"
- + done
- + fi
- +
- if [[ -v data.uripath ]] ; then
- - data.path="${ printf "${data.uripath//~(E)(?:%([[:xdigit:]][[:xdigit:]]))/\\x}" ; }"
- + urldecodestr data.path "${data.uripath}"
- fi
- return 0
- diff --git a/mount/mount.c b/mount/mount.c
- index 67b011a..06a0c35 100644
- --- a/mount/mount.c
- +++ b/mount/mount.c
- @@ -71,6 +71,7 @@ static VOID PrintUsage(LPTSTR pProcess)
- {
- (void)_tprintf(
- TEXT("Usage: %s [options] <drive letter|*> <hostname>:<path>\n")
- +
- TEXT("* Options:\n")
- TEXT("\t-h\thelp\n")
- TEXT("\t/?\thelp\n")
- @@ -82,6 +83,7 @@ static VOID PrintUsage(LPTSTR pProcess)
- " (Linux compat)\n")
- TEXT("\t-p\tmake the mount persist over reboots\n")
- TEXT("\t-o <comma-separated mount options>\n")
- +
- TEXT("* Mount options:\n")
- TEXT("\tro\tmount as read-only\n")
- TEXT("\trw\tmount as read-write (default)\n")
- @@ -100,23 +102,33 @@ static VOID PrintUsage(LPTSTR pProcess)
- "\t\tif this value is prefixed with 'nfsv3attrmode+'\n"
- "\t\tthe mode value from a \"NfsV3Attributes\" EA will be used\n"
- "\t\t(defaults \"nfsv3attrmode+0o%o\").\n")
- +
- + TEXT("* URL parameters:\n")
- + TEXT("\tro=1\tmount as read-only\n")
- + TEXT("\trw=1\tmount as read-write (default)\n")
- +
- TEXT("* Hostname:\n")
- TEXT("\tDNS name, or hostname in domain\n")
- TEXT("\tentry in C:\\Windows\\System32\\drivers\\etc\\hosts\n")
- TEXT("\tIPv4 address\n")
- TEXT("\tIPv6 address within '[', ']' "
- "(will be converted to *.ipv6-literal.net)\n")
- +
- TEXT("* Examples:\n")
- TEXT("\tnfs_mount.exe -p -o rw 'H' derfwpc5131_ipv4:/export/home2/rmainz\n")
- TEXT("\tnfs_mount.exe -o rw '*' bigramhost:/tmp\n")
- + TEXT("\tnfs_mount.exe -o ro '*' archive1:/tmp\n")
- + TEXT("\tnfs_mount.exe '*' archive1:/tmp?ro=1\n")
- TEXT("\tnfs_mount.exe -o rw,sec=sys,port=30000 T grendel:/net_tmpfs2\n")
- TEXT("\tnfs_mount.exe -o sec=sys,rw S nfs://myhost1//net_tmpfs2/test2\n")
- + TEXT("\tnfs_mount.exe -o sec=sys S nfs://myhost1//net_tmpfs2/test2?rw=1\n")
- TEXT("\tnfs_mount.exe -o sec=sys,rw S nfs://myhost1:1234//net_tmpfs2/test2\n")
- TEXT("\tnfs_mount.exe -o sec=sys,rw,port=1234 S nfs://myhost1//net_tmpfs2/test2\n")
- TEXT("\tnfs_mount.exe -o sec=sys,rw '*' [fe80::21b:1bff:fec3:7713]://net_tmpfs2/test2\n")
- TEXT("\tnfs_mount.exe -o sec=sys,rw '*' nfs://[fe80::21b:1bff:fec3:7713]//net_tmpfs2/test2\n")
- TEXT("\tnfs_mount.exe -o sec=sys,rw S nfs://myhost1//dirwithspace/dir%%20space/test2\n")
- - TEXT("\tnfs_mount.exe -o sec=sys,rw S nfs://myhost1//dirwithspace/dir+space/test2\n"),
- + TEXT("\tnfs_mount.exe -o sec=sys,rw S nfs://myhost1//dirwithspace/dir+space/test2\n")
- + TEXT("\tnfs_mount.exe -o sec=sys S nfs://myhost1//dirwithspace/dir+space/test2?rw=1\n"),
- pProcess, (int)NFS41_DRIVER_DEFAULT_CREATE_MODE);
- }
- @@ -404,6 +416,65 @@ static DWORD ParseRemoteName(
- goto out;
- }
- + if (uctx->num_parameters > 0) {
- + int pi;
- + const char *pname;
- + const char *pvalue;
- +
- + /*
- + * FIXME: Values added here based on URL parameters
- + * should be added at the front of the list of options,
- + * so users can override the nfs://-URL given default.
- + * Right now this does not work, e.g.
- + * $ nfs_mount.exe -o rw nfs://foo//bar?ro=1 # will
- + * result in a read-only mount, while the expectation
- + * is that -o overrides URL settings.
- + */
- + for (pi = 0; pi < uctx->num_parameters ; pi++) {
- + pname = uctx->parameters[pi].name;
- + pvalue = uctx->parameters[pi].value;
- +
- + if (!strcmp(pname, "rw")) {
- + if ((pvalue == NULL) || (!strcmp(pvalue, "1"))) {
- + (void)InsertOption(TEXT("rw"), TEXT("1"), pOptions);
- + }
- + else if (!strcmp(pvalue, "0")) {
- + (void)InsertOption(TEXT("ro"), TEXT("1"), pOptions);
- + }
- + else {
- + result = ERROR_BAD_ARGUMENTS;
- + (void)_ftprintf(stderr,
- + TEXT("Unsupported nfs://-URL parameter ")
- + TEXT("'%S' value '%S'.\n"),
- + pname, pvalue);
- + goto out;
- + }
- + }
- + else if (!strcmp(pname, "ro")) {
- + if ((pvalue == NULL) || (!strcmp(pvalue, "1"))) {
- + (void)InsertOption(TEXT("ro"), TEXT("1"), pOptions);
- + }
- + else if (!strcmp(pvalue, "0")) {
- + (void)InsertOption(TEXT("rw"), TEXT("1"), pOptions);
- + }
- + else {
- + result = ERROR_BAD_ARGUMENTS;
- + (void)_ftprintf(stderr,
- + TEXT("Unsupported nfs://-URL parameter ")
- + TEXT("'%S' value '%S'.\n"),
- + pname, pvalue);
- + goto out;
- + }
- + }
- + else {
- + result = ERROR_BAD_ARGUMENTS;
- + (void)_ftprintf(stderr,
- + TEXT("Unsupported nfs://-URL parameter '%S'.\n"), pname);
- + goto out;
- + }
- + }
- + }
- +
- if (uctx->hostport.port != -1)
- port = uctx->hostport.port;
- diff --git a/mount/urlparser1.c b/mount/urlparser1.c
- index a90d1e2..8fcae52 100644
- --- a/mount/urlparser1.c
- +++ b/mount/urlparser1.c
- @@ -28,10 +28,23 @@
- #include <stdlib.h>
- #include <stdbool.h>
- #include <string.h>
- +#include <ctype.h>
- #include <stdio.h>
- +// #define TEST_URLPARSER 1
- +
- #include "urlparser1.h"
- +typedef struct _url_parser_context_private {
- + url_parser_context c;
- +
- + /* Private data */
- + char *parameter_string_buff;
- +} url_parser_context_private;
- +
- +#define MAX_URL_PARAMETERS 256
- +
- +#ifdef _MSC_VER
- /*
- * Disable "warning C4996: 'wcscpy': This function or variable may be
- * unsafe." because in this case the buffers are properly sized,
- @@ -43,6 +56,7 @@
- * because it is safe to use in our code.
- */
- #pragma warning (disable : 4706)
- +#endif /* _MSC_VER */
- /*
- * Original extended regular expression:
- @@ -62,69 +76,61 @@
- * ")"
- * ")"
- * "(?:/(.*?))?" // path (optional)
- + * "(?:\?(.*?))?" // URL parameters (optional)
- * "$"
- */
- #define DBGNULLSTR(s) (((s)!=NULL)?(s):"<NULL>")
- -#if 0
- +#if 0 || defined(TEST_URLPARSER)
- #define D(x) x
- #else
- #define D(x)
- #endif
- static
- -void urldecodestr(char *dst, const char *src, size_t len)
- +void urldecodestr(char *outbuff, const char *buffer, size_t len)
- {
- - /*
- - * Unicode characters with a code point > 255 are encoded
- - * as UTF-8 bytes
- - */
- -#define isurlxdigit(c) \
- - (((c) >= '0' && (c) <= '9') || \
- - ((c) >= 'a' && (c) <= 'f') || \
- - ((c) >= 'A' && (c) <= 'F'))
- - char a, b;
- - while (*src && len--) {
- - if (len > 2) {
- - if ((*src == '%') &&
- - (a = src[1]) && (b = src[2])) {
- - if ((isurlxdigit(a) &&
- - isurlxdigit(b))) {
- - if (a >= 'a')
- - a -= 'a'-'A';
- - if (a >= 'A')
- - a -= ('A' - 10);
- - else
- - a -= '0';
- -
- - if (b >= 'a')
- - b -= 'a'-'A';
- - if (b >= 'A')
- - b -= ('A' - 10);
- - else
- - b -= '0';
- -
- - *dst++ = 16*a+b;
- -
- - src+=3;
- - len-=2;
- - continue;
- - }
- + size_t i, j;
- +
- + for (i = j = 0 ; i < len ; ) {
- + switch (buffer[i]) {
- + case '%':
- + if ((i + 2) < len) {
- + if (isxdigit((int)buffer[i+1]) && isxdigit((int)buffer[i+2])) {
- + const char hexstr[3] = {
- + buffer[i+1],
- + buffer[i+2],
- + '\0'
- + };
- + outbuff[j++] = (unsigned char)strtol(hexstr, NULL, 16);
- + i += 3;
- + } else {
- + /* invalid hex digit */
- + outbuff[j++] = buffer[i];
- + i++;
- }
- + } else {
- + /* incomplete hex digit */
- + outbuff[j++] = buffer[i];
- + i++;
- }
- - if (*src == '+') {
- - *dst++ = ' ';
- - src++;
- - continue;
- + break;
- + case '+':
- + outbuff[j++] = ' ';
- + i++;
- + break;
- + default:
- + outbuff[j++] = buffer[i++];
- + break;
- }
- - *dst++ = *src++;
- }
- - *dst++ = '\0';
- +
- + outbuff[j] = '\0';
- }
- url_parser_context *url_parser_create_context(const char *in_url, unsigned int flags)
- {
- - url_parser_context *uctx;
- + url_parser_context_private *uctx;
- char *s;
- size_t in_url_len;
- size_t context_len;
- @@ -137,30 +143,36 @@ url_parser_context *url_parser_create_context(const char *in_url, unsigned int f
- in_url_len = strlen(in_url);
- - context_len = sizeof(url_parser_context) +
- - ((in_url_len+1)*5);
- + context_len = sizeof(url_parser_context_private) +
- + ((in_url_len+1)*6) +
- + (sizeof(url_parser_name_value)*MAX_URL_PARAMETERS)+sizeof(void*);
- uctx = malloc(context_len);
- if (!uctx)
- return NULL;
- s = (void *)(uctx+1);
- - uctx->in_url = s; s+= in_url_len+1;
- - (void)strcpy(uctx->in_url, in_url);
- - uctx->scheme = s; s+= in_url_len+1;
- - uctx->login.username = s; s+= in_url_len+1;
- - uctx->hostport.hostname = s; s+= in_url_len+1;
- - uctx->path = s; s+= in_url_len+1;
- - uctx->hostport.port = -1;
- -
- - return uctx;
- + uctx->c.in_url = s; s+= in_url_len+1;
- + (void)strcpy(uctx->c.in_url, in_url);
- + uctx->c.scheme = s; s+= in_url_len+1;
- + uctx->c.login.username = s; s+= in_url_len+1;
- + uctx->c.hostport.hostname = s; s+= in_url_len+1;
- + uctx->c.path = s; s+= in_url_len+1;
- + uctx->c.hostport.port = -1;
- + uctx->c.num_parameters = -1;
- + uctx->c.parameters = (void *)s; s+= (sizeof(url_parser_name_value)*MAX_URL_PARAMETERS)+sizeof(void*);
- + uctx->parameter_string_buff = s; s+= in_url_len+1;
- +
- + return &uctx->c;
- }
- -int url_parser_parse(url_parser_context *uctx)
- +int url_parser_parse(url_parser_context *ctx)
- {
- - D((void)fprintf(stderr, "## parser in_url='%s'\n", uctx->in_url));
- + url_parser_context_private *uctx = (url_parser_context_private *)ctx;
- +
- + D((void)fprintf(stderr, "## parser in_url='%s'\n", uctx->c.in_url));
- char *s;
- - const char *urlstr = uctx->in_url;
- + const char *urlstr = uctx->c.in_url;
- size_t slen;
- s = strstr(urlstr, "://");
- @@ -170,57 +182,120 @@ int url_parser_parse(url_parser_context *uctx)
- }
- slen = s-urlstr;
- - (void)memcpy(uctx->scheme, urlstr, slen);
- - uctx->scheme[slen] = '\0';
- + (void)memcpy(uctx->c.scheme, urlstr, slen);
- + uctx->c.scheme[slen] = '\0';
- urlstr += slen + 3;
- - D((void)fprintf(stdout, "scheme='%s', rest='%s'\n", uctx->scheme, urlstr));
- + D((void)fprintf(stdout, "scheme='%s', rest='%s'\n", uctx->c.scheme, urlstr));
- s = strstr(urlstr, "@");
- if (s) {
- /* URL has user/password */
- slen = s-urlstr;
- - urldecodestr(uctx->login.username, urlstr, slen);
- + urldecodestr(uctx->c.login.username, urlstr, slen);
- urlstr += slen + 1;
- - s = strstr(uctx->login.username, ":");
- + s = strstr(uctx->c.login.username, ":");
- if (s) {
- /* found passwd */
- - uctx->login.passwd = s+1;
- + uctx->c.login.passwd = s+1;
- *s = '\0';
- }
- else
- {
- - uctx->login.passwd = NULL;
- + uctx->c.login.passwd = NULL;
- }
- /* catch password-only URLs */
- - if (uctx->login.username[0] == '\0')
- - uctx->login.username = NULL;
- + if (uctx->c.login.username[0] == '\0')
- + uctx->c.login.username = NULL;
- }
- else
- {
- - uctx->login.username = NULL;
- - uctx->login.passwd = NULL;
- + uctx->c.login.username = NULL;
- + uctx->c.login.passwd = NULL;
- }
- D((void)fprintf(stdout, "login='%s', passwd='%s', rest='%s'\n",
- - DBGNULLSTR(uctx->login.username),
- - DBGNULLSTR(uctx->login.passwd),
- + DBGNULLSTR(uctx->c.login.username),
- + DBGNULLSTR(uctx->c.login.passwd),
- DBGNULLSTR(urlstr)));
- + char *raw_parameters;
- +
- + uctx->c.num_parameters = 0;
- + raw_parameters = strstr(urlstr, "?");
- + if (raw_parameters) {
- + *raw_parameters++ = '\0';
- + D((void)fprintf(stdout, "raw parameters = '%s'\n", raw_parameters));
- +
- + char *ps = raw_parameters;
- + char *pv; /* parameter value */
- + char *na; /* next '&' */
- + char *pb = uctx->parameter_string_buff;
- + char *pname;
- + char *pvalue;
- + ssize_t pi;
- +
- + for (pi = 0; pi < MAX_URL_PARAMETERS ; pi++) {
- + pname = ps;
- +
- + /*
- + * Handle parameters without value,
- + * e.g. "path?name1&name2=value2"
- + */
- + na = strstr(ps, "&");
- + pv = strstr(ps, "=");
- + if (pv && (na?(na > pv):true)) {
- + *pv++ = '\0';
- + pvalue = pv;
- + ps = pv;
- + }
- + else {
- + pvalue = NULL;
- + }
- +
- + if (na) {
- + *na++ = '\0';
- + }
- +
- + /* URLDecode parameter name */
- + urldecodestr(pb, pname, strlen(pname));
- + uctx->c.parameters[pi].name = pb;
- + pb += strlen(uctx->c.parameters[pi].name)+1;
- +
- + /* URLDecode parameter value */
- + if (pvalue) {
- + urldecodestr(pb, pvalue, strlen(pvalue));
- + uctx->c.parameters[pi].value = pb;
- + pb += strlen(uctx->c.parameters[pi].value)+1;
- + }
- + else {
- + uctx->c.parameters[pi].value = NULL;
- + }
- +
- + /* Next '&' ? */
- + if (!na)
- + break;
- +
- + ps = na;
- + }
- +
- + uctx->c.num_parameters = pi+1;
- + }
- +
- s = strstr(urlstr, "/");
- if (s) {
- /* URL has hostport */
- slen = s-urlstr;
- - urldecodestr(uctx->hostport.hostname, urlstr, slen);
- + urldecodestr(uctx->c.hostport.hostname, urlstr, slen);
- urlstr += slen + 1;
- /*
- * check for addresses within '[' and ']', like
- * IPv6 addresses
- */
- - s = uctx->hostport.hostname;
- + s = uctx->c.hostport.hostname;
- if (s[0] == '[')
- s = strstr(s, "]");
- @@ -232,29 +307,41 @@ int url_parser_parse(url_parser_context *uctx)
- s = strstr(s, ":");
- if (s) {
- /* found port number */
- - uctx->hostport.port = atoi(s+1);
- + uctx->c.hostport.port = atoi(s+1);
- *s = '\0';
- }
- }
- else
- {
- - (void)strcpy(uctx->hostport.hostname, urlstr);
- - uctx->path = NULL;
- + (void)strcpy(uctx->c.hostport.hostname, urlstr);
- + uctx->c.path = NULL;
- urlstr = NULL;
- }
- - D((void)fprintf(stdout, "hostport='%s', port=%d, rest='%s'\n",
- - DBGNULLSTR(uctx->hostport.hostname),
- - uctx->hostport.port,
- - DBGNULLSTR(urlstr)));
- + D((void)fprintf(stdout, "hostport='%s', port=%d, rest='%s', num_parameters=%d\n",
- + DBGNULLSTR(uctx->c.hostport.hostname),
- + uctx->c.hostport.port,
- + DBGNULLSTR(urlstr),
- + (int)uctx->c.num_parameters));
- +
- + D(
- + ssize_t dpi;
- + for (dpi = 0 ; dpi < uctx->c.num_parameters ; dpi++) {
- + (void)fprintf(stdout, "param[%d]: name='%s'/value='%s'\n",
- + (int)dpi,
- + uctx->c.parameters[dpi].name,
- + DBGNULLSTR(uctx->c.parameters[dpi].value));
- + }
- + );
- if (!urlstr) {
- - return 0;
- + goto done;
- }
- - urldecodestr(uctx->path, urlstr, strlen(urlstr));
- - D((void)fprintf(stdout, "path='%s'\n", uctx->path));
- + urldecodestr(uctx->c.path, urlstr, strlen(urlstr));
- + D((void)fprintf(stdout, "path='%s'\n", uctx->c.path));
- +done:
- return 0;
- }
- @@ -301,7 +388,16 @@ int main(int ac, char *av[])
- (void)test_url_parser("nfs://hostbar:93//absolutepath/a");
- (void)test_url_parser("nfs://hostbar:93//absolutepath/blank%20path/a");
- (void)test_url_parser("nfs://hostbar:93//absolutepath/blank+path/a");
- -
- + (void)test_url_parser("foo://hostbar:93?param1");
- + (void)test_url_parser("foo://hostbar:93?pname1=pvalue1");
- + (void)test_url_parser("foo://hostbar:93?pname1=pvalue1&pname2=pvalue2");
- + (void)test_url_parser("foo://hostbar:93?pname1=pvalue1&pvalue2=v2&n3=v3");
- + (void)test_url_parser("foo://hostbar:93?pname1¶m2=p2");
- + (void)test_url_parser("foo://hostbar:93?pname1=¶m2=p2");
- + (void)test_url_parser("foo://hostbar:93//path/path2?param1=p1");
- + (void)test_url_parser("foo://hostbar:93//path/path2?param1¶m2=p2");
- + (void)test_url_parser("foo://hostbar:93?pname1=pvalue1&%E2%82%AC=u+n2&n3=v3");
- + (void)test_url_parser("foo://hostbar:93?pname1=pvalue1&%E2%82%AC=%E2%82%AC&n3=v3");
- (void)test_url_parser("foo://");
- (void)test_url_parser("typo:/hostbar");
- diff --git a/mount/urlparser1.h b/mount/urlparser1.h
- index 8ed0f91..4526f1c 100644
- --- a/mount/urlparser1.h
- +++ b/mount/urlparser1.h
- @@ -26,8 +26,16 @@
- #include <stdlib.h>
- -typedef
- -struct _url_parser_context {
- +#ifdef _MSC_VER
- +typedef signed long long ssize_t;
- +#endif
- +
- +typedef struct _url_parser_name_value {
- + char *name;
- + char *value;
- +} url_parser_name_value;
- +
- +typedef struct _url_parser_context {
- char *in_url;
- char *scheme;
- @@ -40,6 +48,9 @@ struct _url_parser_context {
- signed int port;
- } hostport;
- char *path;
- +
- + ssize_t num_parameters;
- + url_parser_name_value *parameters;
- } url_parser_context;
- /* Prototypes */
URL parameter work backup 2024-07-08
Posted by Anonymous on Mon 8th Jul 2024 17:43
raw | new post
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.