473,396 Members | 2,111 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Extract any URL from any string?

geturl.php

Too much code to paste here, but have a look at http://www.liarsscourge.com/

So far, I have not found a string that can break this...

Any built-in functions or suggestions for improvement?

Thanks in advance.
Feb 10 '07 #1
14 2464
Daz
On Feb 10, 8:41 pm, "deko" <d...@nospam.comwrote:
geturl.php

Too much code to paste here, but have a look athttp://www.liarsscourge.com/

So far, I have not found a string that can break this...

Any built-in functions or suggestions for improvement?

Thanks in advance.

I don't want to sound negative here, but what exactly is the point?
The reason I ask, is because I see no reason why you can't extract it
with a single regex expression, and then you could use another one to
validate it. It's simple enough to validate, the question is how valid
do you want it to be. Should you need to specify each TLD, or do you
just need to match a pattern. In either case, 2 or 3 regex expressions
max should be able to do what you are after. With a little extra
crafting, you should be able to extract multiple URLs in one go.

Feb 10 '07 #2
deko wrote:
geturl.php

Too much code to paste here, but have a look at
http://www.liarsscourge.com/
So far, I have not found a string that can break this...

Any built-in functions or suggestions for improvement?
1. Increase the error_reporting level and you will find some sloppy notices
2. Have a look at parse_url(), which might be useful
3. Use preg_* functions instead of POSIX ereg* function (performance)
4. Strings like the following cause infinite loops:

getURL('fofo http://discovery.co.uk/../foo');

Probable fix:

= Replace:

if (!eregi("^(com|net|org...)$", $urlString_a[$i])) {
...
}

= With:

if (preg_match("!^(com|net|org...)[^$]!", $urlString_a[$i], $m)) {
$urlString_a[$i] = $m[1];
}
JW
Feb 10 '07 #3
1. Increase the error_reporting level and you will find some sloppy notices
2. Have a look at parse_url(), which might be useful
3. Use preg_* functions instead of POSIX ereg* function (performance)
4. Strings like the following cause infinite loops:

getURL('fofo http://discovery.co.uk/../foo');

Probable fix:

= Replace:

if (!eregi("^(com|net|org...)$", $urlString_a[$i])) {
...
}

= With:

if (preg_match("!^(com|net|org...)[^$]!", $urlString_a[$i], $m)) {
$urlString_a[$i] = $m[1];
}
Outstanding. Thanks for the constructive feedback.
Feb 11 '07 #4
geturl 2.0...
1. Increase the error_reporting level and you will find some sloppy notices
so I have a few undefined variables... I thought this did not matter with PHP
(script vs. compiled code)
2. Have a look at parse_url(), which might be useful
well, if urlString = http://netforex.subdomain.net.foo'>, parse_url() returns:
netforex.subdomain.net.foo'- which is not much help. Nevertheless, I'm using
it on line 79 for validation - but I think it would be better validation if I
could do this:
if ($urlLink = parse_url($urlLink))
{
return $urlLink['host'];
}
??
3. Use preg_* functions instead of POSIX ereg* function (performance)
I was able to replace an eregi with preg_match on lines 18 and 29, but unsure of
the syntax for line 44 ... suggestions?
4. Strings like the following cause infinite loops:

getURL('fofo http://discovery.co.uk/../foo');
fixed! see line 38.

- - - - -

I'm wondering how much of a hack that for loop is (lines 26 - 53). Seems to
work okay...

Feb 11 '07 #5
http://www.liarsscourge.com <<== the script is here
"deko" <de**@nospam.comwrote in message
news:5K******************************@comcast.com. ..
geturl 2.0...
>1. Increase the error_reporting level and you will find some sloppy notices

so I have a few undefined variables... I thought this did not matter with PHP
(script vs. compiled code)
>2. Have a look at parse_url(), which might be useful

