PHP url - Is this a viable hack? - php

Following on from this question, i realised you can only use $POST when using a form...d'oh.
Using jQuery or cURL when there's no form still wouldn't address the problem that i need to post a long string in the url.
Problem
I need to send data to my database from a desktop app, so figured the best way is to use the following url format and append the data to the end, so it becomes:
www.mysite.com/myscript.php?testdata=somedata,moredata,123,xyz,etc,etc,thisgetslong
With my previous script, I was using $GET to read the [testdata=] string and my web host told me $GET can only read 512 chars, so that was the problem.
Hack
Using the script below, I'm now able to write thousands of characters; my question, is this viable or is there a better way?
<?
include("connect.php"); //Connect to the database
//hack - read the url directly and search the string for the data i need
$actual_link = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$findme = '=';
$pos = strpos($actual_link, $findme) + 1; //find start of data to write
$data = substr($actual_link, $pos); //grab data from url
$result = mysql_query("INSERT INTO test (testdata) VALUES ('$data')");
// Check result
if ($result) {echo $data;}
else echo "Error ".$mysqli->error;
mysql_close(); ?>
Edit:
Replaced image with PHP code.
I've learned how not to ask a question - don't use the word hack as it riles peoples feathers and don't use an image for code.
I just don't get how to pass a long string to a formless PHP page and whilst i appreciate people's responses, the answers about cURL don't make sense to me. From this page, it's not clear to me how you'd pass a string from a .NET app for example. I clearly need to do lots of research and apologise for my asinine question(s).

The URL has a practical fixed limit of ~2000 chars, so you should not be passing thousands of chars into the URL. The query portion of the URL is only meant to be used for a relatively short set of parameters.
Instead, you can build up a request body to send via cURL/jQuery/etc for POSTing. This is how a browser will submit form data, and you should probably do the same.

In your scenario, there are two important elements that you need to examine.
First, what is the client that is performing the http operation? I can't tell from your text if the client is going to be a browser, or an application. The client is whatever you have in your solution that is going to be invoking a GET or POST operation.
This is important. When you read about query string length limitations online, it's usually within the context of someone using a browser with a long URL. There is no standard across browsers for maximum URL length. But if you think about it in practical fashion, you'd never want to share an immensely large URL by posting it somewhere or sending it in an e-mail; having to do the cut-and-paste into a client browser would frustrate someone pretty quickly. On the other hand, if the client is an application, then it's just two machines exchanging data and there's really no human factor involved.
The second point to examine is the web server. The web server implementation may pose limitations on URL length, or maybe not. Again, there is no standard.
In any event, if you use a GET operation, your constraint will be the minimum of what both your client AND server allow (i.e. if both have no limit, you have no limit; if either has a limit of 200 bytes, your limit is 200 bytes; if one has a 200 byte limit and the other has a 400 byte limit, your limit is 200 bytes)
Taking a look back, you mentioned "desktop app" but have failed to tell us what language you're developing in, and what operating system. It matters -- that's your CLIENT.
Best of luck.

Related

Need to parse unfiltered url querys via PHP, can't deal with '&' signs

