Sharing Memcache with PHP and Python - php

I am trying to share a Memcache key between Python and PHP. Python writes the key and PHP reads it. I am using the Cakephp framework, with php-pecl-memcache (not php-pecl-memcached), and the python-memcache all python library.
Python:
mc = memcache.Client( ["127.0.0.1:11211"])
key = "key1"
value = 1323779849
mc.set(key, value)
PHP:
echo Cache::read('key1', 'memcached');
PHP can't read the variable, I get weird "MemcachePool::get() [http://php.net/memcachepool.get]: Failed to uncompress data" errors; I suspect it has to do with memcached flags that are set differently in each library.
This is what happens when I telnet to memcached:
Python sets key:
get key1
VALUE key1 1 12
1323779849
.
END
PHP sets key:
get key1
VALUE key 1 0 12
1323779849
END
Is there a way to override these flags and just 'do your own thing'?
Are there php/python memcache libraries that play better together?
Alternatively, is there a simple way to create a common memory space between python/php?

Finally got it to work. Lot's of stuff wasn't working as expected.
One problem is that php and python use different flags to do different things.
Not a problem in an all-python or all-php solution, but for inter-environment communication a real problem. A useful resource is http://www.hjp.at/zettel/m/memcached_flags.rxml, which shows that python-memcache flags long integer as '2', which php-memcache does not understand, hence the compression error. I amended python-memcache to include a 'flag-override' in the set function. This variable simply forces a particular flag irrespective of what python memcache thinks it ought to be. This allowed me to re-flag Int from 2 to 0. I will prob branch the current version of python-memcache and submit it to Github. This allowed me to force the python long int flag (2) to something php would understand (0).
CakePhp prior to 1.3.3 stores all keys in memcached with an additional key_expires key, flagged as 768, etc, etc. Without this additional key it cannot find the key you are looking for. Thankfully this behaviour was dumped in later Cakephp version (I simply upgraded to 1.3.13) and it works well now.

When you put something via python memcached, it's probably pickled. So PHP cannot unpickle it. I would try to use some kind of very basic type maybe ctypes? Maybe raw strings?

I had a similar problem, using PHP and pymemcache. I serialized Python dictionary with https://www.php2python.com/wiki/function.serialize/ and wrote that to memcache. PHP side also had it's own way of storing into memcache, and memcache values written by PHP and Python seemed to be the same, but PHP couldn't read Python set value properly, so it puzzled me a lot. PHP read it as a String, being unable to deserialize it / convert it to an Array. Then I got to read memcache values using netcat, like this:
echo -e 'get my-key\r' | nc 192.168.1.17 11211
Python set value returned:
VALUE my-key 0 1460
, while PHP set value had:
VALUE my-key 1 1460
Not knowing how to deal with these flags, I simply used this - on PHP side, if I got a String "a:{s:6..." instead of an Array, I used PHP's unserialize() method to make it an Array and it worked.

Related

PECL stats_rand_gen_normal always returns the same value

With PHP 7.3, I'm trying to use the PECL stats extension: https://pecl.php.net/package/stats
Especially, I'm interested in generating random values following a normal distribution, with the function stats_rand_gen_normal
In my script, the function always returns the same result.
I tried in CLI, to be sure :
php -r "echo(stats_rand_gen_normal(0,1));"
Every execution prints the same number.
So it's a random value which is always the same... What am I missing here?
This seems to me like a bug too and I have make a bug report.
There is a solution on stackoverflow using a custom function.
You should use stats_rand_setall() to seed values to the random generator.

Get PHP Opcodes Dynamically at Runtime

