Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

strings 1

Status
Not open for further replies.

ruler1

MIS
Feb 19, 2007
89
hi peeps, i was wondering if someone could help me.
im having difficulties extracting items from a text file and adding them to variables. the contents of the file below might give an idea of what i am trying to do...

this is a regular visitor:24.8.0.1-24.8.0.255
unknown visitor:124.80.0.1-124.80.0.255
top member:10.90.0.1-10.90.0.255
admin member:22.28.0.255-22.28.0.255
moderator member:22.27.17.11-22.27.17.11

i am trying to put each into a variable when reading through the file for example using something like below..

Code:
$file = fopen("c:users.txt", "r") or exit("Unable to open file!");
while(!feof($file))
  {
    // (put info into $info):(put start IP1 into $ip1).(put start IP2 into $ip2).(put start IP3 into $ip3)....
  }
fclose($file);

any idea's would be great because i just cant think of any way to do this. thank you in advanced
 
Code:
<?php
$file = 'c:/users.txt';
$lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$data = array();
foreach ($lines as $line){
	list($info, $ips) = explode(':', $line);
	list($startIP, $endIP) = explode ('-', $ips);
	$data[$info] = array(
						'startIP'=>$startIP,
						'endIP'=>$endIP
						);
}
//dump to screen
echo "<pre>" . print_r($data, true) ."</pre>";
?>
 
thanks for your reply.
i will gave that a try and post back a bit later. the code i am presently working with is a little complex (at least for me it is) so it will give me time to try it out and see if i can use it.
the general idea of the code is to pull from the text file each row at a time, put the text before the : into a string and then the start IP address into another string and then finally the last. would also be nice to know how to break down the actual IPs and put them into their own variables such as Start IP $Sip1.$Sip2.$Sip3.$Sip4 - $Eip1.$Eip2.$Eip3.$Eip4 im sure i did something like this a long time ago but cant rememebr how.

anyway i will post back later and say if it worked or not. thank you again for the help
 
ok this works great eccept for one thing, if someone enters the character : then it throws out.

the data that is being added to the file is added in 9 input fields, 1) info 2-5) are the start range and 6-9) is the end range. the range inputs allow only numbers so i need not to worry about those but the info input field will eccept any character. is it posible to look for a patern such as
" :value'.'value'.'value'.'value'-'value'.'value'.'value'.'value \r\n "

where \r\n would detect its the end of that line. if there is no way to do it i will go with what is above and stop users from entering that character ; into the info field. thanks
 
Code:
$file = 'c:/users.txt';
$lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$lines = implode ("\r\n", $lines); //turn in to string
$pattern = '(?<info>.*?):(?<startIP>\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3})-(?<endIP>\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3})/ims';
preg_match_all($pattern, $lines, $matches);
echo "<pre>";
print_r($matches['info']);
print_r($matches['startIP']);
print_r($matches['endIP']);
echo "</pre>";
 
wow thats perfect, i wont say how long i was trying to get that to work :embarrassed: i am really greatful for your help :) thank you, much appreciated :)
 
no worries. regular expressions are real arcane and dark arts... anything past the basics and i'm useless at them.
 
anything past the basics and i'm useless at them.
if thats not past the basics then im way behind :D i also noticed you managed to do it with only a few lines(impressive). if i ever did manage to figure it out im sure the code would have been as long as the phone book :D i have a lot to learn.
writing to the file was easy infact it took me only an hour to write the code (for me thats good) but reading it back and being able to do checks was where the real trouble began for me. im sure code like this would surely help someone else too so thanks once again for the help :)
 
hmm there is one small error appearing, works as a test but when i add the code to the rest of the php script it reports this error...

Warning: preg_match_all() [function.preg-match-all]: Unknown modifier ':' in C:\Program Files\xampp\htdocs\mysite\users.php on line 59

line 59 is this line of the code...

Code:
preg_match_all($pattern, $lines, $matches);
it seems it doesnt like that character : but its 99% working.
 
curious.i missed out a slash. please change this line as shown
Code:
$pattern = '[red]/[/red](?<info>.*?):(?<startIP>\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3})-(?<endIP>\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3})/ims';
 
i think its working, this was the output below...

Array
(
[0] => Moderator
[1] =>

friend
[2] =>

work collegue
[3] =>

private member
[4] =>

key member
)
Array
(
[0] => 24.8.0.1
[1] => 124.80.0.1
[2] => 10.90.0.1
[3] => 22.28.0.255
[4] => 22.27.17.11
)
Array
(
[0] => 24.8.0.255
[1] => 124.80.0.255
[2] => 10.90.0.255
[3] => 22.28.0.255
[4] => 22.27.17.11
)

not sure if this is the expected output but its reporting no errors now :)
 
hmm. that looks right.

so for key 0
info is Moderator
startip is 24.8.0.1
endip is 24.8.0.255

but i've mucked up the formatting with the implode.
this will fix it
Code:
array_walk($matches['info'], 'trim');
print_r($matches['info']);

could also fix it in the regex, but this is quicker!
 