first of all: I'm not a professional php developer, I'm just able to scramble together a few bits of code to make basic stuff work.
I also don't know how to properly name all that stuff, so let me give you some background:
A client of ours wants to send an email containing a link to a vcard qr-code, that contains contact details of their clients to every client they have (between 100-5000 clients possibly).
They don't want to do this by hand so they asked me for an automation solution.
They have a marketing tool that allows them to send mass emails containing the customers details.
So entering 'Hello %name%' in the emails text will be replaced with each customers name in their respective email.
So I found an api that does what they need, it takes url query strings to generate a vcard qr-code (as png file).
I made a script that takes custom query strings, some of them are being sent to said api, some of them are just being embed on the page, so people can print the qr-code including some extra information they need.
The whole system will be used as a "entry-ticket-system" for an event they are hosting, that being said, no high requirements, those tickets are free, our customer wants to use the v-card qr code so they can scan the "tickets" on entry and verify who was actually there, to target them with marketing campaigns later on.
Now to get to the technical part:
This is the api we are using:
https://qrcode.tec-it.com/en/VCard
The way we are currently using it, is by displaying the qr-code in html (<img src="https://qrcode.tec-it.com/API/QRCode?data=BEGIN%3aVCARD%0d%0aVERSION%3a2.1%0d%0aN%3aJohn+Doe%0d%0aTEL%3bHOME%3bVOICE%3a555-555-5555%0d%0aTEL%3bWORK%3bVOICE%3a666-666-6666%0d%0aEMAIL%3aemail%40example.com%0d%0aORG%3aTEC-IT%0d%0aURL%3ahttps%3a%2f%2fwww.example.com%0d%0aEND%3aVCARD&backcolor=%23ffffff" />) and then entering the url query strings as a variable.
This looks something like this:
$fname = filter_var($_GET['fname'], FILTER_SANITIZE_STRING);
$lname = filter_var($_GET['lname'], FILTER_SANITIZE_STRING);
$email = filter_var($_GET['email'], FILTER_SANITIZE_EMAIL);
$fullname = $fname . ' ' . $lname;
echo '<br><img src="https://qrcode.tec-it.com/API/QRCode?data=BEGIN%3aVCARD%0d%0aVERSION%3a2.1%0d%0aN%3a'.$fullname.'%0d%0aEMAIL%3a'.$email. (...)
Now we come to the problem: The email service our customer is using is only able to fill in basic strings, which we cannot modify. So if a client's email would theoretically contain a '&' sign, it would break up the url by indicating a new url query string. We cannot encode them, nor can we do http push.
We can't properly access the data either, we could only export everyting into a csv, modify them and re-import all of their customers (last solution)
Is there any solution for this, so we can accept basically any character within the url. A friend of mine suggested to use a json in the url, however json just has different characters that would break everything.
Everything else does work fine, it's just the '&' sign I'm currently aware of.
PS: I do know that the php code isn't proper code, very low quality. This is okay, the customer is aware of that, they just wanted the cheapest possible solution so they don't have to do it by hand, they have been informed about possible bugs and the very much existing security flaws.
I hope someone can give me a push in the right direction, how could one possibly handle this?
Thanks in advance and apologies for low quality code and possibly unclear explanations, I'm trying my best.

Running preg_replace on html code taking too long

At the risk of getting redirected to this answer (yes, I read it and spent the last 5 minutes laughing out loud at it), allow me to explain this issue, which is just one in a list of many.
My employer asked me to review a site written in PHP, using Smarty for templates and MySQL as the DBMS. It's currently running very slowly, taking up to 2 minutes (with a entirely white screen through it all, no less) to load completely.
Profiling the code with xdebug, I found a single preg_replace call that takes around 30 seconds to complete, which currently goes through all the HTML code and replaces each URL found to its SEO-friendly version. The moment it completes, it outputs all of the code to the browser. (As I said before, that's not the only issue -the code is rather old, and it shows-, but I'll focus on it for this question.)
Digging further into the code, I found that it currently looks through 1702 patterns with each appropriate match (both matches and replacements in equally-sized arrays), which would certainly account for the time it takes.
Code goes like this:
//This is just a call to a MySQL query which gets the relevant SEO-friendly URLs:
$seourls_data = $oSeoShared->getSeourls();
$url_masks = array();
$seourls = array();
foreach ($seourls_data as $seourl_data)
{
if ($seourl_data["url"])
{
$url_masks[] = "/([\"'\>\s]{1})".$site.str_replace("/", "\/", $seourl_data["url"])."([\#|\"'\s]{1})/";
$seourls[] = "$1".MAINSITE_URL.$seourl_data["seourl"]."$2";
}
}
//After filling both $url_masks and $seourls arrays, then the HTML is parsed:
$html_seo = preg_replace($url_masks, $seourls, $html);
//After it completes, $html_seo is simply echo'ed to the browser.
Now, I know the obvious answer to the problem is: don't parse HTML with a regexp. But then, how to solve this particular issue? My first attempt would probably be:
Load the (hopefully, well-formed) HTML into a DOMDocument, and then get each href attribute in each a tag, like so.
Go through each node, replacing the URL found for its appropriate match (which would probably mean using the previous regexps anyway, but on a much-reduced-size string)
???
Profit?
but I think it's most likely not the right way to solve the issue.
Any ideas or suggestions?
Thanks.
As your goal is to be SEO-friendly, using canonical tag in the target pages would tell the search engines to use your SEO-friendly urls, so you don't need to replace them in your code...
Oops ,That's really tough, bad strategy from the beginning , any way that's not your fault,
i have 2 suggestion:-
1-create a caching technique by smarty so , first HTML still generated in 2 min >
second HTMl just get from a static resource .
2- Don't Do what have to be done earlier later , so fix the system ,create a database migration that store the SEO url in a good format or generate it using titles or what ever, on my system i generate SEO links in this format ..
www.whatever.com/jobs/722/drupal-php-developer
where i use 722 as Id by parsing the url to get the right page content and (drupal-php-developer) is the title of the post or what ever
3 - ( which is not a suggestion) tell your client that project is not well engineered (if you truly believe so ) and need a re structure to boost performance .
run