I want to build a PHP extension that can dynamically inspect every opcode generated from a PHP file and do some checking on that.
I came across several websites and found out a couple of functions like zend_set_user_opcode_handler, but I fail to understand how this function can be used to get a complete opcode like ASSIGN !0, 50.
I'm aware of a command like php -d vld.active=1 -d vld.execute=0 -f [filename].php which I can use to generate PHP opcodes, but as far as I know you can only access the opcodes after the PHP program terminates.
What I'd like to get from the extension is an opcode which is obtained one-by-one (dynamically) as the function executes.
Can someone help me with this issue?
You could use parsekit which is available through pecl which can be downloaded from the pecl website or installed with:
sudo pecl install parsekit
Get OPcodes from a string of PHP code during runtime:
You could use the parsekit_compile_string
The syntax for this command is:
array parsekit_compile_string ( string $phpcode [, array &$errors [, int $options = PARSEKIT_QUIET ]] )
Parameters:
phpcode
A string containing phpcode. Similar to the argument to eval().
errors
A 2D hash of errors (including fatal errors) encountered during compilation. Returned by reference.
options
One of either PARSEKIT_QUIET or PARSEKIT_SIMPLE. To produce varying degrees of verbosity in the returned output.
Return Values
Returns a complex multi-layer array structure as detailed below.
An example usage of this is:
<?php
$ops = parsekit_compile_string('
echo "Foo\n";
', $errors, PARSEKIT_QUIET);
var_dump($ops);
?>
The output is too long to include in this answer but is available on the documentation page
Get OPcodes from a PHP file during runtime:
You could use the parsekit_compile_file
Very similar to the above approach but parses a file instead of a string.

PHP $_COOKIE parameter execution

I could not find the reason why my request fail for the following
My php code is:
if (isset($_COOKIE["user"])) {
echo '<p><h3><strong>Welcome '.$_COOKIE["param"].'</strong></h3></p>'; .....
When i request exec('ls -al') as param , the php code did not run the command.
On the response of the request it was like parameterized:
Welcome exec('ls -al')
What may the reason that failed this execution?
$_COOKIE["param"] is a string. You are echoing it. It is not supposed to run anything.
If you wanted to run a command in your PHP, you would have to use eval(). But as for running a command from a cookie value:
DON'T DO IT!
So you're saying that the value of $_COOKIE['param'] is exec('ls -al'), and you're expecting that to run when you echo it out?
That's not how it works. The value of that cookie will be the string value "exec('ls -al')", not the result of the executed code. If you think about it for a second, you'll understand why it would be a bad idea for a cookie to be able to auto-execute code.
It's not really a great idea to be running random commands through exec() anyway, especially if that input came from a user (which cookies do - the user can and will change them to try to attack you).
Instead, you should be using other input that your code can interpret as a signal to run certain code. For example, you could have the param value hold the string list files, and your code would see that value and run exec('ls -al') for you.
You still shouldn't be execing code to do this though, since it's very easy to accidentally run dangerous commands that way. Instead, you should use PHP's built-in functions as much as possible, and only after sanitizing your inputs and only running known values.
For your case, PHP has a bunch of functions that let you interact with the filesystem of your server. Use those to get a list of files on the system instead.

Passing an array from php via command line to R

I have a problem, e am executing a R script from php via command line, and i need to give it two arrays for calculation.
I call the script by running:
Rscript nls.R ??? ???
??? and ??? are my arrays that i need to "give" to R, in order for it to calculate certain values.
Anyone knows how to do this? It is not limited to php, because it is command line - i just need to know if an array can be passed to R via command line and how.
How would R catch it, with what command?
Thanks a lot.
Regards
The command you are looking for is commandArgs() .
Now, if you have for example a list if integers separated by commas in a string, you can get the integers
s = '1,2,3,4,5'
your_list = lapply(strsplit(s, ','), as.numeric)[[1]]
There might be more straight-forward ways achieving this.
EDIT:
better example (should also work with Rscript)
$ R "1,2,3,4,5"
...
>lapply(strsplit(commandArgs()[[2]], ','), as.numeric)[[1]]
[1] 1 2 3 4 5
Assuming you want to run R in a process of serving a web page, there are some better ways of invoking R than command line; the problem is that R interpreter starts very slow and you are wasting lots of time and CPU power to start it over and over again.
You may for instance make a small R server with triggr and talk to it using a client made with PHP sockets.
The simpler yet heavier idea is to make an rApache app and either talk to it with CURL or use it directly as AJAX or even HTML provider.
You'll have to adapt your R script and include a call to commandArgs(). When used with the option trailingOnly=TRUE, it will return a character vector with the space-separated arguments after the call. This will allow you to further manipulate the arguments.
Given a script myscript.r:
#My script
x <- commandArgs(trailingOnly=TRUE)
print(x)
print(str(x))
You can call from the command line Rscript myscript.r 1 2 3 and get
Loading required package: ...
...
[1] "1" "2" "3"
chr[1:3] "1" "2" "3"
NULL
F:\Temp
This gives you the possibility to pass names of text files with your arrays to the Rscript. If I combine different languages, I usually use text files to save intermediate results, it makes things go a bit more smooth.
Beware, if you use any of the options of Rscript (eg --no-save), you have to put them before the script, eg Rscript --no-save myscript.r
You can't pass such things (well, not easily) to Rscript. Rscript has the -e option, of which there can be more than one, which are R expressions. So you could get PHP to produce a character string that is an R expression creating your arrays, and pass each expression to create an array via separate -e arguments.
You can also pass in command line arguments that the R function commandArgs() can grab and make available for you. See an example here, but you may have to play around with how the arguments get pass in and evaluated by R.
Depending on the size of the arrays, the above more than likely won't be useful. In which case you will have to look at other ways of communicating with R than via Rscript.

mssql_bind empty string converting to NULL

I am currently using SQL Server 2000 Stored Procedures with PHP. Following the PHP doc, I use mssql_bind to assign value of parameters and then execute the Stored Procedure.
The problem is that I got this bug which prevents me to bind empty strings to parameters (they are converted to NULL when the Stored Proc gets called)
I dont't want to have to convert every parameter inside the Stored Procedures to check if its NULL then convert back to an empty string. I want to be able to use empty strings as well as NULL which both have their own meaning.
Does anyone know a workaround for this in PHP ? PHP bugs website isn't very clear if that bug is fixed or when it will be fixed, I use PHP 5.2.11 (the lastest version from the 5.2 branch)
Assuming you do not want to do what you suggested, options left to you are
Download a cvs snapshot of php and install it if viable, see if it is fixed. If not viable or fixed via cvs then...
Use system() or exec() calls to use the stored procedures. If too much a hassle then...
Don't use stored procedures, do your functionality in php or other scripting code.
Alter the stored procedure to accept another value for '' strings and convert THAT to a '' string.
Do what you didn't want to do. Harsh :P But I do not see another way.
The bug #44325 proposed a patch to solve the problem, but it was not a correct solution, as it seems the problem is in ntwdblib.dll, and not in the code of the php_mssql extension.
See the comment from alexr at oplot dot com :
I'm sorry. This bug is not fixed. This
is a bug of the ntwdblib.dll. And
after latest updates the bug is
return.
When I bind a empty string, the stored
procedure received a chr(0) char
instead a empty string.
Please roll back last fixes. This bug
is irrecoverable.
Considering this, I'm not sure there's much that could be done on the PHP side :-(
Last time I worked with PHP+MSSQL on Windows, I had quite a lot of problems, like some quite similar to this one, actually ;-(
Maybe a possible solution, for you, might be to switch to the newer SQL Server Driver for PHP driver ? Note that is only works on Windows, though...
I personally don't have a MSSQL server available to test but have you tried using PDO instead of mssql directly?
PDOStatement->bindValue( mixed $parameter , mixed $value [, int $data_type ] )
bindValue()
Yes, I realize that PDO is only a wrapper but who knows, could work! :)
I have a solution that will work.
I am using ADODB (but that doesnt matter) and I have hacked the mssql driver (adodb-mssql.inc.php in the adodb5 drivers folder).
here is the code
if($var === ''){
//stupid hack to prevent mssql driver from converting empty strings to null. now they arent empty strings but they will get trimmed down to legth 0 ;-)
$var = ' ';
$type = SQLVARCHAR;
$isNull = false;
$maxLen = 0;
}
simply check if you are trying to bind an empty string and if you are change it to be non empty. it doesn't matter what value you use I just use a space.
make the type a sqlvarchar isnull should be false and now the trick is to make maxlen 0 so that the mssql driver will trim your string to an empty string.
those variables should get passsed to the mssql_bind function if that wasn't obvious.

Categories