Is there any good Objective-C or Cocoa Bridge/Connector for PHP? I'm interested in Mac development, but want to do it with PHP. It'd be also good if you could recommend me any PHP compiler for Mac.
Note: I already know Titanium-like apps, and that's not what I want.
Thanks.
Looks like there's one here: http://www.slideshare.net/wezfurlong/hot-chocolate-you-got-cocoa-in-my-php
(download link is in the slides)
There's little in PHP that is going to do you any favors with Mac development, though. If you want to do Mac development with a language that has a more familiar syntax and you don't want to deal as much with memory issues and such, doing your coding with MacRuby or RubyCocoa shouldn't be too much of a jump from previous PHP experience.
Unfortunately I wasn't able to get the wezfurlong-Bridge running under Mac OS X Lion. So I decided to use the flexibility of Objective-C to let PHP talk to my Cocoa application, even create objects and send messages with arguments to them.
You can get the source including the (very basic) sample application on http://github.com/cundd/pop/
I "bridge" PHP like this… simplicity is golden.. If you wanna get fancy, JSON encode things back and forth, and send raw data as base64 encoded strings…
- (NSString *)getSomethingFromPHP {
NSString *scriptPath = [[[NSBundle mainBundle]resourcePath]
stringByAppendingPathComponent:#"myPHPscript.php"];
NSString *standardIn = [myApp someData]
NSTask *php = [NSTask new];
NSPipe *pipe = [NSPipe new];
[php setLaunchPath:#"/usr/bin/php"];
[php setArguments:[NSArray arrayWithObjects:
#"-f", scriptPath, standardIn, nil]];
[php setStandardOutput:pipe];
NSFileHandle *handle = [pipe fileHandleForReading];
[php launch];
NSString *string = [[NSString alloc] initWithData:
[handle readDataToEndOfFile] encoding:NSASCIIStringEncoding];
return string;
}
Related
I have an iOS app and PHP web service that take a user submitted "password" and hash it.
The problem arises when you enter an emoji:
PHP hashes the salt + 😍
iOS hashes the salt + [heart-for-eyes smiley emoji]
Is there a way to convert the emoji on iOS to the corresponding HTML Entity (like PHP does automatically) so that the resulting hash values are the same?
stringWithUTF8String does not work
NSNonLossyASCIIStringEncoding converts it to "\ud83d\ude0d"
Here is a solution, perhaps there is a built-in:
NSString *emojiString = #"😍";
NSLog(#"emojiString: %#", emojiString);
NSData *codePointData = [emojiString dataUsingEncoding:NSUTF32LittleEndianStringEncoding];
u_int32_t codePoint = *((u_int32_t *)(codePointData.bytes));
NSString *escapedEmoji = [NSString stringWithFormat:#"&#%d", codePoint];
NSLog(#"escapedEmoji: %#", escapedEmoji);
NSLog output:
emojiString: 😍
escapedEmoji: 😍
This based on the fact that the escaped emoji is the decimal number of the code point. The binary code point is the UTF-32 encoding of the unicode character.
Unfortunately I was not able to find a pre-existing solution.
Preface:
I've a web page with a form and a text field.
1) On submission, the text in the field is sent with ajax to a php script (with GET method).
2) The php script gets the text and passes it as a parameter to a shell tool.
3) The shell C tool parses argc into an array of unichars (actually an NSString in my current implementation)
(4.. 5.. 6.. then the tool does his job, returns a result to stdout that the php script serves back as response to the web page...)
I'm looking for the correct / canonical / "unicode" way to do each step so that: content is properly encoded and preserved, no security issues come out.
What I'm doing now:
1) (JavaScript) the text is retrieved from the form this way
theText = $('#theField').attr('value');
and sent to the server this way
httpReq.open('GET','myScript.php?theText=' + encodeURIComponent(theText),true);
2) (PHP) I get the text
$theText=(isset($_GET["theText"])?$_GET["theText"]:"");
I call the C tool
$cmd = "/usr/bin/thetool -theText ".escapeshellarg($theText);
echo shell_exec( $cmd );
3) (Objective-C) I'm on MacOS X, so I take advantage of NSString and NSUserDefaults classes (but a plain C solution would be good for me as well, assumed that I'll end up with an array of unichars)
int main(int argc, const char * argv[])
{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSString *theText = [userDefaults stringForKey: #"theText"];
Question(s)
Is this the good way?
Is escapeshellarg alone safe when invoking shell_exec?
Am I going to lose some characters along the way if the user types something peculiar?
Waiting from a competent reply, I've started making some empiric tests...
First I changed
echo shell_exec( $cmd );
to
echo $cmd;
to see what the command line invocation was turning out to be given various text entered in the form. It seem that escapeshellarg on the PHP side do a good job.
The text passed to the Tool seems to be always properly sealed between single quotes, with "dangerous" character well escaped. I found no way to tamper with the tool invocation.
Then I tested for the text passed to see if something was getting lost somewhere.
I set up the C tool this way and looked for the output
int main(int argc, const char * argv[])
{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSString *theText = [userDefaults stringForKey: #"theText"];
int i;
unichar c;
for(i=0;i<[theText length];i++)
{
c = [searchString characterAtIndex:(NSUInteger) i];
printf("%d\n",c);
}
return 0;
}
Made various tries. It seems all ok. As the last test I entered a "MUSICAL SYMBOL G CLEF" in the form
http://www.fileformat.info/info/unicode/char/1d11e/index.htm
It turned out to correctly end into the tool as a couple* of unichars
55348
56606
(* being this a very special character whose code exceeds 65535 it need to be represented with a couple of surrogate unichars. This is the most edge case I found).
Anyway as I stated at the beginning these are just empiric tests. I don't like to assume that sensible code is good just beacuse passes a dozen of test. I'd very happy to receive comments or suggestions (or warnings!).
I tested on Mac OS X - Firefox on the client side - Mac OS X - Mamp on the server side.
Is it possible to run a Python script within PHP and transferring variables from each other ?
I have a class that scraps websites for data in a certain global way. i want to make it go a lot more specific and already have pythons scripts specific to several website.
I am looking for a way to incorporate those inside my class.
Is safe and reliable data transfer between the two even possible ? if so how difficult it is to get something like that going ?
You can generally communicate between languages by using common language formats, and using stdin and stdout to communicate the data.
Example with PHP/Python using a shell argument to send the initial data via JSON
PHP:
// This is the data you want to pass to Python
$data = array('as', 'df', 'gh');
// Execute the python script with the JSON data
$result = shell_exec('python /path/to/myScript.py ' . escapeshellarg(json_encode($data)));
// Decode the result
$resultData = json_decode($result, true);
// This will contain: array('status' => 'Yes!')
var_dump($resultData);
Python:
import sys, json
# Load the data that PHP sent us
try:
data = json.loads(sys.argv[1])
except:
print "ERROR"
sys.exit(1)
# Generate some data to send to PHP
result = {'status': 'Yes!'}
# Send it to stdout (to PHP)
print json.dumps(result)
You are looking for "interprocess communication" (IPC) - you could use something like XML-RPC, which basically lets you call a function in a remote process, and handles the translation of all the argument data-types between languages (so you could call a PHP function from Python, or vice versa - as long as the arguments are of a supported type)
Python has a builtin XML-RPC server and a client
The phpxmlrpc library has both a client and server
There are examples for both, Python server and client, and a PHP client and server
Just had the same problem and wanted to share my solution. (follows closely what Amadan suggests)
python piece
import subprocess
output = subprocess.check_output(["php", path-to-my-php-script, input1])
you could also do: blah = input1 instead of just submitting an unnamed arg... and then use the $_GET['blah'].
php piece
$blah = $argv[1];
if( isset($blah)){
// do stuff with $blah
}else{
throw new \Exception('No blah.');
}
The best bet is running python as a subprocess and capturing its output, then parsing it.
$pythonoutput = `/usr/bin/env python pythoncode.py`;
Using JSON would probably help make it easy to both produce and parse in both languages, since it's standard and both languages support it (well, at least non-ancient versions do). In Python,
json.dumps(stuff)
and then in PHP
$stuff = json_decode($pythonoutput);
You could also explicitly save the data as files, or use sockets, or have many different ways to make this more efficient (and more complicated) depending on the exact scenario you need, but this is the simplest.
For me the escapeshellarg(json_encode($data)) is giving not exactly a json-formatted string, but something like { name : Carl , age : 23 }.
So in python i need to .replace(' ', '"') the whitespaces to get some real json and be able to cast the json.loads(sys.argv[1]) on it.
The problem is, when someone enters a name with already whitespaces in it like "Ca rl".
I have been following this great tutorial and got my codes to working with most of the database transfers. Now I'd like to use the same method to update long text messages and images onto my server MySQL database, but it doesn't seem to work.
NSString *strURL = [NSString stringWithFormat:#"http://mydomain.com/sync.php?name=%#&message=%#&image=%#",nameField.text, messageField.text, image];
and then
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]];
NSString *strResult = [[[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding] autorelease];
NSLog(#"StrResult is... %#", strResult);
Problem 1: When the messageField.text is a long text with blank spacing in between such as "This is a free text format with up to 1000 characters..." , it will cause strURL to have blank spaces as well, and thus strResult will become null.
Problem 2: image is of blob format which I already saved in the local sqlite. I'm not even sure if transferring this way is a good idea. But basically I want to upload the image from iPhone/iPad straight onto a server MySQL database.
Hope someone could help me with either one of these 2 problems. Or are there any better and easier alternatives to update MySQL on my server? Thank you!
Problem 1 : When you are sending parameters through a GET request, you need to escape your parameters to avoid illegal characters. By the way, you can not send unlimited data with this kind of request. For a large amount of data, you should rather use a POST request.
Problem 2 : ASIHTTPRequest is a wrapper used to communicate with remote servers. If you choose to use it (I encourage you to do), here is the documentation that you will need to POST a request . There is also an example to send an image to a remote server with NSData.
Problem 1: there's a lot of ways to do this... one of them are when you put it into the database do this:
messageField.text = [messageField.text stringByReplacingOccurrencesOfString:#" " withString:#"_"];
Maked the text: "This is a free text format with up to 1000 characters..." to: "This_is_a_free_text_format_with_up_to_1000_characters..."
And then when you take it out of the database again use the code opposite:
messageField.text = [messageField.text stringByReplacingOccurrencesOfString:#"_" withString:#" "];
That makes it from: "This_is_a_free_text_format_with_up_to_1000_characters..." to "This is a free text format with up to 1000 characters..."
But remember thats one way to do it... you can also replace the "_" with Something else like"I" or whatever you want.. something the user won't type...
Problem 2: I don't know a lot about databases and images.. but se this: Blob
:)
I have to deserialize a dictionary in PHP that was serialized using cPickle in Python.
In this specific case I probably could just regexp the wanted information, but is there a better way? Any extensions for PHP that would allow me to deserialize more natively the whole dictionary?
Apparently it is serialized in Python like this:
import cPickle as pickle
data = { 'user_id' : 5 }
pickled = pickle.dumps(data)
print pickled
Contents of such serialization cannot be pasted easily to here, because it contains binary data.
If you want to share data objects between programs written in different languages, it might be easier to serialize/deserialize using something like JSON instead. Most major programming languages have a JSON library.
Can you do a system call? You could use a python script like this to convert the pickle data into json:
# pickle2json.py
import sys, optparse, cPickle, os
try:
import json
except:
import simplejson as json
# Setup the arguments this script can accept from the command line
parser = optparse.OptionParser()
parser.add_option('-p','--pickled_data_path',dest="pickled_data_path",type="string",help="Path to the file containing pickled data.")
parser.add_option('-j','--json_data_path',dest="json_data_path",type="string",help="Path to where the json data should be saved.")
opts,args=parser.parse_args()
# Load in the pickled data from either a file or the standard input stream
if opts.pickled_data_path:
unpickled_data = cPickle.loads(open(opts.pickled_data_path).read())
else:
unpickled_data = cPickle.loads(sys.stdin.read())
# Output the json version of the data either to another file or to the standard output
if opts.json_data_path:
open(opts.json_data_path, 'w').write(json.dumps(unpickled_data))
else:
print json.dumps(unpickled_data)
This way, if your getting the data from a file you could do something like this:
<?php
exec("python pickle2json.py -p pickled_data.txt", $json_data = array());
?>
or if you want to save it out to a file this:
<?php
system("python pickle2json.py -p pickled_data.txt -j p_to_j.json");
?>
All the code above probably isn't perfect (I'm not a PHP developer), but would something like this work for you?
I know this is ancient, but I've just needed to do this for a Django 1.3 app (circa 2012) and found this:
https://github.com/terryf/Phpickle
So just in case, one day, someone else needs the same solution.
If the pickle is being created by the the code that you showed, then it won't contain binary data -- unless you are calling newlines "binary data". See the Python docs. Following code was run by Python 2.6.
>>> import cPickle
>>> data = {'user_id': 5}
>>> for protocol in (0, 1, 2): # protocol 0 is the default
... print protocol, repr(cPickle.dumps(data, protocol))
...
0 "(dp1\nS'user_id'\np2\nI5\ns."
1 '}q\x01U\x07user_idq\x02K\x05s.'
2 '\x80\x02}q\x01U\x07user_idq\x02K\x05s.'
>>>
Which of the above looks most like what you are seeing? Can you post the pickled file contents as displayed by a hex editor/dumper or whatever is the PHP equivalent of Python's repr()? How many items in a typical dictionary? What data types other than "integer" and "string of 8-bit bytes" (what encoding?)?