I'm working on a bridge-like solution to communicate from an HbbTV-application with some Philips Hue lights (correctly with the gateway-hardware).
As the process is moving forward and the system was working, I'm now at the point that I use a plugin for Firefox that simulates a TV with HbbTV. To do so, I start an apache via XAMPP, on this i have my files which are loaded into Firefox.
Since I did that, I can't send any POST-requests to he Philips gateway, what is correct due same origin policy. I have no access to settings on Philips Hue and so my workarround has to be from clientside only.
My actual try looks like this:
var stringState = "http://" + this.Ip + "/api/" + this.UserId + "/lights/" + this.LightId;
var httpxml = new XMLHttpRequest();
var valueRequest;
console.log("in GetState:" + this.LightId);
httpxml.onreadystatechange = function() {
if (httpxml.readyState == XMLHttpRequest.DONE) {
valueRequest = JSON.parse(httpxml.responseText);
console.log(valueRequest);
console.log(valueRequest.state.on);
that.switchState(valueRequest.state.on);
}
}
httpxml.open('GET',stringState,true);
httpxml.withCredentials = true;
httpxml.setRequestHeader("Content-Type", "application/json");
httpxml.send();
I'm pretty new to developing in JavaScript and Web. I hope someone could lead me on the right road, with some advice and maybe a clear example.
Best regards
Adrian
One of the P-s in XAMPP is for PHP. So a workaround you can do is hosting a PHP page right next to your HTML one (and there will not be any issues with CORS), and let it do the job.
Something like
<?php
$ip=$_REQUEST['ip'];
$user=$_REQUEST['user'];
$light=$_REQUEST['light'];
$ch=curl_init("http://".$ip."/api/".$user."/lights/".$light);
curl_exec($ch);
curl_close($ch);
This is far from anything safe and nice, but may help to get started. Some trivial clues: variables start with $, and . is the operator for string concatenation. $_REQUEST is an array which gets the url parameters, what you should supply in your modified request (where xy.php is the filename of the PHP page):
var stringState = "xy.php?ip=" + this.Ip + "&user=" + this.UserId + "&light=" + this.LightId;
curl is a utility for issuing web requests (you can find it in your XAMPP folders, xampp\apache\curl.exe), and it has bindings for PHP. https://curl.haxx.se/. By default it returns whatever your contoller provides, so the JSON should pass-through. Content-type may or may not be an issue, if it does not work, you can try putting a header("Content-Type: application/json"); right before the curl_exec line.
Related
With some help from this thread I came up with the code below. How can I fetch the Google Drive file ID, open the direct link to the file and snatch the virus scan confirm ID that is required to stream files over 100 MB and then puzzle back the link? I'm kind of stuck at the xhr part.
function fixGoogleDriveURL(url) {
if (url.indexOf('drive.google.com') !== -1) {
var DocIDfull = url;
var DocIDstart = DocIDfull.indexOf('open?id=');
if (DocIDstart == -1) {
// invalid
return url;
}
var DocID = DocIDfull.slice(DocIDstart+8);
url = 'https://drive.google.com/uc?export=download&id=' + DocID;
var xhr = new XMLHttpRequest();
xhr.onload = function () {
if (xhr.readyState === xhr.DONE) {
if (xhr.status === 200) {
var token = xhr.responseText.match("/confirm=([0-9A-Za-z]+)&/");
window.location.replace(url + '&confirm=' + token[1]);
// should I add url += '&confirm=' + token[1] here instead of window.location?
}
}
};
xhr.open("GET", url);
xhr.send();
}
return url;
}
console.log(fixGoogleDriveURL('https://drive.google.com/open?id=1C25uoL6nIqqNhex3wm8VwODsO2q2pXBt') + "\n<-- should output:\nhttps://drive.google.com/uc?export=download&id=1C25uoL6nIqqNhex3wm8VwODsO2q2pXBt&confirm=XXXXX");
Scraping GDrive using Client-Side JavaScript isn't explicitly allowed by Google and therefore your Ajax call/XHR fails.
The only way to get around that restriction is by using a proxy in the middle that will forward Google's Website code but add appropriate Access-Control Allow-Origin Headers.
You can either use your own server for that (some minimal server-side script code will do) or you can use a service like http://multiverso.me/AllOrigins/ or https://corsproxy.github.io/ to proxy the request for you.
The AllOrigins site has some example code for use with jQuery, but basically they work by URI encoding the URL you want to access and appending that string to the site's proxy URL.
Here's an article by freecodecamp.org that outlines how to use these services (skip to the Don’t Let CORS Stop You! section.
Note: A security advice: These services are working fine right now, but they could go out of business tomorrow and start serving malicious data instead or redirect your file requests to completely different files or completely different websites altogether. It's up to you to decide if you want to trust these strangers or not.
I have this code (InDesign CS6), and it's not working as expected. I'm using Mac OS and I need to make the code compatible with Windows and Mac.
Trying to get a text/JSON over my localhost, and the socket return an empty string:-
function getData(host, path) {
var reply = '';
var conn = new Socket;
var request = "GET " + path + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "\n";
if (conn.open (host)) {
conn.write (request);
reply = conn.read(999999);
var close = conn.close();
}
return reply;
}
var host = 'localhost:80';
var path = '/test/test/json.php';
var test = getData(host, path);
alert(typeof(test) + ' Length:' + test.length);
Edit: Finally I manage to find out what causing the problem. I create a VMware, and try to run the script, and it's working. Not sure why it doesn't work on my machine. Download Wireshark, and saw InDesign send the request, but something blocks the request from accessing the server. I will update if I able to detect what causing the block.
When it comes to Socket, I guess the simpliest is to take advantage of that script written by Rorohiko:
https://rorohiko.blogspot.fr/2013/01/geturlsjsx.html
Or have a try with IDExtenso library:
https://github.com/indiscripts/IdExtenso
I find those convenient as they deal with the inner socket mechanisms for you.
You do not need to use a socket just to get JSON from your server.
Instead refer to the XMLHttpRequest documentation or just a library such as jQuery which greatly simplifies making Ajax calls for JSON.
Hi I am using phonegap for crossed plateform development (I use angularJS as JS framework).
I want to use a web service to access to a list of positions from my database (mysql) on my website.
The problem is that the solution I found is not secure at all:
Javascript
var xhr;
if (window.XMLHttpRequest)
xhr = new XMLHttpRequest();
else
xhr = ActiveXObject("Microsoft.XMLHTTP");
xhr.open("GET", "http://localhost:8888/MAMP_Site/0/test.php", true);
xhr.send(null);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 0)) {
console.log("Ready State4: Json Textual Data retrieved");
handleData(xhr.responseText); // Json Textual Data
}
};
function handleData(data)
{
var jsonData;
console.log("ReceivedData from WebService:"+data);
jsonData = eval('(' + data + ')');
$scope.lastUpdate = jsonData[0];
$scope.jsonData = jsonData[1];
$scope.$apply();
}
PHP (used as "web service")
<?php
header('Access-Control-Allow-Origin: *');
header("Content-Type: text/plain");
class UserInfo {
public $id = "";
public $name = "";
public $username = "";
public $timestamp = "";
public function __construct($_id, $_name, $_username, $_timestamp) {
$this->id = $_id;
$this->name = $_name;
$this->username = $_username;
$this->timestamp = $_timestamp;
}
}
$db = mysql_connect('localhost:8889', 'root', 'root');
mysql_select_db('myDbName',$db);
$sql = 'SELECT id,name,username,timestamp FROM positions_test';
$req = mysql_query($sql) or die('Erreur SQL !<br>'.$sql.'<br>'.mysql_error());
$dataArray = array();
while($data = mysql_fetch_assoc($req)) {
$dataArray[]= new UserInfo($data['id'],$data['name'],$data['username'],$data['timestamp']);
}
//Last Modified Time
$sql = "SELECT UPDATE_TIME FROM information_schema.tables WHERE TABLE_SCHEMA = 'myDbName'AND TABLE_NAME = 'positions_test'";
$req = mysql_query($sql) or die('Erreur SQL !<br>'.$sql.'<br>'.mysql_error());
$data = mysql_fetch_assoc($req)["UPDATE_TIME"];
$jsonDataArray = array($data, $dataArray);
echo json_encode($jsonDataArray);
mysql_close();
?>
Basically the PHP return a JSON (as text), and I get it (as text) in my JS. Then I evaluate it as a JSON.
The question
Security concern
As the application is made with cordova, all JS and Html source code can be viewed and so the URL of my php "web service". It means that anybody who have the adress can access to the Json File. Even if this data is public (in my case) I want it to be only accessible from my app (this way I can for instance avoid a bot to store all of this data and spam).
Token or user-agent
As there is no authentification for users is there any way for my webservice to know where the request come from?
I thought using a token to ensure that the request come from my app but once again as the source code can be viewed, anybody could see the token or the code to generate it.
Maybe using user-agent to know if it is accessed from a mobile device?
Other port than 80
Maybe it would be judicious to choose another port than 80 to connect to my web service, but how can I select my connexion port?
Best practice
The main point would actually be, what are the best practice for web services on phonegap (cordova) ?
Should I use SSL, Https?
Should I use a real web service instead of a simple php page and XMLHTTPRequest? If yes, which one?
And of course how building properly and securely my web service ?
I know this is a long post, but I searched the web a for while and I found a lot of interesting stuff but nothing really concret on the best practices to build your web services for a phonegap application (with no user authentification)
You could try to obfuscate it, or a a lot of other things, but in the end you have to receive it in the client side and therefore there is nothing you can do to fully prevent him from reading your data, seeing your client side code or spamming your service.
The best you can do to make sure that the service is safe is: make sure the connection to the db does not allow writes, all the software involved is updated regularly and that the queries sent to your service have the syntax and content that you are expecting.
Which is the best method to make the browser use cached versions of js files (from the serverside)?
Have a look at Yahoo! tips: https://developer.yahoo.com/performance/rules.html#expires.
There are also tips by Google: https://developers.google.com/speed/docs/insights/LeverageBrowserCaching
or in the .htaccess file
AddOutputFilter DEFLATE css js
ExpiresActive On
ExpiresByType application/x-javascript A2592000
I just finished my weekend project cached-webpgr.js
which uses the localStorage / web storage to cache JavaScript files. This approach is very fast. My small test showed
Loading jQuery from CDN: Chrome 268ms, FireFox: 200ms
Loading jQuery from localStorage: Chrome 47ms, FireFox 14ms
The code to achieve that is tiny, you can check it out at my Github project https://github.com/webpgr/cached-webpgr.js
Here is a full example how to use it.
The complete library:
function _cacheScript(c,d,e){var a=new XMLHttpRequest;a.onreadystatechange=function(){4==a.readyState&&(200==a.status?localStorage.setItem(c,JSON.stringify({content:a.responseText,version:d})):console.warn("error loading "+e))};a.open("GET",e,!0);a.send()}function _loadScript(c,d,e,a){var b=document.createElement("script");b.readyState?b.onreadystatechange=function(){if("loaded"==b.readyState||"complete"==b.readyState)b.onreadystatechange=null,_cacheScript(d,e,c),a&&a()}:b.onload=function(){_cacheScript(d,e,c);a&&a()};b.setAttribute("src",c);document.getElementsByTagName("head")[0].appendChild(b)}function _injectScript(c,d,e,a){var b=document.createElement("script");b.type="text/javascript";c=JSON.parse(c);var f=document.createTextNode(c.content);b.appendChild(f);document.getElementsByTagName("head")[0].appendChild(b);c.version!=e&&localStorage.removeItem(d);a&&a()}function requireScript(c,d,e,a){var b=localStorage.getItem(c);null==b?_loadScript(e,c,d,a):_injectScript(b,c,d,a)};
Calling the library
requireScript('jquery', '1.11.2', 'http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js', function(){
requireScript('examplejs', '0.0.3', 'example.js');
});
From PHP:
function OutputJs($Content)
{
ob_start();
echo $Content;
$expires = DAY_IN_S; // 60 * 60 * 24 ... defined elsewhere
header("Content-type: x-javascript");
header('Content-Length: ' . ob_get_length());
header('Cache-Control: max-age='.$expires.', must-revalidate');
header('Pragma: public');
header('Expires: '. gmdate('D, d M Y H:i:s', time()+$expires).'GMT');
ob_end_flush();
return;
}
works for me.
As a developer you'll probably quickly run into the situation that you don't want files cached, in which case see Help with aggressive JavaScript caching
In your Apache .htaccess file:
#Create filter to match files you want to cache
<Files *.js>
Header add "Cache-Control" "max-age=604800"
</Files>
I wrote about it here also:
http://betterexplained.com/articles/how-to-optimize-your-site-with-http-caching/
I am heavily tempted to close this as a duplicate; this question appears to be answered in many different ways all over the site:
will a script in html's script tag with extension php be cached?
When does browser automatically clear cache of external JavaScript file?
Help with aggressive JavaScript caching
How to control web page caching, across all browsers?
How can I make the browser see CSS and Javascript changes?
The best (and only) method is to set correct HTTP headers, specifically these ones: "Expires", "Last-Modified", and "Cache-Control". How to do it depends on the server software you use.
In Improving performance… look for "Optimization on server side" for general considerations and relevant links and for "Client-side cache" for the Apache-specific advice.
If you are a fan of nginx (or nginx in plain English) like I am, you can easily configure it too:
location /images {
...
expires 4h;
}
In the example above any file from /images/ will be cached on the client for 4 hours.
Now when you know right words to look for (HTTP headers "Expires", "Last-Modified", and "Cache-Control"), just peruse the documentation of the web server you use.
I have a simple system that is pure JavaScript. It checks for changes in a simple text file that is never cached. When you upload a new version this file is changed. Just put the following JS at the top of the page.
(function(url, storageName) {
var fromStorage = localStorage.getItem(storageName);
var fullUrl = url + "?rand=" + (Math.floor(Math.random() * 100000000));
getUrl(function(fromUrl) {
// first load
if (!fromStorage) {
localStorage.setItem(storageName, fromUrl);
return;
}
// old file
if (fromStorage === fromUrl) {
return;
}
// files updated
localStorage.setItem(storageName, fromUrl);
location.reload(true);
});
function getUrl(fn) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", fullUrl, true);
xmlhttp.send();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState === XMLHttpRequest.DONE) {
if (xmlhttp.status === 200 || xmlhttp.status === 2) {
fn(xmlhttp.responseText);
}
else if (xmlhttp.status === 400) {
throw 'unable to load file for cache check ' + url;
}
else {
throw 'unable to load file for cache check ' + url;
}
}
};
}
;
})("version.txt", "version");
just replace the "version.txt" with your file that is always run and "version" with the name you want to use for your local storage.
I am trying to find the distance between two locations. For that I used Google web services. I got a JSON response from that web service, but I am unable to get the distance from that JSON response in a javascript function.
See my code below:
function myjourneysubdetails(){
var fp = jQuery('#fp').val();
var tp = jQuery('#tp').val();
var city = jQuery('#city').val();
alert(fp);
$.ajax({
type : 'GET',
url : 'http://maps.googleapis.com/maps/api/distancematrix/json?origins=Silk board&destinations=marathahalli&language=en-US&sensor=false',
async: false,
success : function(data) {
alert("Success");
var locObject = eval('(' + JSON.stringify(data) + ')');
alert("locObject: "+locObject);
alert("Destination: "+locObject.destination_addresses);
var origins = data.origin_addresses;
var destinations = data.destination_addresses;
alert('destinations'+destinations);
for (var i = 0; i < origins.length; i++) {
var results = data.rows[i].elements;
for (var j = 0; j < results.length; j++) {
var element = results[j];
var distance = element.distance.text;
var duration = element.duration.text;
var from = origins[i];
var to = destinations[j];
alert('distance'+distance);
}
}
},
error : function(xhr, type) {
alert('Internal Error Occoured! '+xhr+' : '+type);
}
});
}
Thanks in advance.
The problem you're having is called the "same origin policy" of web browsers.
Basically, as one of numerous security measures implemented by web browsers (and one of the earliest to be proposed and implemented) you are not allowed to make ajax requests to a domain which is different from the url of the web page. So, the only way for your code to work as is is if you can manage to convince google to host your page on the maps.googleapis.com domain.
Obviously that won't work. There are several work-arounds to this. The current most popular method is JSONP. Unfortunately google maps does not support JSONP. There are several other methods such as using flash or java applets to forward the request for you. But the simplest, most compatible method is the original solution to this problem: proxy the request on your server.
The reason proxying works is because programming languages and web servers, unlike web browsers, don't care where you connect to on the internet. There are several ways you can do this. You can either write a web app to do the proxying (an example is this simple proxy in PHP: https://github.com/cowboy/php-simple-proxy/) or configure your web server to proxy your request (for example using apache mod_proxy or mod_rewrite) or you can use a dedicated proxy server installed on your server.
So for example, in your code you should really be doing this:
$.ajax({
type : 'GET',
url : 'http://myserver.com/proxy/distancematrix/json?origins=Silk board&destinations=marathahalli&language=en-US&sensor=false',
And then configure your server to forward that request with something like this:
# Example of Apache mod_rewrite proxying:
RewriteEngine on
RewriteRule ^/proxy/(.*) http://maps.googleapis.com/maps/api/$1 [P]
A word of warning:
However you do it, remember that this is the internet. Do not write an open proxy. If you do you run the risk of hackers using your proxy to forward spam, DOS attacks etc. and you'll get the blame because it would appear to come from your server. The best way to prevent this is to hardcode the proxy url to google maps so that people can't use your server to connect to anywhere else. Just forward the query parameters, not the whole url.