Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

proof of concept

  • Loading branch information...
commit 0b04990eea9643ffe554ca9ca3726d9c5576ddfa 1 parent e6e6314
@cubiq authored
View
1  .gitignore
@@ -0,0 +1 @@
+.DS_Store
View
4 README.md
@@ -1,4 +1,4 @@
-underpants-project
+The Underpants Project
==================
-The Underpants Project
+http://lab.cubiq.org/underpants/
View
7 config.php
@@ -0,0 +1,7 @@
+<?php
+
+$config = array(
+ 'db' => 'mysql:host=localhost;dbname=underpants',
+ 'dbUser' => '',
+ 'dbPassword' => ''
+);
View
166 css/style.css
@@ -0,0 +1,166 @@
+* {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+body, p, h1, form, input {
+ margin: 0; padding: 0; border: 0;
+}
+
+body {
+ background: #0c1312 url(../images/bg.png);
+ font:14px menlo, consolas, verdana, monospace;
+ line-height:1;
+}
+
+input {
+ font:inherit;
+}
+
+form {
+ text-align:center;
+}
+
+a {
+ color:#0f343f;
+}
+
+#flwobj {
+ position: absolute;
+ left:-9999px;
+}
+
+#wrapper {
+ margin: 0 auto;
+ padding: 20px;
+ width: 100%;
+ max-width: 620px;
+ line-height:140%;
+}
+
+#fingerprint {
+ font-size:1.2em;
+ font-weight:bold;
+ text-align:center;
+ background-color:#b64826;
+ background:-webkit-linear-gradient(top, #b64826, #81331b);
+ background:-moz-linear-gradient(top, #b64826, #81331b);
+ background:-ms-linear-gradient(top, #b64826, #81331b);
+ background:-o-linear-gradient(top, #b64826, #81331b);
+ background:linear-gradient(top, #b64826, #81331b);
+ white-space:nowrap;
+ overflow: hidden;
+ text-overflow:ellipsis;
+ text-shadow:0 1px 0 rgba(255,255,255,0.24);
+}
+
+#submit {
+ font-size:1.2em;
+ background-color:#b64826;
+ background:-webkit-linear-gradient(top, #b64826, #81331b);
+ background:-moz-linear-gradient(top, #b64826, #81331b);
+ background:-ms-linear-gradient(top, #b64826, #81331b);
+ background:-o-linear-gradient(top, #b64826, #81331b);
+ background:linear-gradient(top, #b64826, #81331b);
+ -webkit-border-radius:3px;
+ -moz-border-radius:3px;
+ -ms-border-radius:3px;
+ -o-border-radius:3px;
+ border-radius:3px;
+ border:1px solid #4b1a10;
+ box-shadow:inset 0 1px 0 rgba(255,255,255,0.3),
+ inset 0 -1px 0 rgba(0,0,0,0.2),
+ 0 1px 5px rgba(0,0,0,0.4);
+ -webkit-background-clip: padding-box;
+ -moz-background-clip: padding-box;
+ -ms-background-clip: padding-box;
+ -o-background-clip: padding-box;
+ background-clip: padding-box;
+ padding:6px 0;
+ text-shadow:0 1px 0 rgba(255,255,255,0.24);
+ white-space:nowrap;
+ width:20%;
+ margin-left:1em;
+}
+
+#word {
+ padding:6px;
+ font-size:1.2em;
+ border:1px solid #748381;
+ -webkit-border-radius:3px;
+ -moz-border-radius:3px;
+ -ms-border-radius:3px;
+ -o-border-radius:3px;
+ border-radius:3px;
+ background:#eee;
+ box-shadow: 0 1px 0 rgba(255,255,255,0.3),
+ inset 0 0 6px #888;
+ -webkit-background-clip: padding-box;
+ -moz-background-clip: padding-box;
+ -ms-background-clip: padding-box;
+ -o-background-clip: padding-box;
+ background-clip: padding-box;
+ width:70%;
+}
+
+p {
+ display: block;
+ -webkit-border-radius:3px;
+ -moz-border-radius:3px;
+ -ms-border-radius:3px;
+ -o-border-radius:3px;
+ border-radius:3px;
+ padding:10px;
+ margin-bottom:0.8em;
+ background-color:#8fa19f;
+ background:-webkit-linear-gradient(top, #8fa19f, #748381);
+ background:-moz-linear-gradient(top, #8fa19f, #748381);
+ background:-ms-linear-gradient(top, #8fa19f, #748381);
+ background:-o-linear-gradient(top, #8fa19f, #748381);
+ background:linear-gradient(top, #8fa19f, #748381);
+ border:1px solid #000;
+ box-shadow:inset 0 1px 0 rgba(255,255,255,0.3),
+ inset 0 -1px 0 rgba(0,0,0,0.2),
+ 0 0 8px #000;
+ text-shadow:0 1px 0 rgba(255,255,255,0.3);
+ clear:both;
+ text-align:left;
+}
+
+h1 {
+ display: block;
+ text-align:center;
+ font-size:1.4em;
+ -webkit-border-radius:3px;
+ -moz-border-radius:3px;
+ -ms-border-radius:3px;
+ -o-border-radius:3px;
+ border-radius:3px;
+ padding:10px;
+ margin-bottom:0.8em;
+ background-color:#626e6d;
+ background:-webkit-linear-gradient(top, #626e6d, #4f5958);
+ background:-moz-linear-gradient(top, #626e6d, #4f5958);
+ background:-ms-linear-gradient(top, #626e6d, #4f5958);
+ background:-o-linear-gradient(top, #626e6d, #4f5958);
+ background:linear-gradient(top, #626e6d, #4f5958);
+ border:1px solid #000;
+ box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),
+ inset 0 -1px 0 rgba(0,0,0,0.2),
+ 0 0 8px #000;
+ text-shadow:0 1px 0 rgba(255,255,255,0.2);
+}
+
+#credits {
+ text-align:center;
+ color:#444;
+ background:transparent;
+ box-shadow:none;
+ border:0;
+ text-shadow:none;
+}
+
+#credits a {
+ color:#143f4f;
+}
View
BIN  images/bg.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
38 index.php
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<title>Underpants</title>
+
+<script type="text/javascript">
+
+var HTTP_ACCEPT = "<?php echo !empty($_SERVER['HTTP_ACCEPT']) ? htmlspecialchars($_SERVER['HTTP_ACCEPT']) : '' ?>",
+ HTTP_ACCEPT_ENCODING = "<?php echo !empty($_SERVER['HTTP_ACCEPT_ENCODING']) ? htmlspecialchars($_SERVER['HTTP_ACCEPT_ENCODING']) : '' ?>",
+ HTTP_ACCEPT_LANGUAGE = "<?php echo !empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? htmlspecialchars($_SERVER['HTTP_ACCEPT_LANGUAGE']) : '' ?>",
+ HTTP_ACCEPT_CHARSET = "<?php echo !empty($_SERVER['HTTP_ACCEPT_CHARSET']) ? htmlspecialchars($_SERVER['HTTP_ACCEPT_CHARSET']) : '' ?>",
+ REMOTE_ADDR = "<?php echo !empty($_SERVER['REMOTE_ADDR']) ? htmlspecialchars($_SERVER['REMOTE_ADDR']) : '' ?>";
+
+</script>
+<script type="text/javascript" src="js/swfobject.js"></script>
+<script type="text/javascript" src="js/sha1.js"></script>
+<script type="text/javascript" src="js/underpants.js"></script>
+
+<link rel="stylesheet" type="text/css" href="css/style.css">
+
+</head>
+<body>
+
+ <div id="wrapper">
+ <h1>Welcome to the Underpants Project</h1>
+ <p>This is a proof of concept aimed to raise concern over privacy (or lack of it) on the internet. The following is your <strong>unique fingerprint</strong> on the web:</p>
+ <p id="fingerprint">loading...</p>
+ <p>This fingerprint can be used to track you across domains with no need of sessions or cookies or -not to mention- your agreement.<br><br>To prove the risk we all are exposed to, enter any word in the field below, hit <strong>track me!</strong> and follow the instructions (no worries, no personal information is stored).</p>
+ <form action="" method="post" onsubmit="underpants.sendWord();return false" id="myForm"><p><input type="text" placeholder="Any word will do" name="word" id="word"><input type="submit" value="Track me!" id="submit"></p></form>
+ <p id="step2" style="display:none"></p>
+ </div>
+ <p id="credits">Brought to you by <a href="https://twitter.com/#!/cubiq">@cubiq</a> and <a href="https://twitter.com/#!/maboa">@maboa</a></p>
+
+ <div id="flwobj"></div>
+
+</body>
+
+</html>
View
12 js/sha1.js
@@ -0,0 +1,12 @@
+/*
+ * Crypto-JS v2.5.3
+ * http://code.google.com/p/crypto-js/
+ * (c) 2009-2012 by Jeff Mott. All rights reserved.
+ * http://code.google.com/p/crypto-js/wiki/License
+ */
+(typeof Crypto=="undefined"||!Crypto.util)&&function(){var d=window.Crypto={},m=d.util={rotl:function(a,c){return a<<c|a>>>32-c},rotr:function(a,c){return a<<32-c|a>>>c},endian:function(a){if(a.constructor==Number)return m.rotl(a,8)&16711935|m.rotl(a,24)&4278255360;for(var c=0;c<a.length;c++)a[c]=m.endian(a[c]);return a},randomBytes:function(a){for(var c=[];a>0;a--)c.push(Math.floor(Math.random()*256));return c},bytesToWords:function(a){for(var c=[],b=0,i=0;b<a.length;b++,i+=8)c[i>>>5]|=(a[b]&255)<<
+24-i%32;return c},wordsToBytes:function(a){for(var c=[],b=0;b<a.length*32;b+=8)c.push(a[b>>>5]>>>24-b%32&255);return c},bytesToHex:function(a){for(var c=[],b=0;b<a.length;b++)c.push((a[b]>>>4).toString(16)),c.push((a[b]&15).toString(16));return c.join("")},hexToBytes:function(a){for(var c=[],b=0;b<a.length;b+=2)c.push(parseInt(a.substr(b,2),16));return c},bytesToBase64:function(a){if(typeof btoa=="function")return btoa(f.bytesToString(a));for(var c=[],b=0;b<a.length;b+=3)for(var i=a[b]<<16|a[b+1]<<
+8|a[b+2],l=0;l<4;l++)b*8+l*6<=a.length*8?c.push("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(i>>>6*(3-l)&63)):c.push("=");return c.join("")},base64ToBytes:function(a){if(typeof atob=="function")return f.stringToBytes(atob(a));for(var a=a.replace(/[^A-Z0-9+\/]/ig,""),c=[],b=0,i=0;b<a.length;i=++b%4)i!=0&&c.push(("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(a.charAt(b-1))&Math.pow(2,-2*i+8)-1)<<i*2|"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(a.charAt(b))>>>
+6-i*2);return c}},d=d.charenc={};d.UTF8={stringToBytes:function(a){return f.stringToBytes(unescape(encodeURIComponent(a)))},bytesToString:function(a){return decodeURIComponent(escape(f.bytesToString(a)))}};var f=d.Binary={stringToBytes:function(a){for(var c=[],b=0;b<a.length;b++)c.push(a.charCodeAt(b)&255);return c},bytesToString:function(a){for(var c=[],b=0;b<a.length;b++)c.push(String.fromCharCode(a[b]));return c.join("")}}}();
+(function(){var d=Crypto,m=d.util,f=d.charenc,a=f.UTF8,c=f.Binary,b=d.SHA1=function(a,l){var g=m.wordsToBytes(b._sha1(a));return l&&l.asBytes?g:l&&l.asString?c.bytesToString(g):m.bytesToHex(g)};b._sha1=function(b){b.constructor==String&&(b=a.stringToBytes(b));var c=m.bytesToWords(b),g=b.length*8,b=[],d=1732584193,h=-271733879,j=-1732584194,k=271733878,f=-1009589776;c[g>>5]|=128<<24-g%32;c[(g+64>>>9<<4)+15]=g;for(g=0;g<c.length;g+=16){for(var o=d,p=h,q=j,r=k,s=f,e=0;e<80;e++){if(e<16)b[e]=c[g+e];else{var n=
+b[e-3]^b[e-8]^b[e-14]^b[e-16];b[e]=n<<1|n>>>31}n=(d<<5|d>>>27)+f+(b[e]>>>0)+(e<20?(h&j|~h&k)+1518500249:e<40?(h^j^k)+1859775393:e<60?(h&j|h&k|j&k)-1894007588:(h^j^k)-899497514);f=k;k=j;j=h<<30|h>>>2;h=d;d=n}d+=o;h+=p;j+=q;k+=r;f+=s}return[d,h,j,k,f]};b._blocksize=16;b._digestsize=20})();
View
4 js/swfobject.js
@@ -0,0 +1,4 @@
+/* SWFObject v2.2 <http://code.google.com/p/swfobject/>
+ is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
+*/
+var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener("load",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener("load",Y,false)}else{if(typeof O.attachEvent!=D){i(O,"onload",Y)}else{if(typeof O.onload=="function"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName("body")[0];var aa=C(r);aa.setAttribute("type",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable("$version");if(ab){ab=ab.split(" ")[1].split(",");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute("name").toLowerCase()!="movie"){ah[X[ad].getAttribute("name")]=X[ad].getAttribute("value")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName=="OBJECT"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F("6.0.65")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName=="OBJECT"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width="310"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height="137"}j.title=j.title.slice(0,47)+" - Flash Player Installation";var ad=M.ie&&M.win?"ActiveX":"PlugIn",ac="MMredirectURL="+O.location.toString().replace(/&/g,"%26")+"&MMplayerType="+ad+"&MMdoctitle="+j.title;if(typeof ab.flashvars!=D){ab.flashvars+="&"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C("div");X+="SWFObjectNew";Y.setAttribute("id",X);ae.parentNode.insertBefore(Y,ae);ae.style.display="none";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C("div");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display="none";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C("div");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName=="PARAM")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah="";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()=="data"){ag.movie=ai[ae]}else{if(ae.toLowerCase()=="styleclass"){ah+=' class="'+ai[ae]+'"'}else{if(ae.toLowerCase()!="classid"){ah+=" "+ae+'="'+ai[ae]+'"'}}}}}var af="";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name="'+ad+'" value="'+ag[ad]+'" />'}}aa.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+ah+">"+af+"</object>";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+="";ag+="";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+="&"+ai+"="+Z[ai]}else{am.flashvars=ai+"="+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\?/.test(Z)){Z=Z.split("?")[1]}if(aa==null){return L(Z)}var Y=Z.split("&");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf("="))==aa){return L(Y[X].substring((Y[X].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display="block"}}if(E){E(B)}}a=false}}}}();
View
179 js/underpants.js
@@ -0,0 +1,179 @@
+var underpants = (function (w) {
+ var nav = w.navigator,
+ scr = w.screen,
+ underpants = {
+ screenSize: scr.width + 'x' + scr.height + 'x' + scr.colorDepth,
+ devicePixelRatio: w.devicePixelRatio || 1,
+ timezone: new Date().getTimezoneOffset(),
+ mimeTypes: [],
+ plugins: [],
+ httpAcceptHeaders: HTTP_ACCEPT + ';' + HTTP_ACCEPT_ENCODING + ';' + HTTP_ACCEPT_LANGUAGE + ';' + HTTP_ACCEPT_CHARSET,
+ fonts: ''
+ },
+ navParms = [
+ 'appCodeName',
+ 'appName',
+ 'appVersion',
+ 'cookieEnabled',
+ 'language',
+ 'platform',
+ 'product',
+ 'productSub',
+ 'userAgent',
+ 'vendor',
+ 'vendorSub'
+ ],
+ fingerprint = '',
+ flashTimeout,
+ flashFailed;
+
+ function init () {
+ var i, l;
+
+ // Get the Navigator params
+ for ( i = 0, l = navParms.length; i < l; i++ ) {
+ underpants[navParms[i]] = navParms[i] in nav ? nav[navParms[i]] : '';
+ }
+
+ // Get the mime types
+ if ( 'mimeTypes' in nav ) {
+ for ( i = 0, l = nav.mimeTypes.length; i < l; i++ ) {
+ underpants.mimeTypes.push( nav.mimeTypes[i].description + ',' + nav.mimeTypes[i].suffixes + ',' + nav.mimeTypes[i].type );
+ }
+
+ underpants.mimeTypes = underpants.mimeTypes.join(',');
+ }
+
+ // Get the plugins
+ if ( 'plugins' in nav ) {
+ for ( i = 0, l = nav.plugins.length; i < l; i++ ) {
+ underpants.plugins.push( nav.plugins[i].description + ',' + nav.plugins[i].filename + ',' + nav.plugins[i].name );
+ }
+ }
+
+ swfobject.embedSWF("swf/FontList.swf", "flwobj", "1", "1", "9.0.0", null, null, null, null, flashCallback);
+ }
+
+ function flashCallback (result) {
+ if ( !result.success ) {
+ flashFailed = true;
+ ready();
+ return;
+ }
+
+ flashTimeout = setTimeout(function () {
+ flashFailed = true;
+ ready();
+ }, 5000);
+ }
+
+ function addFonts (fonts) {
+ clearTimeout(flashTimeout);
+
+ if ( flashFailed ) return;
+
+ underpants.fonts = fonts.join(',');
+ ready();
+ }
+
+ function makeFingerprint () {
+ var i,
+ out = [];
+
+ for ( i in underpants ) {
+ out.push(underpants[i]);
+ }
+
+ return out.join(';');
+ }
+
+ function ready () {
+ fingerprint = Crypto.SHA1(makeFingerprint());
+ document.getElementById('fingerprint').innerHTML = fingerprint;
+ }
+
+ function ajax (url, parms) {
+ var req = new XMLHttpRequest(),
+ post = parms.post || null,
+ callback = parms.callback || null,
+ timeout = parms.timeout || null;
+
+ req.onreadystatechange = function () {
+ if ( req.readyState != 4 ) return;
+
+ // Error
+ if ( req.status != 200 && req.status != 304 ) {
+ if ( callback ) callback(false);
+ return;
+ }
+
+ if ( callback ) callback(req.responseText);
+ };
+
+ if ( post ) {
+ req.open("POST", url, true);
+ req.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
+ req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
+ } else {
+ req.open('GET', url, true);
+ }
+
+ req.send(post);
+
+ if ( timeout ) {
+ setTimeout(function () {
+ req.onreadystatechange = function () {};
+ req.abort();
+ if ( callback ) callback(false);
+ }, timeout);
+ }
+ }
+
+ function sendWord () {
+ var myForm = document.getElementById('myForm'),
+ step2 = document.getElementById('step2'),
+ word = document.getElementById('word').value;
+
+ if ( word.length < 1 ) {
+ alert('Please enter any string');
+ return;
+ }
+
+ myForm.style.display = 'none';
+ step2.style.display = 'block';
+ step2.innerHTML = 'Loading...';
+
+ ajax('store.php', {
+ post: 'fp=' + escape(fingerprint) + '&word=' + escape(word),
+ callback: function (result) {
+ if ( !result ) {
+ alert('Error connecting to server. Check your internet connect and retry.');
+ myForm.style.display = 'block';
+ step2.style.display = 'none';
+ return;
+ }
+
+ result = w.JSON.parse(result);
+ if ( result.status == 'error' ) {
+ myForm.style.display = 'block';
+ step2.style.display = 'none';
+ alert(result.message);
+ return;
+ }
+
+ step2.innerHTML = '<strong>Your word has been saved!</strong> Now point your browser to any of the following addresses (copy-n-paste) and watch the magic.<br><br>http://ghosttouch.com/underpants<br>http://libellu.la/underpants<br><br>Note: I ask you to copy-n-paste the address to prove that no extra data is transmitted.<br><br><a href="#" onclick="document.getElementById(\'myForm\').style.display=\'block\';document.getElementById(\'step2\').style.display=\'none\';return false">Want to change word?</a>';
+ }
+ });
+ }
+
+ init();
+
+ return {
+ addFonts: addFonts,
+ sendWord: sendWord
+ };
+})(this);
+
+function fontList (fonts) {
+ underpants.addFonts(fonts);
+}
View
44 store.php
@@ -0,0 +1,44 @@
+<?php
+include 'config.php';
+
+header('Cache-Control: no-cache, must-revalidate');
+header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
+header('Content-type: application/json');
+
+if ( !isset($_POST['fp']) || empty($_POST['word']) ) {
+ echo json_encode( array(
+ 'status' => 'error',
+ 'message' => '')
+ );
+ exit;
+}
+
+$fingerprint = strip_tags(trim(urldecode($_POST['fp'])));
+$word = substr(strip_tags(trim(urldecode($_POST['word']))), 0, 127);
+
+if ( $word == "" ) {
+ echo json_encode( array(
+ 'status' => 'error',
+ 'message' => 'Word is empty')
+ );
+ exit;
+}
+
+$db = new PDO($config['db'], $config['dbUser'], $config['dbPassword']);
+$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
+
+$stmt = $db->prepare( "SELECT `id` FROM `words` WHERE `fingerprint` = :fingerprint LIMIT 1" );
+$stmt->execute( array(':fingerprint' => $fingerprint) );
+$user = $stmt->fetch();
+
+if ( !$user ) {
+ $stmt = $db->prepare( "INSERT INTO `words` (`fingerprint`, `word`) VALUES (:fingerprint, :word)" );
+} else {
+ $stmt = $db->prepare( "UPDATE `words` SET `word` = :word WHERE `fingerprint` = :fingerprint" );
+}
+$stmt->execute( array(':fingerprint' => $fingerprint, ':word' => $word) );
+
+echo json_encode( array(
+ 'status' => 'success',
+ 'message' => 'word saved')
+);
View
34 swf/FontList.as
@@ -0,0 +1,34 @@
+// FontList.as
+package {
+ import flash.display.Sprite;
+ import flash.text.Font;
+ import flash.text.FontType;
+ import flash.text.FontStyle;
+ import flash.external.ExternalInterface;
+
+ public class FontList extends Sprite
+ {
+ public function FontList()
+ {
+ ExternalInterface.call('fontList', getDeviceFonts());
+ }
+
+ public function getDeviceFonts():Array
+ {
+ var embeddedAndDeviceFonts:Array = Font.enumerateFonts(true);
+
+ var deviceFontNames:Array = [];
+ for each (var font:Font in embeddedAndDeviceFonts)
+ {
+ if (font.fontType == FontType.EMBEDDED
+ || font.fontStyle != FontStyle.REGULAR
+ )
+ continue;
+ deviceFontNames.push(font.fontName);
+ }
+
+ deviceFontNames.sort();
+ return deviceFontNames;
+ }
+ }
+}
View
BIN  swf/FontList.swf
Binary file not shown
Please sign in to comment.
Something went wrong with that request. Please try again.