to i replace a line with that code or do i add it before/after a line?
 
this kind of patterning might be useful for other users so i have rewritten the code and put lots of commenting and explanation in. hopefully answers your question too!

Code:
$file = 'c:/users.txt';
//get the contents of the file into an array
//skip blank lines and don't include the new line chars
$lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

//reconstitute the array as one long string
$lines = implode ("\r\n", $lines); //turn in to string

//this pattern works as follows
/*
 * / starts the pattern. 
 * ^ must be start of line
 * \s* zero or more spaces
 * (?<info>.*?) capture all the characters until the last colon before the next match and put it in a backreference called info
 * : match a colon
 * (?<startIP> 	capture the next match into a back reference called startIP
 * \d{1,3}\. match a digit (0-9) that is between 1 and 3 digits long followed by a DOT
 * the repetitions are obvious...
 * / ends the pattern
 * i	makes it case insensitive (irrelevant in this case)
 * m	makes it multiline (so the ^ and $ match beginning and end of lines as well as files)
 * s 	makes the dot match everything (including new lines).  this would ordinarily be a bad idea but because of the pattern we can deal with it
 */
$pattern = '/^\s*(?<info>.*?):(?<startIP>\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3})-(?<endIP>\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3})\s*$/ims';

//perform the matches and put the output into $matches
preg_match_all($pattern, $lines, $matches);

//just in case - trim the output of white space
//do this in a foreach loop and pass the array by reference so that the original array is modified by the walk
foreach ($matches as &$m){
	array_walk($m, 'trim');
}
echo "<pre>";
print_r($matches['info']);
print_r($matches['startIP']);
print_r($matches['endIP']);
echo "</pre>";
 
i changed the lines below

Code:
echo "<pre>";
print_r($matches['info']);
print_r($matches['startIP']);
print_r($matches['endIP']);
echo "</pre>";

with these lines...

Code:
array_walk($matches['info'], 'trim');
print_r($matches['info']);

im guessing thats what i was meant to do? thanks for the above code that will definatly be useful. ive been struggling to find good code for pattern matching so i can use that as a reference :)
 
and did that work for you?

you still need to handle the other lines too of course.

once you have this data in arrays, what are you planning to do with it?
 
the output was as follows..

Array ( [0] => Moderator [1] => friend [2] => work collegue [3] => private member [4] => key member )

it is like a IP blocklist but the opposite. if i registered a member and they tried to connect to my webpage they would only be able to logon as that user if their IP matched the IP that was asigned to that name or if their IP was within that range.
it could also be used for other things at a later date :)
 
hmm. thought so. that's going to be more difficult though - as how will you decide (in php) whether an incoming IP is within a range? i guess i'd convert each item to a decimal and compare that way.

you might be better off using apache security for this kind of filtering.
 
i think i could write the ip/range checkings, it was mainly the matching that was a real headache because i searched google and the php site and also here but found little of any use to me or what i did find i couldnt understand. i did think of the inbuilt security with apache and even my sql db but with php i have more flexability in what i can get it to do. it is also good learning too which i like, i still have a lot to learn as you can see :)
to be honist the code you have posted here is about the only code i can actually understand because its not only showing the code but also each line is explained. i will use the code above for reference and i'll try and write the ip/range checking, if it is too complicated then i will most likely use apache as a last resort. its all fun :)
 
I'm back but with a final small problem. ive managed to be able to add new IPs perfectly but i am having troubles removing IPs from the list. I did try google but most forums seem to start off with a little code then as i scroll down to the bottom of their pages the code seems to get huge and more confusing. this is the code i have at the moment or the main chunk i am working with. hope it makes some sence :)

Code:
			$file = 'c:users.txt';
			$lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
			$lines = implode ("\r\n", $lines); //turn in to string
			$pattern = '/(?<info>.*?):(?<startIP>\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3})-(?<endIP>\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3})/ims';
			preg_match_all($pattern, $lines, $matches);
			array_walk($matches['info'], 'trim');
			$cc=0; 
			$enterIPstart = $ip9*256*256*256+$ip10*256*256+$ip11*256+$ip12+0;
			$enterIPend = $ip13*256*256*256+$ip14*256*256+$ip15*256+$ip16+0;
			while($matches['startIP'][$cc])
			{
				if(ereg("([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})", $matches['startIP'][$cc],$regs) && ereg("([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})", $matches['endIP'][$cc],$regs1))
				{
					$foundIPstart = $regs[1]*256*256*256+$regs[2]*256*256+$regs[3]*256+$regs[4]+0;
					$foundIPend = $regs1[1]*256*256*256+$regs1[2]*256*256+$regs1[3]*256+$regs1[4]+0;
				}
				// check to see if the end ip is lower than the start ip

				//check to see if there is an exact IP range match if so delete the line
				if ($enterIPstart = $foundIPstart && $enterIPend = $foundIPend)
				{
					//delete the line here
				}
				$cc++;
			}

the reason for the long tab spaces is because its been taken from a section of code on my page. Ive seen a couple of ways of doing it but not sure what is best. thanks for any help
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top