well, if urlString = http://netforex.subdomain.net.foo'>, parse_url()
returns: netforex.subdomain.net.foo'- which is not much help. Nevertheless,
I'm using it on line 79 for validation - but I think it would be better
validation if I could do this:
if ($urlLink = parse_url($urlLink))
{
return $urlLink['host'];
}
??
>3. Use preg_* functions instead of POSIX ereg* function (performance)

I was able to replace an eregi with preg_match on lines 18 and 29, but unsure
of the syntax for line 44 ... suggestions?
>4. Strings like the following cause infinite loops:

getURL('fofo http://discovery.co.uk/../foo');

fixed! see line 38.

- - - - -

I'm wondering how much of a hack that for loop is (lines 26 - 53). Seems to
work okay...
Feb 11 '07 #6
deko wrote:
so I have a few undefined variables... I thought this did not matter
with PHP (script vs. compiled code)
It doesn't, but it's just good practice to do so (and increasing the
error_reporting level saves you a lot of time debugging when making typos in
variable names).
well, if urlString = http://netforex.subdomain.net.foo'>,
parse_url() returns: netforex.subdomain.net.foo'- which is not much
The parse_url function can indeed easily be fooled, so you will have to add
some additional validation. But it's quite useful for what you are doing
(and pretty fast).
I was able to replace an eregi with preg_match on lines 18 and 29,
but unsure of the syntax for line 44 ... suggestions?
You mean the following line?
if (eregi("^(com|net|org...)$", $urlString_a[$i]))
You can simply replace this with:
if (preg_match("!^(com|net|org...)$!i", $urlString_a[$i]))

JW

Feb 11 '07 #7
>so I have a few undefined variables... I thought this did not matter
>with PHP (script vs. compiled code)

It doesn't, but it's just good practice to do so (and increasing the
error_reporting level saves you a lot of time debugging when making typos in
variable names).
Understood. Adjusting error_reporting is helpful for debugging and
optimization.
>well, if urlString = http://netforex.subdomain.net.foo'>,
parse_url() returns: netforex.subdomain.net.foo'- which is not much

The parse_url function can indeed easily be fooled, so you will have to add
some additional validation. But it's quite useful for what you are doing (and
pretty fast).
I'm not sure where parse_url is useful, precisely because it is so easily
fooled. The
strings I'm working with are entirely unpredictable. That's why I explode the
candidate URL into domains and inspect each one in a for loop.
>I was able to replace an eregi with preg_match on lines 18 and 29,
but unsure of the syntax for line 44 ... suggestions?

You mean the following line?
>if (eregi("^(com|net|org...)$", $urlString_a[$i]))

You can simply replace this with:
>if (preg_match("!^(com|net|org...)$!i", $urlString_a[$i]))
Thanks, but I'm still baffled by that syntax - why the second negation '!' after
the first '$' ? I understand that '$' means end of line, and 'i' means case
insensitive... is '$!' saying "not ending with"?

I still want to replace the eregi code (lines 44, 51, 55, 85) with preg_match,
but the preg_match syntax seems counter intuitive... just have not figured it
out yet. What's up with delimiters?

http://www.liarsscourge.com <<== latest code here

Thanks again for the help!

Feb 12 '07 #8
http://www.liarsscourge.com/ <<== this is better

known bug: if an email address appears in the test string before a valid URL,
the script will not find the URL

Feb 12 '07 #9
deko wrote:
http://www.liarsscourge.com/ <<== this is better

known bug: if an email address appears in the test string before a valid
URL, the script will not find the URL
Hard coding TLDs is generally not useful, as you never know when
unexpected ones may be put in use. Plus, you do not allow variance for
different schemes other than http(s).

You do not support valid URLs that have the authority:

<http://bob1234z_.sss:li*****@example.com/foo/bar
baz/index.bak.php?q=my&q2=query#frag2>

This is indeed a valid URL, but your algorithm fails. It's far more
useful to use a single regex, anticipate any scheme (look at wikipedia
or search some RFCs for valid URI format), and any TLD.