file_get_contents returns different results when called from different servers

I'm running a simple piece of php code, like so:
echo file_get_contents( 'http://example.com/service?params' );
When I run the code on my local machine (at work) or from my shared hosting account, or if I simply open the URL in my browser, I get the following result:
{"instances":[{"timestamp":"2014-02-28 18:03:39.0","ids":[{"id":"525125875"}],"cId":179,"cInstanceId":9264183220}]}
However, when I run the exact same code on either of two different web severs at my workplace, I get the following slightly different result:
{"instances":[{"timestamp":"2014-02-28 18:03:39.0","ids":[{"id":"632572147"}],"cId":179,"cInstanceId":4302001980}]}
Notice how a couple of the numbers are different, and that's all. Unfortunately, these different numbers are the wrong numbers. The result should be identical to the first one.
The server I'm making the call to is external to my workplace.
I've tried altering the file_get_contents call to include headers and masquerade as a browser, but nothing seems to give a different result (well, other than an error due to an accidentally malformed request). I can't use cURL because it's not installed on the servers where this code needs to be deployed.
Any clue what could be causing the differing results? Perhaps something in the request headers? Although I'm not sure why something in the headers would cause the service to return different data.
thanks.
(edit)
The service URL I'm testing with is:
http://iswa.ccmc.gsfc.nasa.gov/IswaSystemWebApp/CygnetLastNInstancesServlet?lastN=1&cygnetId=179&endTimestamp=2014-02-28+21%3A35%3A48
The response it gives is a bit different than what I posted above; I simplified and shortened the responses in my SO post to make it easier to read--but the essential information given, and the differences, are still the same.
I give the service a timestamp, the number of images I want to fetch which were created prior to that timestamp, and a 'cygnetId', which defines what sort of data I want the images to show (solar wind velocity, radiation belt intensity, etc).
The service then echoes back some of the information I gave it, as well as URL segments for the images I requested.
With the returned data, I can build the URL for an image.
Here's the URL for an image built from a "correct" response:
http://iswa.ccmc.gsfc.nasa.gov/IswaSystemWebApp/StreamByDataIdServlet?allDataId=525125875
Here's the URL for an image built from a "wrong" response:
http://iswa.ccmc.gsfc.nasa.gov/IswaSystemWebApp/StreamByDataIdServlet?allDataId=632572147
If you click the links above, you'll see that the "wrong" URL does not open an image--the response is blank.

Request-URI Too Large showing on server

