In snippets plugin, I have added the following code ;
add_action( 'wp_head', function () { ?>
<script>
function createCookie(cookieName,cookieValue,daysToExpire) {
var date = new Date();
date.setTime(date.getTime()+(daysToExpire*24*60*60*1000));
document.cookie = cookieName + "=" + cookieValue + "; expires=" + date.toGMTString() + "; path=/; domain=humanistperspectives.org; secure";
}
function accessCookie(cookieName) {
var name = cookieName + "=";
var allCookieArray = document.cookie.split(';');
for(var i=0; i<allCookieArray.length; i++) {
var temp = allCookieArray[i].trim();
if (temp.indexOf(name)==0)
return temp.substring(name.length,temp.length);
}
return "";
}
function getCookie(cookieName) {
let cookie = {};
document.cookie.split(';').forEach(function(el) {
let [key,value] = el.split('=');
cookie[key.trim()] = value;
})
return cookie[cookieName];
}
function delCookie(cookieName) {
cookieValue = "";
var date = new Date();
date.setTime(date.getTime()-(3600));
document.cookie = cookieName + "=" + cookieValue + "; expires=" + date.toGMTString() + "; path=/; domain=humanistperspectives.org; secure";
}
</script>
<?php } );
This sets a cookie and sets the file and title that displays on the front page of our site.
When I inspect the same page in browsers on my mac (safari, firefox, chrome), I see that the cookies are all set, expiring in september of this year.
Here are the values of the cookie:
Name: issuecover
Value: /wp-content/uploads/2022/03/220.jpg
Domain: .domain.org
Expires: Sept 5, 2022
Size: 45
HttpOnly: false
Secure: true
Samesite: None;
Last accessed: Tue, May 17, 2022
The same values appear in Windows in firefox, chrome and edge — but in Windows, despite having the same cookie values, the site doesn't seem to be able to access the cookies. So the magazine cover is a blank image and the title is blank, etc — but I see when I inspect that yes, in fact, the cookie is set just like on my mac.
It's just that on the mac, every browser is able to access the values and display the appropriate text/image and on windows, the same cookies are not accessible to the browsers.
Does anyone know if Windows is more picky regarding cookies?
NOTE: the site is on Cloudflare and strangely, if I purge the cache and force refresh in windows, the information in the cookie is accessible to the browsers.. but only at that time. If I come back a few hours later... despite seeing the cookies being still active in the browsers, the information in the cookies won't display on the page after the first time.
I appreciate any help here..thanks very much!
EDIT: I added code to add SameSite=Lax and on Mac, that shows up, but on Windows, SameSite=None still.
document.cookie = cookieName + "=" + cookieValue + "; expires=" + date.toGMTString() + "; path=/; domain=domain.org; secure; SameSite=Lax;";
UPDATE:
ACTUALLY, I noticed there was a javascript error from another plugin and when I removed it, and purged the cache, the cookie's samesite lax status actually transferred over in Windows and the cookies were readable/accessible on the page. However, the true test is to check back in 1-2 hours and see if it's still behaving how I want. I'll come back with the details. THANKS.
BAD NEWS :
So going back to the site, the cookies AGAIN, despite being there, with samesite=lax, are somehow not accessible to the page and their values can't display.
httponly is false... it SHOULD show up. Why is this not working in Windows? Both Mac and Windows have the cookies properly stored but only on Mac do they appear on the page. HELP!
FINAL UPDATE
I've removed the cookies and used global variables to select different issues and relevant content.
For some reason, it seems like Cloudflare is caching cookies.
So thanks for your help everyone!
I removed all cookie-related code and ended up with a much simpler and faster code with global variables.
Thanks everyone!
I am developing a rails app (I am a student) and I am trying to make a cookie that stores the users location which is found through the javascript geo location api. However, the cookie works perfectly in chrome but not safari or Firefox. I looked in the inspector and the cookie was there for chrome but not the other two. The code for the cookie is below. The rest of the code is written in ruby. The point of the cookie is so that I can get the users recent location in the controller.
<%if #lat_lng.nil? %>
<script>
getGeoLocation();
function getGeoLocation() {
navigator.geolocation.getCurrentPosition(setGeoCookie);
}
function setGeoCookie(position) {
var expiration = new Date();
expiration.setDate(expiration.getDate()+1);
var cookie_val = position.coords.latitude + "|" + position.coords.longitude;
document.cookie = "lat_lng=" + escape(cookie_val); expires= 'expiration.toGMTString()';
}
</script>
<% end %>
The cookie is defined in my applications controller:
#lat_lng = cookies[:lat_lng]
I really appreciate any help that is possible!
When you are setting the cookie, it should be in the following format:
document.cookie = "some=value; expires=Mon, 1 Jan 2000 12:59:59 GMT";
In your case, you are simply defining a variable in javascript. Try changing it to:
document.cookie = "lat_lng=" + escape(cookie_val) + "; expires=" + expiration.toGMTString();
PS. However, the expires part is optional and should work without it just fine. Maybe, Safari and FF require it for security reasons? Try googling that.
I'm currently writing a small web page application where users can dynamically drag and drop links to files and pages on a customisable homepage.
It is written in Html5 and Javascript/Jquery mobile. The page will be stored on the local machine and accessed with the 'file:///' protocol, using the Internet Explorer / Microsoft Edge webbrowser.
I'm trying to find a way to store the data that resembles the customized page and links, so that when the user opens the page again the links will still be there and can be edited and customized further.
So far I've been looking into HTML localStorage, but this doesn't work with IE/Edge through the 'file:///' protocol, the page will not be hosted.
I was thinking of just creating a file with all the data in there, but I don't believe that is possible either due to security reasons.
I have not alot of experience with javascript, so any help is appreciated!
If you only want it to work on Internet Explorer/Microsoft Edge, a simple way to persist data would be using cookies. They will work even using the file:// protocol, and the only thing would be setting a far away expiration date (in the example below: 2/2/2222).
Try this sample code (part of it comes from this site) that will count the number of times a page has been loaded. Notice how the counter is kept even after closing the browser and reopening it:
<!doctype html>
<html>
<head>
<title>Persistent Data With Cookies In IE</title>
</head>
<body>
Number of reloads: <span id="num">-</span>
<script>
function setCookie(name, value)
{
var expiry = new Date(2222,2,2);
document.cookie = name + "=" + escape(value) + "; path=/; expires=" + expiry.toGMTString();
}
function getCookie(name)
{
var re = new RegExp(name + "=([^;]+)");
var value = re.exec(document.cookie);
return (value != null) ? unescape(value[1]) : null;
}
var cookieVal = getCookie("num");
var num = cookieVal != null ? cookieVal : 0;
document.getElementById("num").innerHTML = num;
setCookie("num", parseInt(num) + 1)
</script>
</body>
</html>
Pros of this solution:
Simple and easy to implement.
Works with the file:// protocol in IE and Edge (as specified in question) and also in Firefox.
Cons of this solution:
Limited storage space.
Doesn't work with the file:// protocol in Chrome (not required in question).
var locator = new ActiveXObject("WbemScripting.SWbemLocator");
var service = locator.ConnectServer(".");
var properties = service.ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration");
var e = new Enumerator(properties);
var MACaddress = '';
alert("Its Inside");
for (; !e.atEnd(); e.moveNext()) {
var p = e.item();
if (p.MACAddress) {
MACaddress = MACaddress + p.MACAddress + ',';
}
}
MACaddress = MACaddress.substring(0, MACaddress.length - 1);
MACaddress = replaceAll(MACaddress, ':', '-');
location.href = location.href + '?CAT=MAC&MACAddr=' + MACaddress;
This function is working fine in IE but its breaking in mozilla firefox at the first line itself. I changed locator.ConnectServer(".") to locator.ConnectServer("MACHINE") but still its not working in Mozilla Firefox.
Simple answer: you can't.
Modern browsers sandboxes (or try to) everything that goes on in the browser for security reason. Sand-boxing prevents any direct access to a system incl. files system, hardware etc. (it doesn't mean the browser does not communicate with the hardware but as users we have not direct access to it).
IE is the only browser which supports ActiveX (which is Microsoft's own technology) but it shouldn't be relied upon for the same reason, (mainly..) security.
If you want to use the MAC-address for some sort of unique identifier/security you can instead look into the new Web Cryptography API, however, at the time of this writing it is still in draft mode and not widely supported (but will be, or intents to be, cross-browser sometime in the future) so perhaps not so very useful advice at the moment.
You can in any case use server side to generate a unique identifier based on various factors and store it locally in the browser using either cookies or localStorage and so forth.
I would like to use client-side Javascript to perform a DNS lookup (hostname to IP address) as seen from the client's computer. Is that possible?
Edit: This question gave me an itch, so I put up a JSONP webservice on Google App Engine that returns the clients ip address. Usage:
<script type="application/javascript">
function getip(json){
alert(json.ip); // alerts the ip address
}
</script>
<script type="application/javascript" src="http://jsonip.appspot.com/?callback=getip"> </script>
Yay, no server proxies needed.
Pure JS can't. If you have a server script under the same domain that prints it out you could send a XMLHttpRequest to read it.
I know this question was asked a very long time ago, but I figured I'd offer a more recent answer.
DNS over HTTPS (DoH)
You can send DNS queries over HTTPS to DNS resolvers that support it. The standard for DOH is described in RFC 8484.
This is a similar thing to what all the other answers suggest, only that DoH is actually the DNS protocol over HTTPS. It's also a "proposed" Internet standard and it's becoming quite popular. For example, some major browsers either support it or have plans to support it (Chrome, Edge, Firefox), and Microsoft is in the process of building it into their operating system.
One of the purposes of DoH is:
allowing web applications to access DNS information via existing browser APIs in a safe way consistent with Cross Origin Resource Sharing (CORS)
There's an open source tool made especially for doing DNS lookups from web applications called dohjs. It does DNS over HTTPS (DoH) wireformat queries as described in RFC 8484. It supports both GET and POST methods.
Full disclosure: I am a contributor to dohjs.
Another JavaScript library with similar features is found here - https://github.com/sc0Vu/doh-js-client. I haven't used this one personally, but I think it would work client side as well.
DNS over HTTPS JSON APIs
If you don't want to bother with DNS wireformat, both Google and Cloudflare offer JSON APIs for DNS over HTTPS.
Google's JSON API
Doc: https://developers.google.com/speed/public-dns/docs/doh/json
Endpoint: https://dns.google/resolve?
Cloudflare's JSON API
Doc: https://developers.cloudflare.com/1.1.1.1/dns-over-https/json-format/
Endpoint https://cloudflare-dns.com/dns-query?
Example Javascript code to lookup example.com with Google's JSON DOH API:
var response = await fetch('https://dns.google/resolve?name=example.com');
var json = await response.json();
console.log(json);
Examples from the RFC for DOH GET and POST with wireformat
Here are the examples the RFC gives for both GET and POST (see https://www.rfc-editor.org/rfc/rfc8484#section-4.1.1):
GET example:
The first example request uses GET to request "www.example.com".
:method = GET
:scheme = https
:authority = dnsserver.example.net
:path = /dns-query?dns=AAABAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB
accept = application/dns-message
POST example:
The same DNS query for "www.example.com", using the POST method would
be:
:method = POST
:scheme = https
:authority = dnsserver.example.net
:path = /dns-query
accept = application/dns-message
content-type = application/dns-message
content-length = 33
<33 bytes represented by the following hex encoding>
00 00 01 00 00 01 00 00 00 00 00 00 03 77 77 77
07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 01 00
01
Other places to send DOH queries
You can find a list of some public DNS resolvers that support DNS over HTTPS in a couple places:
DNSCrypt has a long list of public DoH and DNSCrypt resolver on their Github, and a nice interactive version of the list at https://dnscrypt.info/public-servers/
Wikipedia - comparison of public recursive nameservers
List on Curl's wiki
(short) list on dnsprivacy.org
Of the above resources, I'd say that the list on Curl's wiki and the DNSCrypt list are are probably the most complete and the most frequently updated. Curl's page also includes a list of open source tools for DoH (servers, proxies, client libs, etc).
There's no notion of hosts or ip-addresses in the javascript standard library. So you'll have to access some external service to look up hostnames for you.
I recommend hosting a cgi-bin which looks up the ip-address of a hostname and access that via javascript.
Very late, but I guess many people will still land here through "Google Airlines". A moderm approach is to use WebRTC that doesn't require server support.
https://hacking.ventures/local-ip-discovery-with-html5-webrtc-security-and-privacy-risk/
Next code is a copy&paste from http://net.ipcalf.com/
// NOTE: window.RTCPeerConnection is "not a constructor" in FF22/23
var RTCPeerConnection = /*window.RTCPeerConnection ||*/ window.webkitRTCPeerConnection || window.mozRTCPeerConnection;
if (RTCPeerConnection) (function () {
var rtc = new RTCPeerConnection({iceServers:[]});
if (window.mozRTCPeerConnection) { // FF needs a channel/stream to proceed
rtc.createDataChannel('', {reliable:false});
};
rtc.onicecandidate = function (evt) {
if (evt.candidate) grepSDP(evt.candidate.candidate);
};
rtc.createOffer(function (offerDesc) {
grepSDP(offerDesc.sdp);
rtc.setLocalDescription(offerDesc);
}, function (e) { console.warn("offer failed", e); });
var addrs = Object.create(null);
addrs["0.0.0.0"] = false;
function updateDisplay(newAddr) {
if (newAddr in addrs) return;
else addrs[newAddr] = true;
var displayAddrs = Object.keys(addrs).filter(function (k) { return addrs[k]; });
document.getElementById('list').textContent = displayAddrs.join(" or perhaps ") || "n/a";
}
function grepSDP(sdp) {
var hosts = [];
sdp.split('\r\n').forEach(function (line) { // c.f. http://tools.ietf.org/html/rfc4566#page-39
if (~line.indexOf("a=candidate")) { // http://tools.ietf.org/html/rfc4566#section-5.13
var parts = line.split(' '), // http://tools.ietf.org/html/rfc5245#section-15.1
addr = parts[4],
type = parts[7];
if (type === 'host') updateDisplay(addr);
} else if (~line.indexOf("c=")) { // http://tools.ietf.org/html/rfc4566#section-5.7
var parts = line.split(' '),
addr = parts[2];
updateDisplay(addr);
}
});
}
})(); else {
document.getElementById('list').innerHTML = "<code>ifconfig | grep inet | grep -v inet6 | cut -d\" \" -f2 | tail -n1</code>";
document.getElementById('list').nextSibling.textContent = "In Chrome and Firefox your IP should display automatically, by the power of WebRTCskull.";
}
The hosted JSONP version works like a charm, but it seems it goes over its resources during night time most days (Eastern Time), so I had to create my own version.
This is how I accomplished it with PHP:
<?php
header('content-type: application/json; charset=utf-8');
$data = json_encode($_SERVER['REMOTE_ADDR']);
echo $_GET['callback'] . '(' . $data . ');';
?>
Then the Javascript is exactly the same as before, just not an array:
<script type="application/javascript">
function getip(ip){
alert('IP Address: ' + ip);
}
</script>
<script type="application/javascript" src="http://www.anotherdomain.com/file.php?callback=getip"> </script>
Simple as that!
Side note: Be sure to clean your $_GET if you're using this in any public-facing environment!
There's a third-party service which provides a CORS-friendly REST API to perform DNS lookups from the browser - https://exana.io/tools/dns/
I am aware this is an old question but my solution may assist others.
I find that the JSON(P) services which make this easy do not last forever but the following JavaScript works well for me at the time of writing.
<script type="text/javascript">function z (x){ document.getElementById('y').innerHTML=x.query }</script>
<script type='text/javascript' src='http://ip-api.com/json/zero.eu.org?callback=z'></script>
The above writes my server's IP on the page it is located but the script can be modified to find any IP by changing 'zero.eu.org' to another domain name.
This can be seen in action on my page at: http://meon.zero.eu.org/
There is a javascript library DNS-JS.com that does just this.
DNS.Query("dns-js.com",
DNS.QueryType.A,
function(data) {
console.log(data);
});
As many people said you need to use an external service and call it. And that will only get you the DNS resolution from the server perspective.
If that's good enough and if you just need DNS resolution you can use the following Docker container:
https://github.com/kuralabs/docker-webaiodns
Endpoints:
[GET] /ipv6/[domain]:
Perform a DNS resolution for given domain and return the associated IPv6
addresses.
{
"addresses": [
"2a01:91ff::f03c:7e01:51bd:fe1f"
]
}
[GET] /ipv4/[domain]:
Perform a DNS resolution for given domain and return the associated IPv4
addresses.
{
"addresses": [
"139.180.232.162"
]
}
My recommendation is that you setup your web server to reverse proxy to the container on a particular endpoint in your server serving your Javascript and call it using your standard Javascript Ajax functions.
Doing this would require to break the browser sandbox. Try to let your server do the lookup and request that from the client side via XmlHttp.
Firefox has a built-in API for this since v60, for WebExtensions:
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/dns/resolve
sure you can do that without using any addition, just pure javascript, by using this method of dns browser.dns.resolve("example.com");
but it is compatible just with FIREFOX 60 you can see more information on MDN https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/dns/resolve
I don't think this is allowed by most browsers for security reasons, in a pure JavaScript context as the question asks.
Maybe I missed the point but in reply to NAVY guy here is how the browser can tell you the 'requestor's' IP address (albeit maybe only their service provider).
Place a script tag in the page to be rendered by the client that calls (has src pointing to) another server that is not loaded balanced (I realize that this means you need access to a 2nd server but hosting is cheap these days and you can set this up easily and cheaply).
This is the kind of code that needs to be added to client page:
On the other server "someServerIown" you need to have the ASP, ASPX or PHP page that;
----- contains server code like this:
"<%
Response.Write("var clientipaddress = '" & Request.ServerVariables("REMOTE_ADDR") & "';")
%>"
(without the outside dbl quotes :-))
---- and writes this code back to script tag:
var clientipaddress = '178.32.21.45';
This effectively creates a Javascript variable that you can access with Javascript on the page no less.
Hopefully, you access this var and write the value to a form control ready for sending back.
When the user posts or gets on the next request your Javascript and/or form sends the value of the variable that the "otherServerIown" has filled in for you, back to the server you would like it on.
This is how I get around the dumb load balancer we have that masks the client IP address and makes it appear as that of the Load balancer .... dumb ... dumb dumb dumb!
I haven't given the exact solution because everyone's situation is a little different. The concept is sound, however. Also, note if you are doing this on an HTTPS page your "otherServerIOwn" must also deliver in that secure form otherwise Client is alerted to mixed content. And if you do have https then make sure ALL your certs are valid otherwise client also gets a warning.
Hope it helps someone! Sorry, it took a year to answer/contribute. :-)
My version is like this:
php on my server:
<?php
header('content-type: application/json; charset=utf-8');
$data = json_encode($_SERVER['REMOTE_ADDR']);
$callback = filter_input(INPUT_GET,
'callback',
FILTER_SANITIZE_STRING,
FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW);
echo $callback . '(' . $data . ');';
?>
jQuery on the page:
var self = this;
$.ajax({
url: this.url + "getip.php",
data: null,
type: 'GET',
crossDomain: true,
dataType: 'jsonp'
}).done( function( json ) {
self.ip = json;
});
It works cross domain.
It could use a status check. Working on that.
If the client has Java installed, you could do something like this:
ipAddress = java.net.InetAddress.getLocalHost().getHostAddress();
Other than that, you will probably have to use a server side script.