I want to edit the code of a Python script from PHP, to change a formula and initial value for one of my projects.
The Python script:
import numpy as np
import scipy as sp
import math
from scipy.integrate import odeint
import matplotlib.pyplot as plt
def g(y, x):
y0 = y[0]
y1 = x #formula
return y1
init = 90#formula2
x= np.linspace(0,1,100)
sol=odeint(g, init, x)
plt.legend()
plt.plot(x, sol[:,0], color='b')
plt.show()
PHP:
<?php
if (isset($_POST['equation1'])&&isset($_POST['constant'])) {
$eqn1 = $_POST['equation1'];
//$equation = $_POST['equation'];
$eqn2 = $_POST['constant'];
//str_replace("^", "**", $equation);
$filename ='ode3.py';
$pgm = "C:\\wamp\\www\\working\\".$filename;
function get_string_between($string, $start, $end) {
$string = " ".$string;
$ini = strpos($string,$start);
if ($ini == 0) return "";
$ini += strlen($start);
$len = strpos($string,$end,$ini) - $ini;
return substr($string,$ini,$len);
}
//write the equation in python code
$pgm_file = $pgm;
$myfile = fopen($pgm_file, "r") or die("Unable to open file!");
$data = fread($myfile,filesize($pgm_file));
$parsed = get_string_between($data, "y1 = ", " #formula");
$parsed2 = get_string_between($data, "init = ", "#formula2");
$datanew1 = str_replace($parsed, $eqn1, $data);
$datanew2 = str_replace($parsed2,$eqn2, $datanew1);
fclose($myfile);
$myfile = fopen($pgm_file, "w") or die("Unable to open file!");
$datacode = fwrite($myfile,$datanew2);
$pgmfile = fopen($pgm_file, "r") or die("Unable to open file!");
$pgmdata = fread($pgmfile,filesize($pgm_file));
fclose($pgmfile);
/*$demo = fopen($pgm, "r") or die("Unable to open file!");
$xxx = fread($demo,filesize($pgm));
echo $xxx;*/
$pyscript = "C:\\wamp\\www\\working\\".$filename;
$python = 'C:\\Python34\\python.exe';
$cmd = "$python $pyscript";
exec("$cmd", $output);
/* if (count($output) == 0) {
echo "error%";
} else {
echo $output[0]."%";*/
}
var_dump($output);
}
?>
I want it to only replace the part of the Python script marked by #formula and #formula2, where x should be replaced by x+45 and the init value should be set to 85.
However, when I run the PHP script, every instance of x in the Python script is replaced with x+45. How can I limit it to only the part marked by #formula inside the g() function?
I think this is a poor way to approach this problem. Rather than editing the source of your Python script, you should re-engineer it so that the variable parts can be passed in as arguments when the script is called. You can then access these execution arguments using sys.argv.
#!/usr/bin/env python
import sys
# ... import numpy etc.
def g(y,x, expr):
y0 = y[0]
# use the Python interpreter to evaluate the expression.
# It should be of the form 'x**2 + 3' or something - a valid Python/math
# expression otherwise it will crash with a syntax error.
y1 = eval(expr)
return y1
if __name__=='__main__':
init = int(sys.argv[1]) # the first argument passed to the script
expr = sys.argv[2].strip('"') # the second argument - if it includes
# whitespace, wrap it in "" so it works.
# ... do stuff
You can then call this as a standard script using PHP's exec or shell_exec function. Pass the function expression in as arguments like so:
python /path/to/ode3.py 85 "x+45".
Please be very careful with Python's eval - it will evaluate anything you put in there. Since you are calling this from a web-facing PHP script that accepts POST arguments, you must be careful to sanitize the input. From the script you've posted, it doesn't look like you validate it, so if it is publicly accessible, it will allow arbitrary code execution with the same permissions as the PHP script. This is true whether you use eval or edit the Python file as you have been attempting.
Update: Also, the operators have different meanings in different languages. For example, in Python, the ^ operator does not mean exponent, it actually means bitwise XOR. If you want to get x^2 (x-squared), the Python syntax is x**2. If you want to be able to write x^2, you would need to write a parser. See here for more information.
Related
i am programming a little bit in VB.net and ich have a code to search into a website for a string and give me the next 4 characters after the string i need... so far so good... in vb.net no Problem:
Dim value As String = New System.Net.WebClient().DownloadString(TextBox1.Text)
Dim wordArr As Integer = value.IndexOf("plid=")
Dim substring As String = value.Substring(wordArr + 5, 4)
substring = "var plid2 = '" & substring & "';"
.... and then save it to a plid.js File on my local machine
Now I want to place a cron job on to my server. I have to do this now in a PHP file......Now Question...... does anyone knows a simple PHP Way for my problem????
:-)
Hi thanks to rickdenhaan..... if someone searching for such code.... here is the way which works for me:
<?php
$meinString = file_get_contents('URL');
$findMich = 'toni=';
$pos = strpos($meinString, $findMich);
$plid = "var plid2 = '" . substr($meinString, $pos + 5, 4) . "';";
$myfile = fopen("plid.js", "w") or die("Unable to open file!");
fwrite($myfile, $plid);
fclose($myfile);
?>
I have app that needs to retrieve some data (signer name) from digital signature "attached" on PDF files.
I have found only examples in Java and C# using the iText class AcroFields method GetSignatureNames
edit: I've tried pdftk with dump_data_fields and generate_fpdf and the result was that (unfortunately):
/Fields [
<<
/V /dftk.com.lowagie.text.pdf.PdfDictionary#3048918
/T (Signature1)
>>]
and
FieldType: Signature
FieldName: Signature1
FieldFlags: 0
FieldJustification: Left
Thanks in Advance !
Well, it's complicated (I would say even impossible, but who knows) to achieve this only with PHP.
At first, please read article about digital signature in Adobe PDF
Second, after reading this you will know that signature is stored between b and c bytes according to /ByteRange[a b c d] indicator
Third, we can extract b and c from document and then extract signature itself (guide says it will be hexdecoded PKCS7# object).
<?php
$content = file_get_contents('test.pdf');
$regexp = '#ByteRange\[\s*(\d+) (\d+) (\d+)#'; // subexpressions are used to extract b and c
$result = [];
preg_match_all($regexp, $content, $result);
// $result[2][0] and $result[3][0] are b and c
if (isset($result[2]) && isset($result[3]) && isset($result[2][0]) && isset($result[3][0]))
{
$start = $result[2][0];
$end = $result[3][0];
if ($stream = fopen('test.pdf', 'rb')) {
$signature = stream_get_contents($stream, $end - $start - 2, $start + 1); // because we need to exclude < and > from start and end
fclose($stream);
}
file_put_contents('signature.pkcs7', hex2bin($signature));
}
Forth, after third step we have PKCS#7 object in file signature.pkcs7. Unfortunately, I don't know methods to extract information from signature using PHP. So you must be able to run shell commands to use openssl
openssl pkcs7 -in signature.pkcs7 -inform DER -print_certs > info.txt
After running this command in file info.txt you will have a chain of certificates. Last one is the one you need. You can see the structure of the file and parse needed data.
Please also refer to this question, this question and this topic
EDIT at 2017-10-09
I knowingly advised you to see exactly this question
There is a code that you can adjust to your needs.
use ASN1\Type\Constructed\Sequence;
use ASN1\Element;
use X509\Certificate\Certificate;
$seq = Sequence::fromDER($binaryData);
$signed_data = $seq->getTagged(0)->asExplicit()->asSequence();
// ExtendedCertificatesAndCertificates: https://tools.ietf.org/html/rfc2315#section-6.6
$ecac = $signed_data->getTagged(0)->asImplicit(Element::TYPE_SET)->asSet();
// ExtendedCertificateOrCertificate: https://tools.ietf.org/html/rfc2315#section-6.5
$ecoc = $ecac->at($ecac->count() - 1);
$cert = Certificate::fromASN1($ecoc->asSequence());
$commonNameValue = $cert->tbsCertificate()->subject()->toString();
echo $commonNameValue;
I've adjusted it for you, but please make the rest by yourself.
This is my working code in PHP7:
<?php
require_once('vendor/autoload.php');
use Sop\ASN1\Type\Constructed\Sequence;
use Sop\ASN1\Element;
use Sop\X509\Certificate\Certificate;
$currentFile = "./upload/test2.pdf";
$content = file_get_contents($currentFile);
$regexp = '/ByteRange\ \[\s*(\d+) (\d+) (\d+)/'; // subexpressions are used to extract b and c
$result = [];
preg_match_all($regexp, $content, $result);
// $result[2][0] and $result[3][0] are b and c
if (isset($result[2]) && isset($result[3]) && isset($result[2][0]) && isset($result[3][0])) {
$start = $result[2][0];
$end = $result[3][0];
if ($stream = fopen($currentFile, 'rb')) {
$signature = stream_get_contents($stream, $end - $start - 2, $start + 1); // because we need to exclude < and > from start and end
fclose($stream);
}
$binaryData = hex2bin($signature);
$seq = Sequence::fromDER($binaryData);
$signed_data = $seq->getTagged(0)->asExplicit()->asSequence();
// ExtendedCertificatesAndCertificates: https://tools.ietf.org/html/rfc2315#section-6.6
$ecac = $signed_data->getTagged(0)->asImplicit(Element::TYPE_SET)->asSet();
// ExtendedCertificateOrCertificate: https://tools.ietf.org/html/rfc2315#section-6.5
$ecoc = $ecac->at($ecac->count() - 1);
$cert = Certificate::fromASN1($ecoc->asSequence());
$commonNameValue = $cert->tbsCertificate()->subject()->toString();
echo $commonNameValue;
}
I've used iText and found it to be very reliable, I highly recommend it.
you can always call the java code as a "microservice" from PHP.
I'm using proc_open to pipe some text over to a perl script for faster processing. The text includes url-encoded strings as well as literal spaces. When a url-encoded space appears in the raw text, it seems to be decoded into a literal space by the time it reaches the perl script. In the perl script, I rely on the positioning of the literal spaces, so these unwanted spaces mess up my output.
Why is this happening, and is there a way to prevent it from happening?
Relevant code snippet:
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
);
$cmd = "perl script.pl";
$process = proc_open($cmd, $descriptorspec, $pipes);
$output = "";
if (is_resource($process)) {
fwrite($pipes[0], $raw_string);
fclose($pipes[0]);
while (!feof($pipes[1])) {
$output .= fgets($pipes[1]);
}
fclose($pipes[1]);
proc_close($process);
}
and a line of raw text input looks something like this:
key url\tvalue1\tvalue2\tvalue3
I might be able to avoid the issue by converting the formatting of my input, but for various reasons that is undesirable, and circumvents rather than solves, the key issue.
Furthermore, I know that the issue is occurring somewhere between the php script and the perl script because I have examined the raw text (with an echo) immediately before writing it to the perl scripts STDIN pipe, and I have tested my perl script directly on url-encoded raw strings.
I've now added the perl script below. It basically boils down to a mini map-reduce job.
use strict;
my %rows;
while(<STDIN>) {
chomp;
my #line = split(/\t/);
my $key = $line[0];
if (defined #rows{$key}) {
for my $i (1..$#line) {
$rows{$key}->[$i-1] += $line[$i];
}
} else {
my #new_row;
for my $i (1..$#line) {
push(#new_row, $line[$i]);
}
$rows{$key} = [ #new_row ];
}
}
my %newrows;
for my $key (keys %rows) {
my #temparray = split(/ /, $key);
pop(#temparray);
my $newkey = join(" ", #temparray);
if (defined #newrows{$newkey}) {
for my $i (0..$#{ $rows{$key}}) {
$newrows{$newkey}->[$i] += $rows{$key}->[$i] > 0 ? 1 : 0;
}
} else {
my #new_row;
for my $i (0..$#{ $rows{$key}}) {
push(#new_row, $rows{$key}->[$i] > 0 ? 1 : 0);
}
$newrows{$newkey} = [ #new_row ];
}
}
for my $key (keys %newrows) {
print "$key\t", join("\t", #{ $newrows{$key} }), "\n";
}
Note to self: always check your assumptions. It turns out that somewhere in my hundreds of millions of lines of input there were, in fact, literal spaces where there should have been url-encoded spaces. It took a while to find them, since there were hundreds of millions of correct literal spaces, but there they were.
Sorry guys!
I want to check the file's size of local drives on windows OS.But the native PHP function filesize() only work when the file size less than 2GB. The file which greater than 2GB will return the wrong number.So,is there other way to get the file size which greater than 2GB?
Thank you very much!!
You can always use the system's file size method.
For Windows:
Windows command for file size only?
#echo off
echo %~z1
For Linux
stat -c %s filenam
You would run these through the exec php command.
PHP function to get the file size of a local file with insignificant memory usage:
function get_file_size ($file) {
$fp = #fopen($file, "r");
#fseek($fp,0,SEEK_END);
$filesize = #ftell($fp);
fclose($fp);
return $filesize;
}
In first line of code, $file is opened in read-only mode and attached to the $fp handle.
In second line, the pointer is moved with fseek() to the end of $file.
Lastly, ftell() returns the byte position of the pointer in $file, which is now the end of it.
The fopen() function is binary-safe and it's apropiate for use even with very large files.
The above code is also very fast.
this function works for any size:
function fsize($file) {
// filesize will only return the lower 32 bits of
// the file's size! Make it unsigned.
$fmod = filesize($file);
if ($fmod < 0) $fmod += 2.0 * (PHP_INT_MAX + 1);
// find the upper 32 bits
$i = 0;
$myfile = fopen($file, "r");
// feof has undefined behaviour for big files.
// after we hit the eof with fseek,
// fread may not be able to detect the eof,
// but it also can't read bytes, so use it as an
// indicator.
while (strlen(fread($myfile, 1)) === 1) {
fseek($myfile, PHP_INT_MAX, SEEK_CUR);
$i++;
}
fclose($myfile);
// $i is a multiplier for PHP_INT_MAX byte blocks.
// return to the last multiple of 4, as filesize has modulo of 4 GB (lower 32 bits)
if ($i % 2 == 1) $i--;
// add the lower 32 bit to our PHP_INT_MAX multiplier
return ((float)($i) * (PHP_INT_MAX + 1)) + $fmod;
}
note: this function maybe litte slow for files > 2gb
(taken from php comments)
If you're running a Linux server, use the system command.
$last_line = system('ls');
Is an example of how it is used. If you replace 'ls' with:
du <filename>
then it will return an integer of the file size in the variable $last_line. For example:
472 myProgram.exe
means it's 472 KB. You can use regular expressions to obtain just the number. I haven't used the du command that much, so you'd want to play around with it and have a look at what the output is for files > 2gb.
http://php.net/manual/en/function.system.php
<?php
$files = `find / -type f -size +2097152`;
?>
This function returns the size for files > 2GB and is quite fast.
function file_get_size($file) {
//open file
$fh = fopen($file, "r");
//declare some variables
$size = "0";
$char = "";
//set file pointer to 0; I'm a little bit paranoid, you can remove this
fseek($fh, 0, SEEK_SET);
//set multiplicator to zero
$count = 0;
while (true) {
//jump 1 MB forward in file
fseek($fh, 1048576, SEEK_CUR);
//check if we actually left the file
if (($char = fgetc($fh)) !== false) {
//if not, go on
$count ++;
} else {
//else jump back where we were before leaving and exit loop
fseek($fh, -1048576, SEEK_CUR);
break;
}
}
//we could make $count jumps, so the file is at least $count * 1.000001 MB large
//1048577 because we jump 1 MB and fgetc goes 1 B forward too
$size = bcmul("1048577", $count);
//now count the last few bytes; they're always less than 1048576 so it's quite fast
$fine = 0;
while(false !== ($char = fgetc($fh))) {
$fine ++;
}
//and add them
$size = bcadd($size, $fine);
fclose($fh);
return $size;
}
To riff on joshhendo's answer, if you're on a Unix-like OS (Linux, OSX, macOS, etc) you can cheat a little using ls:
$fileSize = trim(shell_exec("ls -nl " . escapeshellarg($fullPathToFile) . " | awk '{print $5}'"));
trim() is there to remove the carriage return at the end. What's left is a string containing the full size of the file on disk, regardless of size or stat cache status, with no human formatting such as commas.
Just be careful where the data in $fullPathToFile comes from...when making system calls you don't want to trust user-supplied data. The escapeshellarg will probably protect you, but better safe than sorry.
I am trying to create a PHP script to get the app version from Android APK file.
Extracting XML file from the APK (zip) file and then parsing XML is one way, but I guess it should be simpler. Something like PHP Manual, example #3.
Any ideas how to create the script?
If you have the Android SDK installed on the server, you can use PHP's exec (or similar) to execute the aapt tool (in $ANDROID_HOME/platforms/android-X/tools).
$ aapt dump badging myapp.apk
And the output should include:
package: name='com.example.myapp' versionCode='1530' versionName='1.5.3'
If you can't install the Android SDK, for whatever reason, then you will need to parse Android's binary XML format. The AndroidManifest.xml file inside the APK zip structure is not plain text.
You would need to port a utility like AXMLParser from Java to PHP.
I've created a set of PHP functions that will find just the Version Code of an APK. This is based on the fact that the AndroidMainfest.xml file contains the version code as the first tag, and based on the axml (binary Android XML format) as described here
<?php
$APKLocation = "PATH TO APK GOES HERE";
$versionCode = getVersionCodeFromAPK($APKLocation);
echo $versionCode;
//Based on the fact that the Version Code is the first tag in the AndroidManifest.xml file, this will return its value
//PHP implementation based on the AXML format described here: https://stackoverflow.com/questions/2097813/how-to-parse-the-androidmanifest-xml-file-inside-an-apk-package/14814245#14814245
function getVersionCodeFromAPK($APKLocation) {
$versionCode = "N/A";
//AXML LEW 32-bit word (hex) for a start tag
$XMLStartTag = "00100102";
//APK is esentially a zip file, so open it
$zip = zip_open($APKLocation);
if ($zip) {
while ($zip_entry = zip_read($zip)) {
//Look for the AndroidManifest.xml file in the APK root directory
if (zip_entry_name($zip_entry) == "AndroidManifest.xml") {
//Get the contents of the file in hex format
$axml = getHex($zip, $zip_entry);
//Convert AXML hex file into an array of 32-bit words
$axmlArr = convert2wordArray($axml);
//Convert AXML 32-bit word array into Little Endian format 32-bit word array
$axmlArr = convert2LEWwordArray($axmlArr);
//Get first AXML open tag word index
$firstStartTagword = findWord($axmlArr, $XMLStartTag);
//The version code is 13 words after the first open tag word
$versionCode = intval($axmlArr[$firstStartTagword + 13], 16);
break;
}
}
}
zip_close($zip);
return $versionCode;
}
//Get the contents of the file in hex format
function getHex($zip, $zip_entry) {
if (zip_entry_open($zip, $zip_entry, 'r')) {
$buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
$hex = unpack("H*", $buf);
return current($hex);
}
}
//Given a hex byte stream, return an array of words
function convert2wordArray($hex) {
$wordArr = array();
$numwords = strlen($hex)/8;
for ($i = 0; $i < $numwords; $i++)
$wordArr[] = substr($hex, $i * 8, 8);
return $wordArr;
}
//Given an array of words, convert them to Little Endian format (LSB first)
function convert2LEWwordArray($wordArr) {
$LEWArr = array();
foreach($wordArr as $word) {
$LEWword = "";
for ($i = 0; $i < strlen($word)/2; $i++)
$LEWword .= substr($word, (strlen($word) - ($i*2) - 2), 2);
$LEWArr[] = $LEWword;
}
return $LEWArr;
}
//Find a word in the word array and return its index value
function findWord($wordArr, $wordToFind) {
$currentword = 0;
foreach ($wordArr as $word) {
if ($word == $wordToFind)
return $currentword;
else
$currentword++;
}
}
?>
Use this in the CLI:
apktool if 1.apk
aapt dump badging 1.apk
You can use these commands in PHP using exec or shell_exec.
aapt dump badging ./apkfile.apk | grep sdkVersion -i
You will get a human readable form.
sdkVersion:'14'
targetSdkVersion:'14'
Just look for aapt in your system if you have Android SDK installed.
Mine is in:
<SDKPATH>/build-tools/19.0.3/aapt
The dump format is a little odd and not the easiest to work with. Just to expand on some of the other answers, this is a shell script that I am using to parse out name and version from APK files.
aapt d badging PACKAGE | gawk $'match($0, /^application-label:\'([^\']*)\'/, a) { n = a[1] }
match($0, /versionName=\'([^\']*)\'/, b) { v=b[1] }
END { if ( length(n)>0 && length(v)>0 ) { print n, v } }'
If you just want the version then obviously it can be much simpler.
aapt d badging PACKAGE | gawk $'match($0, /versionName=\'([^\']*)\'/, v) { print v[1] }'
Here are variations suitable for both gawk and mawk (a little less durable in case the dump format changes but should be fine):
aapt d badging PACKAGE | mawk -F\' '$1 ~ /^application-label:$/ { n=$2 }
$5 ~ /^ versionName=$/ { v=$6 }
END{ if ( length(n)>0 && length(v)>0 ) { print n, v } }'
aapt d badging PACKAGE | mawk -F\' '$5 ~ /^ versionName=$/ { print $6 }'