I am passing the following data through url :
<?php
$url = "generate_pdf.php/?feed=" . urlencode(serialize($result));
echo '<div id="left-sidebar">';
echo '<div id="pdf">Download PDF</div>';
echo '</div>';
?>
Here the $result containing the rss feed data in form of array. I am using urlencode(serialize($result) for passing that data through url and its working perfectly on local machine but in server it showing the following error :
Request-URI Too Large
The requested URL's length exceeds the capacity limit for this server.
Please tell me your views to deal with this problem.
I made this mistake (It was more than not knowing than making a mistake!) once. I've build an ajax engine for webapps. It used only the get method. Once I had a form with a lot of data and it did not work.
After some research I found out this: look here
So basically most browser does not make any problems because they support approximately 100.000 characters. But most web-servers like Apache only support 4000 characters from a URL.
No you can not just configure Apache to accept more. It is possible do but you have to edit the source code to do so.
solution: Use the POST method it is made for large data transfer between web-servers and clients(which are most likely browsers).
In your case I think you want to create a pdf with some user input an for some reason that input is larger than 4000 characters.
Store data somewhere on the server (e.g. a database)
Assign a unique ID to such data
Pass that ID in the URL
Retrieve data from storage using the ID as key

How to capture unset REQUEST values in PHP

I'm really unsure if this is even possible but we have an issue where we control an interface that is having XML posted in to it via HTTP post in the form of www.url.com/script.php?xml=<xmlgoeshere>. That is then URL encoded and passed in to us, and we decode and parse it.
Except I have one client who just refuses to url encode their incoming code, which works fine except for when the XML hits an ampersand, at which point everything is being parsed as an end of the xml variable.
www.url.com/script.php?xml=<xmlstart...foo&bar.../>
The end result being that I have XML being POST/GET'd into the xml variable as normal, and then I lose half of the incoming content because of the ampersand.
Now I know that's expected/proper behavior, my question is, is it possible to capture the &bar.../> segment of this code, so that if we hit a known error I can crowbar this into working anyways? I know this is non-ideal but I'm at my wit's end dealing with the outside party.
UPDATE
Ok so I was totally confused. After grabbing the server variables as mentioned below, it looks like I'm not getting the querystring, but that's because on the query they're submitting it has:
[CONTENT_TYPE] => application/x-www-form-urlencoded
[QUERY_STRING] =>
That being the case, is the above behavior still to be expected? Is their a way to get the raw form input in this case? Thanks to the below posters for their help
You'd be hard pressed to do it, if it's even possible, because the fragments of a query string take the format foo=bar with the & character acting as the separator. This means that you'd get an unpredictible $_GET variable created that would take the key name of everything between the & and the next = (assuming there even is one) that would take the value from the = to the next & or the end of the string.
It might be possible to attempt to parse the $_GET array in some way to recover the lost meaning but it would never be all that reliable. You might have more luck trying to parse $_SERVER ['QUERY_STRING'], but that's not guaranteed to succeed either, and would be a hell of a lot of effort for a problem that can be avoided just by the client using the API properly.
And for me, that's the main point. If your client refuses to use your API in the way you tell them to use it, then it's ultimately their problem if it doesn't work, not yours. Of course you should accommodate your clients to a reasonable standard, but that doesn't mean bending over backwards for them just because they refuse to accommodate your needs or technical standards that have been laid down for the good of everyone.
If the only parameter you use is xml=, and it's always at the front, and there are no other parameters, you can do something like this pseudocode:
if (count($_GET)>1 or is_not_well_formed_xml($_GET['xml'])) {
$xml = substr($_SERVER['QUERY_STRING'], 4);
if (is_not_well_formed_xml($xml)) {
really_fail();
}
}
However, you should tell the client to fix their code, especially since it's so easy for them to comply with the standard! You might still get trouble if the xml contains a ? or a #, since php or the web server may get confused about where the query string starts (messing up your $_SERVER['QUERY_STRING'], and either PHP, the client's code or an intermediary proxy or web server may get confused about the #, because that usually is the beginning of a fragment.
E.g., Something like this might be impossible to transmit reliably in a query parameter:
<root><link href="http://example.org/?querystring#fragment"/></root>
So tell them to fix their code. It's almost certainly incredibly easy for them to do so!
UPDATE
There's some confusion about whether this is a GET or POST. If they send a POST with x-www-form-urlencoded body, you can substitute file_get_contents('php://input') for $_SERVER['QUERY_STRING'] in the code above.
YES, Its possible. Using $_SERVER["QUERY_STRING"].
For your url www.url.com/script.php?xml=<xmlstart...foo&bar.../>, $_SERVER["QUERY_STRING"] should contain, xml=<xmlstart...foo&bar.../>;
The following code should extract the xml data.
$pos=strpos($_SERVER["QUERY_STRING"], 'xml');
$xml="";
if($pos!==false){
$xml = substr($_SERVER["QUERY_STRING"], $pos+strlen("xml="));
}
The problem here is that the query string will be parsed for & and = characters. If you know where your = character will be after the "bar" key then you may be able to capture the value of the rest of the string. However if you hit more & you are going to need to know the full content of the incoming message body. If you do then you should be able to get the rest of the content.

Categories