parse_url is not meant to be used for validation, as stated in the PHP
docs themselves.

This is an example implementing the regex I made, recently:

<?php
$re = '%
( [\w.+-]+ : (?://)? ) # scheme name

( [^/]+ ) # authority, domain
( / [^?]+ )? # path, if exists

# query and fragment, which may or may not exist
(?:
\\? # query initializer
( [^#]+ ) # grab query
(?: \\# ([\w-]+) )? # fragment, if exists
)?
%x';

$s = 'Welcome.to{"http://user:pa**@example.com/foo
bar".-/index.bak.php?q=query&r=arrr#frag2_2borky borked!';
if (preg_match($re, $s, $m)) {
echo '<p>Original: <code>' . $s . '</code></p>';
echo '<p>Extrapolation: <a href="'
. htmlentities($m[0], ENT_QUOTES) . '">' . ($m[1].$m[2])
. '</a(full URI in link, see status bar).</p>';
}
else {
echo 'Not a valid URI.';
}
?>

Curtis
Feb 12 '07 #10
Hard coding TLDs is generally not useful, as you never know when unexpected
ones may be put in use. Plus, you do not allow variance for different schemes
other than http(s).

You do not support valid URLs that have the authority:

<http://bob1234z_.sss:li*****@example.com/foo/bar
baz/index.bak.php?q=my&q2=query#frag2>

This is indeed a valid URL, but your algorithm fails. It's far more useful to
use a single regex, anticipate any scheme (look at wikipedia or search some
RFCs for valid URI format), and any TLD.

parse_url is not meant to be used for validation, as stated in the PHP docs
themselves.

This is an example implementing the regex I made, recently:

<?php
$re = '%
( [\w.+-]+ : (?://)? ) # scheme name

( [^/]+ ) # authority, domain
( / [^?]+ )? # path, if exists

# query and fragment, which may or may not exist
(?:
\\? # query initializer
( [^#]+ ) # grab query
(?: \\# ([\w-]+) )? # fragment, if exists
)?
%x';

$s = 'Welcome.to{"http://user:pa**@example.com/foo
bar".-/index.bak.php?q=query&r=arrr#frag2_2borky borked!';
if (preg_match($re, $s, $m)) {
echo '<p>Original: <code>' . $s . '</code></p>';
echo '<p>Extrapolation: <a href="'
. htmlentities($m[0], ENT_QUOTES) . '">' . ($m[1].$m[2])
. '</a(full URI in link, see status bar).</p>';
}
else {
echo 'Not a valid URI.';
}
?>
Thanks, I'll try to use this. As for Internet address validation, I've come to
this conclusion: I can only validate known quantities - that is, the scheme
(http, https, ftp) and the TLD. Granted, TLDs come and go, but not often enough
to avoid using a list to validate against. As for domain names, I can only
validate format - that is, 255 or less characters and no non-alphanumeric
characters (other than a hyphen). geturl.php is my first attempt at implementing
this. I'll have another rev posted at http://liarsscourge.com shortly. Thanks
for your help!

Feb 12 '07 #11
Here's a possible way to validate a host's domain name(s):

$invalid = "(~ ` ! @ # $ % ^ & * ( ) _+ = { } [ ] \ | : ; " ' < , ? /)"
//pseudo code
$url_a = parse_url($url);
$urlHost = $url_a['host'];
$urlHost_a = explode('.',$urlHost);
for ($i = count($urlHost_a) - 2; $i 0 ; $i--) //skips TLD
{
if (preg_match($invalid, $urlHost_a[$i]))
{
echo 'failed on '.$urlhost_a[$i].'<br>';
}
else
{
echo 'valid domain name(s)<br>';
}
}

Any suggestions on how to construct that $invalid pattern? I'm not sure what
syntakx to use or what characters need to be escaped.

Feb 12 '07 #12
deko wrote:
Thanks, but I'm still baffled by that syntax - why the second
negation '!' after the first '$' ? I understand that '$' means end
of line, and 'i' means case insensitive... is '$!' saying "not ending
with"?
The exclamation marks are used to indicate the beginning and the end of the
pattern. The following will also work:

#(pattern)#
|(pattern)|
?(pattern)?

.....or any character that's not in use by the pattern. This is not a
restriction, however, because you can escape characters with a backslash
when they occur both in the pattern and as pattern delimiters:

|(a\|b)|
JW
Feb 13 '07 #13
deko wrote:
Here's a possible way to validate a host's domain name(s):

$invalid = "(~ ` ! @ # $ % ^ & * ( ) _+ = { } [ ] \ | : ; " ' < , ?
/)" //pseudo code
$url_a = parse_url($url);
$urlHost = $url_a['host'];
$urlHost_a = explode('.',$urlHost);
for ($i = count($urlHost_a) - 2; $i 0 ; $i--) //skips TLD
{
if (preg_match($invalid, $urlHost_a[$i]))
{
echo 'failed on '.$urlhost_a[$i].'<br>';
}
else
{
echo 'valid domain name(s)<br>';
}
}

Any suggestions on how to construct that $invalid pattern? I'm not sure
what syntakx to use or what characters need to be escaped.
Again, I would implement it all in one regex, using the /x modifier to
maintain readability. You could use that list of invalid chars in a
negative lookahead - but there are plenty of ways you can do this.
Just not sure how worth it it would be to go all out.

Curtis
Feb 14 '07 #14
>Any suggestions on how to construct that $invalid pattern? I'm not sure
>what syntakx to use or what characters need to be escaped.

Again, I would implement it all in one regex, using the /x modifier to
maintain readability. You could use that list of invalid chars in a
negative lookahead - but there are plenty of ways you can do this.
Just not sure how worth it it would be to go all out.
This seems to be working:

preg_match('/[^0-9a-z-]/i', $urlHost_a[$d])

http://www.liarsscourge.com

Feb 14 '07 #15

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
by: Sharon | last post by:
hi, I want to extract a string from a file, if the file is like this: 1 This is the string 2 3 4 how could I extract the string, starting from the 10th position (i.e. "T") and...
6
by: Mohammad-Reza | last post by:
Hi I want to extract icon of an exe file and want to know how. I look at the MSDN and find out that I can use ExtractIconEx() Windows API but in there are some changes to that api in c# I made...
7
by: teo | last post by:
hallo, I need to extract a word and few text that precedes and follows it (about 30 + 30 chars) from a long textual document. Like the description that Google returns when it has found a...
5
by: deko | last post by:
If I have random and unpredictable user agent strings containing URLs, what is the best way to extract the URL? For example, let's say the string looks like this: registered NYSE 943 <a...
1
by: caine | last post by:
I want to extract web data from a news feed page http://everling.nierchi.net/mmubulletins.php. Just want to extract necessary info between open n closing tags of <title>, <categoryand <link>....
1
by: nkg1234567 | last post by:
I'm trying to extract HTML from a website in the form of a string, and then I want to extract particular elements from the string using the substr function: here is some sample code that I have thus...
7
by: erikcw | last post by:
Hi all, I'm trying to extract zip file (containing an xml file) from an email so I can process it. But I'm running up against some brick walls. I've been googling and reading all afternoon, and...
1
by: rcamarda | last post by:
I'd need to have a function that allows me to extract 'fields' from within the string I.E. (kinda pseudo code) declare @foo as varchar(100) set @foo = "Robert*Camarda*123 Main Street" select...
1
by: GS | last post by:
I need to extract sections out of a long string of about 5 to 10 KB, change any date format of dd Mmm yyyy to yyyy-mm-dd, then further from each section extract columns of tables. what is the...
5
by: Steve | last post by:
Hi all Does anybody please know a way to extract an Image from a pdf file and save it as a TIFF? I have used a scanner to scan documents which are then placed on a server, but I need to...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.