You are not logged in.
#26 25 Sep 2007 3:41 pm
Re: Automated File Changes
echo the contents of the file after file_get_contents. if all the contents are there, then check the value returned from str_replace. if thats correct then make sure file_put_contents gets the same file variable that you passed to file_get_contents.
Offline
#27 27 Sep 2007 10:30 am
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Automated File Changes
Seems it stops when opening from full path, gives me this:
Warning: fopen(D:\xampp\htdocs\write) [function.fopen]: failed to open stream: Permission denied in D:\xampp\htdocs\write\write.php on line 10
Though, I do not recieve this error or any error when calling the file as purely "index.php".
Offline
#28 27 Sep 2007 8:31 pm
Re: Automated File Changes
try echo'ing file_get_contents with "index.php"
I'm willing to bet that it isn't finding anything and therefore will print an empty string. the reason you're getting the error is that it does find the file but you do not have read permissions for that file.
you may want to chmod the file before you attempt to modify it.
chmod($index_file_path, 0755); // important that the second parameter is 0755 (and you cannot omit the leading zero)
Offline
#29 28 Sep 2007 3:03 am
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Automated File Changes
Ok, added the chmod to it, but it still persistantly denies me to read it, did this now:
Code:
<?php //File 1 $base_dir = dirname(__FILE__); $newfile1 = $base_dir.DIRECTORY_SEPARATOR."index.php"; echo $newfile1; echo '<br>'; echo '<br>'; chmod($newfile1, 0755); $nr1 = 'USUAL STUFF'; $nr2 = 'USUAL STUFF'; $index_content = file_get_contents($newfile1); echo $index_content; echo '<br>'; echo '<br>'; $modified = str_replace($nr1, $nr2, $index_content); $stringdata1 = $modified; echo '<br>'; echo '<br>'; echo $stringdata1; ?>
$newfile1 echoes to: D:\xampp\htdocs\write\index.php
$index_content echoes to: blank
$stringdata1 echoes to: blank
As far as I can tell, it is set up in the right order;
1. $base_dir tells directory name
2. $newfile1 specifies file based on $base_dir
3. The file is chmod'ed to 0755
4. $index_content reads the file
5. $modified altars the file to get the right content
6. $stringdata1 now contains the right content for the file, and can be written
But somehow that goes wrong...
Offline
#30 01 Oct 2007 7:01 pm
Re: Automated File Changes
does it give you permission errors still?
try this sample and see what it does:
index.php:
Code:
<?php echo "it goes well!"; ?>
mod.php:
Code:
<?php $one = "it goes well"; $two = "It goes VERY well"; $path = dirname(__FILE__); $path = $path.DIRECTORY_SEPARATOR."index.php"; $content = file_get_contents($path); $content = str_replace($one, $two, $content); file_put_contents($path, $content); ?>
and run mod.php.
it may be that whatever you're editing your mod file in, is adding CRLF to the end of each line (\r\n), and whatever the source file is in, is just LF (\n) so str_replace is failing because its not finding a match. actually I believe you said you used notepad to do the replacements. notepad uses \r\n and may have inserted it into your string that does the looking which would cause it to not find the exact same string in the source file.
Offline
#31 02 Oct 2007 10:09 am
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Automated File Changes
It worked, I made a file called echo.php that contained "it goes well!", and ran mod.php on it, and it became "it goes very well!".
Could the CHMOD not work since the file is on a Windows system? I am currently doing my website building using XAMPP, not sure if CHMOD would work on the file then.
Offline
#32 02 Oct 2007 10:18 am
Re: Automated File Changes
apache emulates the unix file system and chmod maps to some windows api that handles the file mode.
your issue is likely the new line or tabs (or spaces) at the beginning and ending of each line. your search string has to be exactly the same as the match string (in the file) otherwise nothing will be replaced. an alternative would be to use a regular expression (which would allow you some flexibility in matching newlines or tabs/spaces) but may be harder for you to maintain or diagnose.
Offline
#33 02 Oct 2007 1:51 pm
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Automated File Changes
I am doing a small change to the original script, to ensure the functionality with the forums (in-case another installed mod is also running off the main arrays), so instead of the full replacement, I'll tried this:
Code:
<?php $one = ' \'FORUM_IMG\' => $images[\'forum\'], \'FORUM_NEW_IMG\' => $images[\'forum_new\'], \'FORUM_LOCKED_IMG\' => $images[\'forum_locked\'], \'L_FORUM\' => $lang[\'Forum\'],'; $two = ' \'FORUM_IMG\' => $images[\'forum\'], \'FORUM_NEW_IMG\' => $images[\'forum_new\'], \'FORUM_LOCKED_IMG\' => $images[\'forum_locked\'], // Menu Mod \'EXTRA_MENU\' => $menu.php, // Menu Mod \'L_FORUM\' => $lang[\'Forum\'],'; $path = dirname(__FILE__); $path = $path.DIRECTORY_SEPARATOR."index.php"; $content = file_get_contents($path); $content = str_replace($one, $two, $content); file_put_contents($path, $content); ?>
Now, as you see, I am using a exact duplicate of the script that just turned "it goes well" into "it goes very well", and it echoes out as this:
$one
'FORUM_IMG' => $images['forum'], 'FORUM_NEW_IMG' => $images['forum_new'], 'FORUM_LOCKED_IMG' => $images['forum_locked'], 'L_FORUM' => $lang['Forum'],
$two
'FORUM_IMG' => $images['forum'], 'FORUM_NEW_IMG' => $images['forum_new'], 'FORUM_LOCKED_IMG' => $images['forum_locked'], // Menu Mod 'EXTRA_MENU' => $menu.php, // Menu Mod 'L_FORUM' => $lang['Forum'],
So, obviously the escaping worked remarkably well. But yet, he doesn't write it to this file:
index.php
Code:
); $template->assign_vars(array( 'TOTAL_POSTS' => sprintf($l_total_post_s, $total_posts), 'TOTAL_USERS' => sprintf($l_total_user_s, $total_users), 'NEWEST_USER' => sprintf($lang['Newest_user'], '<a href="' . append_sid("profile.$phpEx?mode=viewprofile&" . POST_USERS_URL . "=$newest_uid") . '">', $newest_user, '</a>'), 'FORUM_IMG' => $images['forum'], 'FORUM_NEW_IMG' => $images['forum_new'], 'FORUM_LOCKED_IMG' => $images['forum_locked'], 'L_FORUM' => $lang['Forum'], 'L_TOPICS' => $lang['Topics'], 'L_REPLIES' => $lang['Replies'], 'L_VIEWS' => $lang['Views'], 'L_POSTS' => $lang['Posts'], 'L_LASTPOST' => $lang['Last_Post'], 'L_NO_NEW_POSTS' => $lang['No_new_posts'], 'L_NEW_POSTS' => $lang['New_posts'], 'L_NO_NEW_POSTS_LOCKED' => $lang['No_new_posts_locked'], 'L_NEW_POSTS_LOCKED' => $lang['New_posts_locked'], 'L_ONLINE_EXPLAIN' => $lang['Online_explain'], 'L_MODERATOR' => $lang['Moderators'], 'L_FORUM_LOCKED' => $lang['Forum_is_locked'], 'L_MARK_FORUMS_READ' => $lang['Mark_all_forums'], 'U_MARK_READ' => append_sid("index.$phpEx?mark=forums")) );
I see a string echoing as it was originally in the file, and another string echoing to what it should become, but he doesn't write it... I had a quick google for PHP Regular Expression, is it basically a way to force the script to read the strings based on the start and end of it? Was sort of confusing, as most sites explain it as a way of creating patterns.
Offline
#34 03 Oct 2007 12:16 am
Re: Automated File Changes
when you press the enter key on your keyboard, it in reality places an unseen character at the end of the line.
depending on the editor you use, that character is either 0xDA /decimal #'s 13 and 10 / \r\n or simply 0xA / decimal # 10 / \n.
also, when you paste in text into your editor, your editor may replace \n's with \r\n, so that what you think you're typing into your PHP script as $one, may LOOK materially the same, but in fact may be different in that the invisible character(s) at the end of each line may be different than what you expect.
since str_replace does a binary comparison between the contents of your string variable and the contents of the file:
Code:
$contents = 'it goes well '; // implied carriage return line feed (aka \r\n) if I typed this in notepad.
and
Code:
$one = "it goes well\n"
may actually look like this in memory (using the hexadecimal ASCII representation of each character)
Code:
$contents = 0x69 0x74 0x20 0x67 0x6f 0x65 0x73 0x20 0x77 0x65 0x6c 0x6c 0x0D 0x0A $one = 0x69 0x74 0x20 0x67 0x6f 0x65 0x73 0x20 0x77 0x65 0x6c 0x6c 0xA
and it would compare character by character until it gets to the 13th character where $one[12] is 0xA, and $contents[12] is 0xD, and would therefore discard the replacement operation because the two strings are actually different.
same goes with case sensitivity since A (0x41) and a (0x61) are different characters. and while its easy to tell the difference between a capital A and lowercase a, since "end of line" is not visible, it could cause you to think that something is not being printed to file, when in fact, what you think you're matching, is not actually what's being matched.
another non-visible character is the tab (0x09). Some editors place a single tab character at the beginning of each line (for indention) while others place 4 spaces (0x20) at the beginning, and looking at the text with your eyes, they will seem to be identical, but doing a binary comparison (what str_replace does) they will not match, since one will have 3 more characters than the other.
also, echo can be misleading as well, since you view its output in an html rendering application, you wont be able to see newlines unless you replace them with <br />'s, and even if you "view source," depending on what browser you're using, you may end up copying two different things. for instance, view source in IE happens in notepad... notepad isn't capable of displaying a new line without \r\n, so while you may have echo'd \n, IE's viewsource would produce \r\n, opera does the same thing. Mozilla will correctly render \n.
you can test this with the following script (type it and save it in notepad):
Code:
<?php $notepad_str = 'testing '; $hardcoded_str = "testing\n"; echo $notepad_str." ".$hardcoded_str; ?>
view it in ie, moz and opera. in each browser, view source, and save as "page1.bin" "page2.bin" and "page3.bin" (make sure to wrap the name in quotes when you save) and open the files in a hex editor (I used visual studio to test this). naming the files with a bin extension instead of html or php will make it easier to open the files in a hex editor (at least it helps make it viewable in visual studio as a hex file).
notice IE added 0x0d 0x0a where we explicitly printed 0xa
same with opera
firefox did not, it maintained what we explicitly coded.
I use zend studio for php development and it has tons of settings in its options (I believe dreamweaver does too) as to what I want to use and where. I use \n for new lines, and 4 spaces for line indentions. I'd venture to guess that these are typical settings for PHP (though some may use tabs for indentions) and when you look at a piece of code where nothing lines up (indention wise) its because multiple people have edited the file, and have used different editors that re-format what is used for newlines and indentions.
If I edit a php file in notepad, I typically open it in word pad first, then hit save (which will convert all \n's to \r\n's), then close it and open it in notepad, because notepad will put everything on one line (since it doesn't know what to do with \n newlines) if word doesn't re-format the document.
using a regular expression will allow you to perform a fuzzy search instead of the binary search str_replace does. instead of requiring your source file to be the same as your search pattern (in the case of str replace your search pattern is a verbatim set of characters in your source file), regular expressions allow you to match a string with a set of criteria.
if
was our source text, and we wanted to replace every instance of the letter l, except if it was followed by another l, we could create a regular expression:"hello world, my name is Leroy"
Code:
$replaced = preg_replace("/l[^l]/i", "X", "hello world, my name is Leroy");
we would end up with the string:
getting the syntax for regular expressions is kind of tricky at first, but once you learn the simple syntax, its pretty easy.helX worX my name is Xroy
the search string "/l[^l]/i" can be broken down into a little easier to understand verbage.
the forward slashes at the beginning and end are a perl thing... since we're using preg (perl regular expression) they have to be in the string. the i after the second slash tells the regular expression evaluator to consider this match to be case INSENSITIVE. otherwise it would try to match based on case. everything inside the slashes are evaluated left to right character by character.
/l/
would mean I want to match every instance of the lower case letter "L" so in our sample string it would replace both L's in hello, one L in world, and would skip Larry because its an upper case L.
/l/i
would match the same as above, but would include Larry since we specify the "i" case insensitive regular expression option.
the square brackets with the carrot inside it means NOT THIS CHARACTER, so
/[^l]/
means NOT a lower case L
since we placed a lower case L next to a NOT lower case L, the expression reads,
match a lower case L that is not followed by another lower case L
which is why the first L in hello was not replaced (because it's before another L)
had our expression been:
/[^l]l/i
our output would have read:
hXlo woXd my name isXeroy
notice that it replaces 2 characters where L is not followed by another L. since the e in hello is next to an L the "e" (matches not an L), and the L are replaced with an X, as is the r&l in world and the space and L in the last word.
there's even a way to allow you to replace only the L in the word while still maintaining the previous assertation:
Code:
$replaced = preg_replace("/l(?=[^l])/i", "X", "hello world my name is Leroy");
will produce:
the (?= ... ) is a a zero width (non-capturing) look ahead assertion group which allows the rule of a "NOT a lowercase L" but does not require 2 characters be captured and replaced in the process (in this case just the lower case L).helXo worXd my name is Xeroy
using this, you can specify that the beginning of the line can be either 4 spaces, or a tab, and the end of the line can either be \r\n or \n.
using regular expressions to do this is probably a bit more than you can chew at the moment, as the regex you'll need to do this will be amazingly complex (but efficient).
Offline
#35 03 Oct 2007 5:41 am
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Automated File Changes
Hmmm, to do the "less chewing" method (grind it in the mixmaster), I had a peek around Notepad (and I might have been unclear there, I use Notepad2), and it has two very important settings (I'd guess, seeing as it relates to how it reads line endings):
Encoding:
ANSI
Unicode
Unicode Big Endian
UTF-8
UTF-8 with Signature
Line Endings:
Windows (CR+LF)
Unix (LF)
Mac (CR)
And they are set to the options I embolded... Should it perhaps be set to Unicode and Unix Line Endings? It is set to the Windows Line Ending style in Dreamweaver too actually. And how would I go about damage repair, as in making sure it reads it as \n instead of \r\n? Is there a function or method that would force the server to not read binaries, but compare the visual text against the other visual text (that was a long shot, as most systems only read binaries don't they? At least my math teacher tried explaining that to me once)?
Offline
#36 03 Oct 2007 8:56 am
Re: Automated File Changes
Windows (CR+LF) ='s \r\n
Unix (LF) ='s \n
Mac (CR) ='s \r
it really doesn't usually matter what you use (in this case it matters greatly). for consistency sake (with php scripts) I would use Unix (LF) which will place the \n character at the end of your lines.
since the developers of phpbb use a unix style editor (which means their line endings will be \n), and you're trying to match that based on a string in your script, you'll want your editor to also use unix style line ending because you're entering the actual new line character at the end of your string by pressing return, then closing your string quote. if you were using double quotes and typed in the \n character using the "\n" special escape character, then you could use whatever line endings you wanted. but this is not how you wrote your strings (because you don't want your strings evaluated).
does that make sense?
encoding isn't really important here since that deals with how the characters in the file are physically stored (the number of bytes per character). ansi & utf8 are the most commonly used encodings, but this would only matter if you're coding in Bokmål, but since you'd typically use english to code in, it doesn't really matter.
Offline
#37 03 Oct 2007 10:31 am
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Automated File Changes
It makes sense , but I still have a problem:
Even though I copied the content from the index.php file (original from phpBB2 directory), and pasted in new index.php file after setting both Dreamweaver and Notepad2 to read Unix Line Endings, it doesn't replace it. Theoretically speaking, there should be no \r\n, but only \n now...
Offline
#38 03 Oct 2007 11:50 am
Re: Automated File Changes
in theory.
I'd recommend opening the file (actually I'd recommend opening both the source file, and your mod script) in a hex editor to validate that what you think is there, actually is (that crlf's have been changed to lf's).
Offline
#39 03 Oct 2007 1:55 pm
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Automated File Changes
It was damn confusing looking through that code, wonder if Bill Gates used any sort of drug when making systems in binary mode. But I see various occurences of the incorrect code;
Windows line shift: 0D 0A 0D 0A
Linux line shift: 0A 0A
And the program I got, HxD (hexeditor, found on wikipedia), shows the windows one as .... and the linux one as .., but then again, he marks tabulated spaces (not sure if its called that, but the spaces you get when you press the tabulator) as ... (or 0A 0A 09). I downloaded a converter tool to convert the files (hope that'll work more easily), but I'll have to try it tomorrow, need to play some more guitar, upload some music to my cellphone and watch the news.
Offline
#40 03 Oct 2007 5:46 pm
Re: Automated File Changes
bill gates never wrote anything in binary machine instructions. he was a BASIC programmer at best.
hex editors typically print a dot in the text area of the hex editor, when you have a non-printable character (like tab or newline). you should be able to see the same thing in my screen shots from visual studio.
good luck!
Offline
#41 04 Oct 2007 9:59 am
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Automated File Changes
Well fry me in oil and call me fried chicken, it worked!
Was a very easy system, just select file, press the convert button, and its LF. Now I "just" got to run this on all the right places. Another valuable lesson learned, thanks again
Offline
#42 12 Oct 2007 3:51 pm
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Automated File Changes
In my integration of systems into the filewriting, I decided to include some anti-spam mods (optional for installers), but came over a regular expression, and it just won't be escaped. It looks like this:
Line:
$timepad = preg_replace('/[^0-9]/'\ '', $HTTP_SERVER_VARS['REMOTE_ADDR']) + 0;
Regular expression:
'/[^0-9]/'
I tried the usual \'/[^0-9]/\', but the code is still active. Is there a special method for escaping them?
Offline
#44 13 Oct 2007 3:35 am
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Automated File Changes
Right now, it looks like this:
$timepad = preg_replace(\'/[^0-9]/\' '', $HTTP_SERVER_VARS[\'REMOTE_ADDR\']) + 0;
But I still get this error message:
Parse error: syntax error, unexpected T_CONSTANT_ENCAPSED_STRING in D:\xampp\htdocs\write\post\write_post.php on line 79 (line 79 is the $timepad line with the expression in it)
Offline
#45 13 Oct 2007 7:24 pm
Re: Automated File Changes
there are 3 parameters to preg_replace, preg_replace($pattern, $replacement, $candidate), and your $replacement is an empty string (two single quotes) this is where its breaking as they are not escaped.
it should look like this:
Code:
$timepad = preg_replace(\'/[^0-9]/\' \'\', $HTTP_SERVER_VARS[\'REMOTE_ADDR\']) + 0;
Offline
#46 14 Oct 2007 1:10 pm
#47 14 Oct 2007 6:28 pm
Re: Automated File Changes
well there shouldn't be. there is a missing comma between the first and second parameters in preg_replace, but I tested the following code with no errors:
Code:
<?php $a = '$timepad = preg_replace(\'/[^0-9]/\', \'\', $HTTP_SERVER_VARS[\'REMOTE_ADDR\']) + 0;'; echo $a; ?>
so it must be something else.
Offline
#48 15 Oct 2007 1:26 pm
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Automated File Changes
Hmmm, but I still get the error. The full code looks like this:
Code:
switch ($mode) { case \'newtopic\': $secretkey = \'f\' . $forum_id; break; case \'quote\': // If we are quoting, we need to determine the topic ID $sql = \'SELECT topic_id FROM\ \' . POSTS_TABLE .\ \' WHERE post_id=\' . $post_id; if (!($query = $db->sql_query($sql))) { message_die(GENERAL_MESSAGE, \'Could not obtain quoted topic information\', '', __LINE__, __FILE__, $sql); } if (($row = $db->sql_fetchrow($query))) { $topic_id = $row[\'topic_id\']; } else { message_die(GENERAL_MESSAGE, \'No_such_post\'); } // Fall through to \'reply\' case case \'reply\': case \'vote\': $secretkey = \'t\' . $topic_id; break; case \'editpost\': $secretkey = \'p\' . $post_id; break; } // Generate a signature to validate this page $authkey = md5("nana" . $secretkey . "foofoo"); $authval = md5($HTTP_SERVER_VARS[\'HTTP_USER_AGENT\'] . $secretkey . $HTTP_SERVER_VARS[\'REMOTE_ADDR\']); $timekey = md5("time" . $secretkey); $timepad = preg_replace(\'/[^0-9]/\', \'\', $HTTP_SERVER_VARS[\'REMOTE_ADDR\']) + 0; $timeval = time() ^ $timepad; // Check the signature - if this is a submit which does not jive with the above, turn it into a preview if ($submit && (!isset($HTTP_POST_VARS[$authkey]) || $HTTP_POST_VARS[$authkey] != $authval || !isset($HTTP_POST_VARS[$timekey]) || ($HTTP_POST_VARS[$timekey] ^ $timepad) > time() - 5)) { $submit = false; $preview = true; } $refresh = $preview || $poll_add || $poll_edit || $poll_delete;
But I cannot see anything that directly interfers with the functionality of the $timepad variable. Though, the error message now says that the last line ($refresh = $preview || $poll_add || $poll_edit || $poll_delete;) has an error, but that line has worked perfectly fine before...
Offline
#49 15 Oct 2007 6:48 pm
Re: Automated File Changes
line:
Code:
message_die(GENERAL_MESSAGE, \'Could not obtain quoted topic information\', '', __LINE__, __FILE__, $sql);
needs to look like:
Code:
message_die(GENERAL_MESSAGE, \'Could not obtain quoted topic information\', \'\', __LINE__, __FILE__, $sql);
Offline
#50 16 Oct 2007 11:38 am
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Automated File Changes
There it works
Almost done with this mod now, just one last function and a quick interface with options, and it shall be a release candidate
Offline