Эта тема на forum.dklab.ru


Rumata: Разбор и валидация URL и DSN
DSN (Data Source Name) структурно похож на URL (наиболее полная информация доступна на странице http://pear.php.net/manual/en/package.database.db.intro-dsn.php).
Мне понадобилось совместить обработку и валидацию этих источников, при чем опционально необходимо разбирать и query string. Хост может быть задан как IP-адрес или имя, допустимо зарезервированное имя localhost.
Полагаю, что подобная работа уже проделана, но искать было лень. Не претендует на универсальность (достаточно вспомнить проблемы валидации email-адресов), но в большинстве случаев работает.
Если модераториат посчитает что не место на складе, можно перенести в более подходящее место.

Кратко.
Структура URL - protocol://user:password@host:port/path?query#fragment
Структура DSN - scheme:subscheme://user:password@host:port/path?query#fragment


# Tries the first parameter as a DSN or an URL and returns separate parts as hash in success.
# The second parameter defines should we parse a query string into separate parts or return as single string.
#
# @param string $dsn
# @param boolean $parse_query
# @return hash
sub parseDSN
{
my $dsn = shift;
my $parse_query = shift;

$dsn =~ /
\s*
(?:
# scheme:subscheme:\/\/
([a-z]+) : (?: ([a-z]*) : )? \/\/
)?
(?:
# username:password@
( [^:@]* ) (?: : ([^:@]*) )? @
)?
(
# hostname|localhost|IP
(?: [a-z0-9_-]+ \. )+ [a-z]{2,}
|
localhost
|
(?: (?: [01]?\d\d? | 2[0-4]\d | 25[0-5] ) \. ){3}
(?: (?: [01]?\d\d? | 2[0-4]\d | 25[0-5] ) )
)
(?:
# :port
: (\d+)
)?
(?:
# \/path
([^:\?\#]+)
)?
(?:
# ?query
\? ([^\#]+)
)?
(?:
# #fragment
\# ([^\s]+)
)?
\s*
/ix;

return () unless defined $5;

my %result = (
scheme => $1 || '',
subscheme => $2 || '',
user => $3 || '',
pass => $4 || '',
host => $5,
port => $6 || '',
path => $7 || '',
query => $8 || '',
fragment => $9 || '',
);

return %result unless $parse_query;

my %query = ();
for my $par (split('&', $result{query})) {
next unless ( $par =~ /([^=]+)=(.*)/ );
$query{$1} = $2;
}
$result{query} = \%query;

return %result;
}

Rumata:
пример использования

%ftp = parseDSN('ftp://user:password@localhost/pub/Software');
$dsn = parseDSN('jdbc:solid://localhost:1313');
%url = parseDSN('http://forum.dklab.ru/viewtopic.php?p=148989#148989', 1);


в последнем случае переменная %url будет содержать все элементы URL предыдущего сообщения

(
scheme => 'http',
subscheme => '',
user => '',
pass => '',
host => 'forum.dklab.ru',
port => '',
path => '/viewtopic.php',
query => (
p => '148989',
),
fragment => '148989',
)

Эта тема на forum.dklab.ru