home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2007 January, February, March & April
/
Chip-Cover-CD-2007-02.iso
/
boot
/
i386
/
root
/
usr
/
share
/
YaST2
/
modules
/
URL.ycp
< prev
next >
Wrap
Text File
|
2006-11-29
|
9KB
|
355 lines
/**
* File: modules/URL.ycp
* Package: yast2
* Summary: Manipulate and Parse URLs
* Authors: Michal Svec <msvec@suse.cz>
* Anas Nashif <nashif@suse.cz>
* Flags: Stable
*
* $Id: URL.ycp 31472 2006-06-13 11:31:49Z jsrain $
*/
{
module "URL";
textdomain "base";
import "Hostname";
import "String";
import "IP";
/**
* TODO:
* - read URI(3)
* - esp. compare the regex mentioned in the URI(3) with ours:
* my($scheme, $authority, $path, $query, $fragment) =
* $uri =~ m|^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?|;
*/
/**
* Valid characters in URL
*/
global string ValidChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:_-/%";
/**
* Transform map used for (un)escaping characters in username/password part of an URL.
* It doesn't contain '%' because this character must be used in a particular
* order (the first or the last) during processing
*/
global map<string, string> transform_map_passwd = $[
";":"%3b",
"/":"%2f",
"?":"%3f",
":":"%3a",
"@":"%40",
"&":"%26",
"=":"%3d",
"+":"%2b",
"$":"%24",
",":"%2c",
" ":"%20"
];
/**
* Transform map used for (un)escaping characters in file location part of an URL.
* It doesn't contain '%' because this character must be used in a particular
* order (the first or the last) during processing
*/
global map<string, string> transform_map_filename = $[
";":"%3b",
"?":"%3f",
":":"%3a",
"@":"%40",
"&":"%26",
"=":"%3d",
"+":"%2b",
"$":"%24",
",":"%2c",
" ":"%20"
];
/**
* Transform map used for (un)escaping characters in query part of a URL.
* It doesn't contain '%' because this character must be used in a particular
* order (the first or the last) during processing
*/
global map<string, string> transform_map_query = $[
";":"%3b",
"?":"%3f",
"@":"%40",
"+":"%2b",
"$":"%24",
",":"%2c",
" ":"%20"
];
/**
* Escape reserved characters in string used as a part of URL (e.g. '%' => '%25', '@' => '%40'...)
*
* @param in input string to escape
* @return string escaped string
*/
global string UnEscapeString(string in, map<string,string> transform) {
if (in == nil || in == "")
{
return "";
}
// replace the other reserved characters
foreach(string tgt, string src, transform, {
// replace both upper and lower case escape sequences
in = String::Replace(in, tolower(src), tgt);
in = String::Replace(in, toupper(src), tgt);
}
);
// replace % at the end
in = String::Replace(in, "%25", "%");
return in;
}
/**
* Escape reserved characters in string used as a part of URL (e.g. '%' => '%25', '@' => '%40'...)
*
* @param in input string to escape
* @return string escaped string
*/
global string EscapeString(string in, map<string,string> transform) {
string ret = "";
if (in == nil || in == "")
{
return ret;
}
// replace % at first
ret = mergestring(splitstring(in, "%"), "%25");
// replace the other reserved characters
foreach(string src, string tgt, transform, {
ret = mergestring(splitstring(ret, src), tgt);
}
);
return ret;
}
/**
* Tokenize URL
* @param url URL to be parsed
* @return URL split to tokens
* @example Parse("http://name:pass@www.suse.cz:80/path/index.html?question#part") ->
* $[
* "scheme" : "http",
* "host" : "www.suse.cz"
* "port" : "80",
* "path" : /path/index.html",
* "user" : "name",
* "pass" : "pass",
* "query" : "question",
* "fragment": "part"
* ]
*/
global define map Parse(string url) ``{
y2debug("url=%1", url);
/* We don't parse empty URLs */
if(url == nil || size(url) < 1) return $[];
/* Extract basic URL parts: scheme://host/path?question#part */
list rawtokens = regexptokenize(url, "^" +
/* 0,1: http:// */
"(([^:/?#]+)://)?" +
/* 2: user:pass@www.suse.cz:23 */
"([^/?#]*)?" +
/* 3: /some/path */
"([^?#]*)?" +
/* 4,5: ?question */
"(\\?([^#]*))?" +
/* 6,7: #fragment */
"(#(.*))?"
);
y2debug("rawtokens=%1", rawtokens);
map tokens = $[];
tokens["scheme"] = rawtokens[1]:"";
string pth = rawtokens[3]:"";
if (tokens["scheme"]:"" == "ftp")
{
if (substring (pth, 0, 4) == "/%2f")
{
pth = "/" + substring (pth, 4);
}
else
{
pth = substring (pth, 1);
}
}
tokens["path"] = UnEscapeString(pth, transform_map_filename);
tokens["query"] = UnEscapeString(rawtokens[5]:"", transform_map_query);
tokens["fragment"] = UnEscapeString(rawtokens[7]:"", transform_map_passwd);
/* Extract username:pass@host:port */
list userpass = regexptokenize(rawtokens[2]:"", "^" +
/* 0,1,2,3: user:pass@ */
"(([^@:]+)(:([^@:]+))?@)?" +
/* 4,5,6,7: hostname|[xxx] */
"(([^:@]+))" +
// FIXME "(([^:@]+)|(\\[([^]]+)\\]))" +
/* 8,9: port */
"(:([^:@]+))?"
);
y2debug("userpass=%1", userpass);
tokens["user"] = UnEscapeString(userpass[1]:"", transform_map_passwd);
tokens["pass"] = UnEscapeString(userpass[3]:"", transform_map_passwd);
tokens["port"] = userpass[7]:"";
if(userpass[5]:"" != "")
tokens["host"] = userpass[5]:"";
else
tokens["host"] = userpass[7]:"";
y2debug("tokens=%1", tokens);
return tokens;
}
/**
* Check URL
* @param url URL to be checked
* @return true if correct
* @see RFC 2396 (updated by RFC 2732)
* @see also perl-URI: URI(3)
*/
global define boolean Check(string url) ``{
/* We don't allow empty URLs */
if(url == nil || size(url) < 1) return false;
/* We don't allow URLs with spaces */
if(find(url, " ") != -1) return false;
map tokens = Parse(url);
/* Check "scheme" : "http" */
if(!regexpmatch(tokens["scheme"]:"", "^[a-z]*$"))
return false;
/* Check "host" : "www.suse.cz" */
if((!Hostname::CheckFQ(tokens["host"]:"") && !IP::Check(tokens["host"]:""))
&& tokens["host"]:"" != "")
return false;
/* Check "path" : /path/index.html" */
/* Check "port" : "80" */
if(!regexpmatch(tokens["port"]:"", "^[0-9]*$"))
return false;
/* Check "user" : "name" */
/* Check "pass" : "pass" */
/* Check "query" : "question" */
/* Check "fragment": "part" */
return true;
}
/**
* Build URL from tokens as parsed with Parse
* @param map token as returned from Parse
* @return string url, empty string if invalid data is used to build the url.
* @see RFC 2396 (updated by RFC 2732)
* @see also perl-URI: URI(3)
*/
global define string Build (map tokens) ``{
string url = "";
string userpass = "";
if(regexpmatch(tokens["scheme"]:"", "^[a-z]*$"))
{
url = tokens["scheme"]:"";
}
y2debug("url: %1", url);
if (tokens["user"]:"" != "")
{
userpass = EscapeString(tokens["user"]:"", transform_map_passwd);
y2milestone("Escaped username '%1' => '%2'", tokens["user"]:"", userpass);
}
if (size(userpass) != 0 && tokens["pass"]:"" != "" )
{
userpass = sformat("%1:%2", userpass, EscapeString(tokens["pass"]:"", transform_map_passwd) );
}
if (size(userpass) > 0 )
userpass = userpass + "@";
url = sformat("%1://%2", url, userpass);
y2debug("url: %1", url);
if(Hostname::CheckFQ(tokens["host"]:"") || IP::Check(tokens["host"]:""))
{
url = sformat("%1%2", url, tokens["host"]:"");
}
y2debug("url: %1", url);
if (regexpmatch(tokens["port"]:"", "^[0-9]*$") && tokens["port"]:"" != "")
{
url = sformat("%1:%2", url, tokens["port"]:"");
}
y2debug("url: %1", url);
if (tokens["path"]:"" != "" && find (tokens["path"]:"", "/") != 0 )
url = sformat("%1/%2", url, EscapeString(tokens["path"]:"", transform_map_filename));
else if (tokens["path"]:"" != "" && find (tokens["path"]:"", "/") == 0 )
{
if (tokens["scheme"]:"" == "ftp") {
url = sformat("%1/%%2f%2", url, substring(EscapeString(tokens["path"]:"", transform_map_filename), 1));
}
else {
url = sformat("%1%2", url, EscapeString(tokens["path"]:"", transform_map_filename));
}
}
y2debug("url: %1", url);
if (tokens["query"]:"" != "" )
url = sformat("%1?%2", url, EscapeString(tokens["query"]:"", transform_map_query));
if (tokens["fragment"]:"" != "" )
url = sformat("%1#%2", url, EscapeString(tokens["fragment"]:"", transform_map_passwd));
y2debug("url: %1", url);
if (!Check(url)) {
y2error("Invalid URL: %1", url);
return "";
}
return url;
}
/*
y2milestone("%1", Parse("http://a:b@www.suse.cz:33/ahoj/nekde?neco#blah"));
y2milestone("%1", Parse("ftp://www.suse.cz/ah"));
y2milestone("%1", Parse("ftp://www.suse.cz:22/ah"));
y2milestone("%1", Parse("www.suse.cz/ah"));
y2milestone("%1", Check("http://a:b@www.suse.cz:33/ahoj/nekde?neco#blah"));
y2milestone("%1", Check("ftp://www.suse.cz/ah"));
y2milestone("%1", Check("ftp://www.suse.cz:22/ah"));
y2milestone("%1", Check("www.suse.cz/ah"));
y2milestone("%1", Check("www.suse.cz ah"));
y2milestone("%1", Check(""));
y2milestone("%1", Check(nil));
*/
}