AndrewPearson.org

Andrew Pearson's Little Corner of the Internet...

Tuesday, January 17, 2012

How To Bypass The Wikipedia SOPA / PIPA Blackout Page

So wikipedia is blacking itself out from midnight tonight until midnight tomorrow. I was interested to see whether wikipedia had actually blocked traffic to its English language website, so I poked around in the HTML for the main English wikipedia page: http://en.wikipedia.org/wiki/Main_Page . It is actually extremely easy to get around the wikipedia blackout page, and I describe how to do so below. If this works for you, or you have any interesting observations, leave a comment for everyone to see.

What I discovered is that wikipedia just has a simple script to pop up a banner over the regular page which is living right below the banner. It is trivial to remove: just disable javascript on wikipedia or run a script-blocking programming when you view wikipedia. NoScript (http://noscript.net/) should work for Firefox, or NotScripts (https://chrome.google.com/webstore/detail/odjhifogjcknibkahlpidmdajjpkkcfn) for Chrome if you choose to go this route. You could also just block the blackout banner script that I describe below.

If you are interested in the mechanics of this "blackout" banner, read on:

Inspecting the scripts running on the page, I see this one:
http://meta.wikimedia.org/w/index.php?title=Special:BannerLoader&banner=blackout&campaign=English+Wikipedia+Blackout&userlang=en&db=enwiki&sitename=Wikipedia&country=US
Inside, we get this:

insertBanner({
"bannerName": "blackout",
"bannerHtml": "<style>\n#mw-sopaOverlay {\n \/* Opera Mini doens't like position absolute *\/\n \/* iOS doesn't like position fixed *\/\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 500;\n color: #dedede;\n background: black url(\/\/upload.wikimedia.org\/wikipedia\/commons\/9\/98\/WP_SOPA_Splash_Full.jpg) no-repeat 0 0;\n overflow: auto;\n font-family:Times New Roman;\n}\n\n\/* Monobook requires position, otherwise background is white+book instead of black *\/\nbody.skin-monobook #mw-sopaOverlay {\n position: absolute;\n}\n\n#mw-sopaColumn {\n position: absolute;\n top: 80px;\n left: 420px;\n width: 400px;\n color: #dedede;\n padding-bottom: 30px;\n}\n#mw-sopaHeadline {\n font-size: 1.7em;\n margin-bottom: 0.5em;\n color: #fff;\n overflow: hidden;\n text-align: justify;\n}\n#mw-sopaText { \n margin-bottom: 1.5em;\n text-align: justify;\n}\n#mw-sopaColumn a {\n color: #eee;\n text-decoration: underline;\n}\n#mw-sopaColumn a:hover {\n color: #fff;\n cursor: pointer;\n text-decoration: underline;\n}\n#mw-sopaColumn a.action {\n margin-top: 2px;\n}\n.mw-sopaActionDiv {\n margin-left: 1em;\n margin-bottom: 1em;\n}\n\n.mw-sopaActionHead {\n font-weight: bold;\n}\n.mw-sopaSocial {\n float: left;\n text-align: center;\n margin-right: 12px;\n margin-bottom: 3px;\n font-size: small;\n}\n.mw-sopaSocial a {\n text-decoration: none;\n}\n<\/style>\n\n\n\n<script type=\"text\/javascript\">\n( function ($) {\n\t\/\/ n.b. community has decided for full blackout including Special pages,\n\t\/\/ but it is hard to do stuff in the meantime without this.\n\tvar namespaceWhitelist = ['Special'];\n\n\t\/\/ see Wikipedia:SOPA_initiative\/Blackout_screen_testing\n\tvar pageWhitelist = [\n'Stop Online Piracy Act',\n'PROTECT IP Act',\n'Online Protection and Enforcement of Digital Trade Act',\n'Censorship',\n'Special:CongressLookup',\n'Special:NoticeTemplate',\n'Special:NoticeTemplate\/view',\n'Wikipedia:Text of Creative Commons Attribution-ShareAlike 3.0 Unported License',\n'Wikipedia:General disclaimer',\n'Wikipedia:Contact us',\n'Wikipedia:About',\n'Wikipedia:Copyright violations',\n'Wikipedia:Copyrights',\n'Wikipedia:Five pillars',\n'Digital Millennium Copyright Act',\n'DNS cache poisoning',\n'Censorship',\n'Wikipedia:SOPA initiative',\n'Wikipedia:SOPA initiative\/Action',\n'Wikipedia:SOPA initiative\/Actions by other communities',\n'Wikipedia:SOPA initiative\/Media',\n'Wikipedia:SOPA initiative\/Learn more',\n'Wikipedia:SOPA initiative\/Legal overview',\n'Wikipedia:SOPA initiative\/Take action',\n'SOPA',\n'PIPA',\n'OPEN',\n'Censorship',\n'Special:CongressLookup'\n\t];\n\tvar geoHasUsRep = [\n\t\t'US', \/\/ USA\n\t\t'PR', \/\/ Puerto Rico\n\t\t'VI', \/\/ Virgin Islands\n\t\t'MP', \/\/ Northern Mariana Islands\n\t\t'AS', \/\/ American Samoa\n\t\t'GU' \/\/ Guam\n\t];\n\tvar preload = [];\n\tvar i;\n\n\t\/\/ Exclude some namespaces\n\tif ( $.inArray( wgCanonicalNamespace, namespaceWhitelist ) !== -1 ) {\n\t\treturn;\n\t}\n\n\t\/\/ Exclude some individual pages\n\tfor ( i = 0; i < pageWhitelist.length; i++ ) {\n\t\tif ( pageWhitelist[i] === wgPageName || pageWhitelist[i] === wgPageName.replace( \/_\/g, ' ' ) ) {\n\t\t\treturn;\n\t\t}\n\t}\n\n var urlParams = {};\n (function () {\n var e,\n a = \/\\+\/g, \n r = \/([^&=]+)=?([^&]*)\/g,\n d = function (s) { return decodeURIComponent(s.replace(a, \" \")); },\n q = window.location.search.substring(1);\n\n while (e = r.exec(q)) {\n urlParams[d(e[1])] = d(e[2]);\n }\n })();\n\n var country = 'ZZ';\n if ( urlParams.country ) {\n country = urlParams.country;\n } else if ( window.Geo && window.Geo.country ) {\n country = window.Geo.country;\n }\n \n\tvar hasUsRep = false;\n for ( i = 0; i < geoHasUsRep.length; i++ ) {\n\t\tif ( geoHasUsRep[i] === country ) {\n\t\t hasUsRep = true;\n\t\t break;\n\t\t}\n\t}\n\n\tvar overlay = $('<div id=\"mw-sopaOverlay\"><\/div>');\n\tvar column = $('<div id=\"mw-sopaColumn\"><\/div>');\n\tvar headline = $('<div id=\"mw-sopaHeadline\">Imagine a World<br \/>Without Free Knowledge<\/div>');\n\tvar intro = $('<div id=\"mw-sopaText\"><p>For over a decade, we have spent millions of hours building the largest encyclopedia in human history. Right now, the U.S. Congress is considering legislation that could fatally damage the free and open internet. For 24 hours, to raise awareness, we are blacking out Wikipedia. <a href=\"http:\/\/en.wikipedia.org\/wiki\/Wikipedia:SOPA_initiative\/Learn_more\" target=\"_blank\">Learn more.<\/a><\/p><\/div>');\n\tvar validateZip = function(zip) {\n\t\treturn \/^\\s*[0-9]{5}([- ]?[0-9]{4})?\\s*$\/.test(zip);\n\t};\n\n\tvar action = $('<div id=\"mw-sopaAction\"><\/div>');\n\tif ( hasUsRep ) {\n\t\taction.append( $('<p class=\"mw-sopaActionHead\">Contact your representatives.<\/p><div class=\"mw-sopaActionDiv\"><form action=\"\/wiki\/Special:CongressLookup\" action=\"GET\"><label for=\"zip\">Your zip code:<\/label> <input name=\"zip\" type=\"text\" size=\"5\"> <input id=\"sopa-zipform-submit\" type=\"submit\" value=\"Look up\"><\/form><\/div>' ) );\n\n\t\t\/*\n\t\taction.find('#sopa-zipform-submit').click(\n\t\t\tfunction(e) {\n\t\t\t\tvar enteredZip = action.find('input[name=\"zip\"]').val();\n\t\t\t\tif ( ! validateZip( enteredZip ) ) {\n\t\t\t\t\talert( 'You've entered an invalid zip code.');\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\taction.find('input[name=\"zip\"]').focus();\n\t\t\t\t}\n\t\t\t} );\n\t\t*\/\n\n\t} else {\n var $socialDiv = $('<div>');\n \n \n var socialSites = [\n {\n url: 'https:\/\/www.facebook.com\/sharer.php?u=' + encodeURIComponent( 'http:\/\/tinyurl.com\/7vq4o8g' ),\n title: 'Facebook',\n hi: '\/\/upload.wikimedia.org\/wikipedia\/commons\/b\/b9\/WP_SOPA_sm_icon_facebook_ffffff.png',\n icon: '\/\/upload.wikimedia.org\/wikipedia\/commons\/2\/2a\/WP_SOPA_sm_icon_facebook_dedede.png',\n 'popup': false\n },\n {\n url: 'https:\/\/m.google.com\/app\/plus\/x\/?v=compose&content=' + encodeURIComponent( 'I support the January 18th Wikipedia blackout to protest SOPA and PIPA. Show your support here http:\/\/tinyurl.com\/7vq4o8g' ),\n title: 'Google+',\n hi: '\/\/upload.wikimedia.org\/wikipedia\/commons\/a\/a1\/WP_SOPA_sm_icon_gplus_ffffff.png',\n icon: '\/\/upload.wikimedia.org\/wikipedia\/commons\/0\/08\/WP_SOPA_sm_icon_gplus_dedede.png',\n 'popup': true\n },\n {\n url: 'https:\/\/twitter.com\/intent\/tweet?original_referer=' + encodeURIComponent( window.location ) + '&text=' + encodeURIComponent( 'I support #wikipediablackout! Show your support here http:\/\/tinyurl.com\/7vq4o8g' ),\n title: 'Twitter',\n hi: '\/\/upload.wikimedia.org\/wikipedia\/commons\/8\/8a\/WP_SOPA_sm_icon_twitter_ffffff.png',\n icon: '\/\/upload.wikimedia.org\/wikipedia\/commons\/4\/45\/WP_SOPA_sm_icon_twitter_dedede.png',\n 'popup': false\n }\n ];\n\n for ( i = 0; i < socialSites.length; i++ ) {\n ( function ( site ) {\n function linkify( $item ) {\n var $link = $( '<a><\/a>' )\n .css( 'text-decoration', 'none' )\n .attr( 'href', site.url )\n .append( $item );\n var target = 'wpblackout_' + site.title + '_share';\n if ( site.popup ) {\n $link.click( function() {\n window.open(\n site.url,\n target,\n 'resizable=yes,width=500,height=300,left=' + (screen.availWidth\/2-250) + ',top=' + (screen.availHeight\/2-150)\n );\n return false;\n } );\n } else {\n $link.attr( 'target', target );\n }\n return $link;\n }\n var $icon = $( '<img><\/img>' ).attr( { 'width': 33, 'height': 33, 'src': site.icon } );\n var $iconLink = linkify( $icon );\n preload.push( site.hi );\n var $wordLink = linkify( site.title );\n var $div = $( '<div class=\"mw-sopaSocial\"><\/div>' );\n $div.hover(\n function() {\n $icon.attr( 'src', site.hi );\n $wordLink.css( 'color', '#fff' );\n },\n function() {\n $icon.attr( 'src', site.icon );\n $wordLink.css( 'color', '#dedede' );\n });\n $div.append( $iconLink, $('<br>'), $wordLink );\n $socialDiv.append($div);\n } )( socialSites[i] );\n }\n action.append(\n $( '<p class=\"mw-sopaActionHead\">Make your voice heard<\/p>' ),\n $( '<div class=\"mw-sopaActionDiv\"><\/div>' ).append(\n $socialDiv,\n $( '<div style=\"clear: both;\"><\/div>' )\n )\n );\n\n\t}\n\n\tcolumn.append( headline, intro, action );\n\toverlay.append( column );\n\n\t$('body').children().hide();\n\t$('body').append(overlay);\n\t$('<style id=\"mw-sopa-blackout\">#mw-page-base, #mw-head-base, #content, #mw-head, #mw-panel, #footer { display: none; }<\/style>').appendTo('head');\n\n\tvar preloaded = [];\n\tfor ( i = 0; i < preload.length; i++ ) {\n\t\tpreloaded[i] = new Image();\n\t\tpreloaded[i].src = preload[i];\n\t}\n\n} )(jQuery);\n<\/script>",
"campaign": "English Wikipedia Blackout",
"fundraising": "0",
"autolink": "0",
"landingPages": ""
});


Notice that the third line contains the HTML for the entire blackout banner. The above code is calling a function called insertBanner which is defined here:
http://en.wikipedia.org/w/index.php?title=Special:BannerController&cache=/cn.js&303-4

It contains the following:
function insertBanner( bannerJson ) {
jQuery( 'div#centralNotice' ).prepend( bannerJson.bannerHtml );
if ( bannerJson.autolink ) {
var url = 'https://wikimediafoundation.org/wiki/Special:LandingCheck';
if ( ( bannerJson.landingPages !== null ) && bannerJson.landingPages.length ) {
targets = String( bannerJson.landingPages ).split(',');
url += "?" + jQuery.param( {
'landing_page': targets[Math.floor( Math.random() * targets.length )].replace( /^\s+|\s+$/, '' )
} );
url += "&" + jQuery.param( {
'utm_medium': 'sitenotice', 'utm_campaign': bannerJson.campaign,
'utm_source': bannerJson.bannerName, 'language': wgUserLanguage,
'country': Geo.country
} );
jQuery( '#cn-landingpage-link' ).attr( 'href', url );
}
}
}
function hideBanner() {
jQuery( '#centralNotice' ).hide(); // Hide current banner
var bannerType = $.centralNotice.data.bannerType;
if ( bannerType === undefined ) bannerType = 'default';
setBannerHidingCookie( bannerType ); // Hide future banners of the same type
}
function setBannerHidingCookie( bannerType ) {
var e = new Date();
e.setTime( e.getTime() + (14*24*60*60*1000) ); // two weeks
var work='centralnotice_'+bannerType+'=hide; expires=' + e.toGMTString() + '; path=/';
document.cookie = work;
}
// This function is deprecated
function toggleNotice() {
hideBanner();
}
var wgNoticeToggleState = (document.cookie.indexOf('hidesnmessage=1')==-1);

( function( $ ) {
$.ajaxSetup({ cache: true });
$.centralNotice = {
'data': {
'getVars': {},
'bannerType': 'default'
},
'fn': {
'loadBanner': function( bannerName, campaign, bannerType ) {
// Store the bannerType in case we need to set a banner hiding cookie later
$.centralNotice.data.bannerType = bannerType;
// Get the requested banner
var bannerPageQuery = $.param( {
'banner': bannerName, 'campaign': campaign, 'userlang': wgUserLanguage,
'db': wgDBname, 'sitename': wgSiteName, 'country': Geo.country
} );
var bannerPage = '?title=Special:BannerLoader&' + bannerPageQuery;
var bannerScript = '<script type="text/javascript" src="//meta.wikimedia.org/w/index.php' + bannerPage + '"&rt;</script&rt;';
if ( document.cookie.indexOf( 'centralnotice_'+bannerType+'=hide' ) == -1 ) {
jQuery( '#siteNotice' ).prepend( '<div id="centralNotice" class="' +
( wgNoticeToggleState ? 'expanded' : 'collapsed' ) +
' cn-' + bannerType + '"&rt;'+bannerScript+'</div&rt;' );
}
},
'loadBannerList': function( geoOverride ) {
if ( geoOverride ) {
var geoLocation = geoOverride; // override the geo info
} else {
var geoLocation = Geo.country; // pull the geo info
}
var bannerListQuery = $.param( { 'language': wgContentLanguage, 'project': wgNoticeProject, 'country': geoLocation } );
var bannerListURL = wgScript + '?title=' + encodeURIComponent('Special:BannerListLoader') + '&cache=/cn.js&' + bannerListQuery;
var request = $.ajax( {
url: bannerListURL,
dataType: 'json',
success: $.centralNotice.fn.chooseBanner
} );
},
'chooseBanner': function( bannerList ) {
// Convert the json object to a true array
bannerList = Array.prototype.slice.call( bannerList );

// Make sure there are some banners to choose from
if ( bannerList.length == 0 ) return false;

var groomedBannerList = [];

for( var i = 0; i < bannerList.length; i++ ) {
// Only include this banner if it's intended for the current user
if( ( wgUserName && bannerList[i].display_account ) ||
( !wgUserName && bannerList[i].display_anon == 1 ) )
{
// add the banner to our list once per weight
for( var j=0; j < bannerList[i].weight; j++ ) {
groomedBannerList.push( bannerList[i] );
}
}
}

// Return if there's nothing left after the grooming
if( groomedBannerList.length == 0 ) return false;

// Choose a random key
var pointer = Math.floor( Math.random() * groomedBannerList.length );

// Load a random banner from our groomed list
$.centralNotice.fn.loadBanner(
groomedBannerList[pointer].name,
groomedBannerList[pointer].campaign,
( groomedBannerList[pointer].fundraising ? 'fundraising' : 'default' )
);
},
'getQueryStringVariables': function() {
document.location.search.replace( /\??(?:([^=]+)=([^&]*)&?)/g, function () {
function decode( s ) {
return decodeURIComponent( s.split( "+" ).join( " " ) );
}
$.centralNotice.data.getVars[decode( arguments[1] )] = decode( arguments[2] );
} );
}
}
}
jQuery( document ).ready( function ( $ ) {
// Initialize the query string vars
$.centralNotice.fn.getQueryStringVariables();
if( $.centralNotice.data.getVars['banner'] ) {
// if we're forcing one banner
$.centralNotice.fn.loadBanner( $.centralNotice.data.getVars['banner'] );
} else {
// Look for banners ready to go NOW
$.centralNotice.fn.loadBannerList( $.centralNotice.data.getVars['country'] );
}
} ); //document ready
} )( jQuery );


Basically, all Wikipedia is doing is having the first script call the second script's banner insertion function, passing the special blackout banner as a parameter. I assume that Wikipedia wants this to be relatively easy to get around considering that if your browser allows you to type javascript into the address bar, you can type in a few lines of javascript to get around the effects of this blackout banner.

UPDATE: As I had anticipated, there is a ton of javascript floating around that you can type into your address bar to remove the blackout banner. Here is one example that I found:
javascript:jQuery("#mw-sopaOverlay").css("display", "none !important");jQuery("#content, #mw-page-base, #mw-head-base, #mw-head, #mw-panel, #footer").css("display", "block !important");
All that it does is tell the Wikipedia page to hide the blackout banner section of the HTML and to show the rest of the HTML (which is usually displayed).

Tuesday, January 10, 2012

Fedora Annoyance: Needs XX MB on the /boot filesystem

This post is quite a bit different from my other posts thus far on this blog (which have been about Android programming), but I decided to include it because I find this problem pretty irritating, and I think that yum should have some sort of option to deal with it automatically.

Fedora is known for keeping its packages very up to date. Though this is great for security and functionality, constant kernel updates can become irritating when one's /boot partition fills up. Sometimes, you might see yum spit out the following error during an update:

Transaction Check Error:
installing package kernel-3.1.0-7.fc16.x86_64 needs 9MB on the /boot filesystem

Error Summary
-------------
Disk Requirements:
At least 9MB more space needed on the /boot filesystem.


This means that your update has failed because you have run out of space to install the new kernel. (It is important to note that Fedora doesn't just replace old kernels, it keeps them so that you can boot into them should the new kernel give you any trouble. This is why GRUB (or whatever bootloader you use) will show a few kernels after you've updated a few times.)

Though / or /home might have a tremendous amount of free space, kernels are installed to the /boot filesystem. Since /boot is (almost) always on its own partition, the amount of space on / or /home is irrelevant: when /boot is full, you won't be able to update to a new kernel and your yum update will error out. The solution to this problem is simple: remove old, unused kernels from /boot to make room for new kernels.

First, check which version kernel you are currently running. At the command prompt, type:
uname -r

You should see something like this:
3.1.7-1.fc16.x86_64

The output from uname (uname is a utility to print system information; the -r flag tells uname to print the kernel release that you are running) says that I have the Fedora 16 package of the 3.1.7-1 version of the Linux kernel, compiled for x86_64 processors, installed.

Next, check which kernel versions you currently have installed. At the command prompt, type:
rpm -q kernel

You should see something like this:
kernel-3.1.4-1.fc16.x86_64
kernel-3.1.6-1.fc16.x86_64
kernel-3.1.7-1.fc16.x86_64


The output from rpm (RPM is a package manager; the -q flag queries the package manager for whatever term immediately follows the -q flag) says that three "kernel" packages are installed: 3.1.4, 3.1.6, and 3.1.7. The only thing left to do is to remove one of the kernels to make room for the new one.

It is very important to note that the previous command listed the kernel which uname told us was currently running. We do not want to remove that kernel. Generally, I would recommend removing the oldest kernel version that you have. To do so, simply type the following at the command prompt:

yum remove kernel-version.that.you.found.above
(kernel-version.that.you.found.above, of course, will be something like kernel-3.1.4-1.fc16.x86_64)

You can check to see that you removed the kernel version by querying rpm for "kernel" again.

Now, simply update (ie type in "yum update" at the command prompt) and your new kernel version will install because you have freed up space for it on /boot.

I have personally used this solution on both Fedora 15 and Fedora 16, and I cannot think of a reason why it would not work on other versions of Fedora.