Denying access based on HTTP referer

To deny access to a site based on the referer URL, you can use Apache rewrite rules.

In the sample below, any referral that ends with .ru, .ua, or .tv will be rejected and redirected to the forbidden page (a 403).

RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} \.(ru|ua|tv)$ [NC]
RewriteRule ^.*  - [F]

To test the rule, you can use curl, like so:

curl -e ‘http://test.tv’ domain.com

dojo - dijit Form - Create dijits programmatically

This code populates an empty form with a radio button input that has three options. It can be modified to work with check boxes and other dijits.

This is intended to be used with Zend Framework’s Zend_Dojo_Form component, the tags are created using the id naming conventions of Zend, so styling can be applied more easily.

Test data is included, this code can be copied and used as is. It does assume dojo is in the dojo directory. It is coded for dojo 1.6.1 and should work for later versions as well. DOCTYPE is HTML5, although no HTML5 tags are used.

<!DOCTYPE html><head>  
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<META http-equiv="Content-Style-Type" content="text/css">
<title>dojo Test Code</title>
<style type="text/css"> 
<!--
    @import "dojo/dijit/themes/tundra/tundra.css";
-->
dl#dl-web_admin_select
{
width:625px;
}
dl#dl-web_admin_select dt
{
font-weight:bolder;
width:550px;
float:right;
}
dd
{
}
</style>
<script type="text/javascript"> 
//<!--
    var djConfig = {"parseOnLoad":true,"isDebug":true,"locale":"en_US"};
//-->
</script>
<script type="text/javascript" src="dojo/dojo/dojo.js"></script>
<script type="text/javascript" src="dojo/dijit/dijit.js"></script>
<script type="text/javascript" src="dojo/dijit/dijit-all.js"></script>
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dijit.form.RadioButton");

// Data to simulate Zend_Dojo_Data response
var data={"identifier":"id","items":[{"id":"1","url":"one.com","account_name":"AccountOne","name":"AccountOne - one.com"},{"id":"3","url":"three.com","account_name":"AccountOne","name":"AccountOne - three.com"},{"id":"2","url":"two.com","account_name":"AccountTwo","name":"AccountTwo - two.com"}]};

// Used to store the array of created inputs, so they can be destroyed if replaced
var dijit_input = new Array();

dojo.addOnLoad(function(){
		var i=0,input_type;
		// Destroy the HTML
		dojo.destroy('fieldset-web_admin_select');
		// Destroy the dijit widgets
		dijit_input.forEach(function(item){item.destroy()});

		fieldset = dojo.create('fieldset',{'id':'fieldset-web_admin_select'},'frmTest');
		dl = dojo.create('dl',{'id':'dl-web_admin_select'},'fieldset-web_admin_select');
		i=0;
		data.items.forEach(function(item){
			label = dojo.create('dt',{'id':'web_admin_select-label_'+i,'innerHTML':item.name},'dl-web_admin_select');
			input = dojo.create('dd',{'id':'dd_web_admin_select_'+i},'web_admin_select-label_'+i,'after');
			selector = dojo.create('input',{'id':'web_admin_select_'+i,'type':'radio','name':'web_admin_select'},'dd_web_admin_select_'+i);
			dijit_input.push(new dijit.form.RadioButton({
				'value': item.id,
				'id': "rb["+i+"]"},
				'web_admin_select_'+i));
			i++;
		});
});

</script>
</head>
<body class="tundra">
<h1>dojo Test</h1>
<form data-dojo-type="dijit.form.Form" data-dojo-props="'id':'frmTest','name':'frmTest','method':'post'">
</form>
</body>
</html>

Apache Mod_AutoIndex - IIS/ASP Implementation

This is a simple directory listing script for IIS, using ASP.

Features

  • Custom CSS for each folder, if available It reads a css directory and if there is a .css file with the requested directory name, it will include a <style> tag for it. For example, if the requested directory listing is forms, it will create a style tag for css/forms.css.
  • Single instance One copy of this code can reside at the top of a directory tree and allow navigation throughout sub folders.
  • Drag and drop content posting The administrator or person who is posting content can drag and drop the files using Windows Explorer, without modifying the script, or asking for help. New content will be displayed as copied.
  • Hidden aware Hidden directories and files aren’t listed, so content can be placed on the server, but not displayed. This includes files named with a leading underscore which are usually not content.
  • Sample CSS A sample CSS file is included

<!DOCTYPE HTML>
<html>
<head>
<%
Const ReadOnly=1
Const Hidden=2

Dim fs,fo,x
Set fs=Server.CreateObject("Scripting.FileSystemObject")

Dim strPage,strPageHTML,strPageEncode,i
strPage=Request.ServerVariables("QUERY_STRING")
If (strPage = Null) Then strPage = ""
If (InStr(strPage,".")) Then strPage = ""
strPage=Replace(strPage,"+"," ")
strPageHTML=Server.HTMLEncode(strPage)
strPageEscape=Server.URLEncode(strPage)
%>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<META http-equiv="Content-Style-Type" content="text/css">
<title>Page Title</title>
<base href="http://domain.com/top/" />
<link href="css/style.css" rel="stylesheet" type="text/css" />
<%
If (strPage <> "") Then
	Set fo=fs.GetFolder("D:\docs\top\css")
	For Each x In fo.Files
		i=InStr(LCase(x.Name),LCase(strPage))
		If (i <> 0) Then Response.Write("<link href=""css/" & x.Name & """ rel=""stylesheet"" type=""text/css"" />")
	Next
End If
%>
</head>
<body>
<div id="divHeader">
<a href="#" title="Go to Home Page"><h1 id="title">Page Title</h1></a>
<h2><% Response.write(strPageHTML) %></h2>
</div>
<div id="divMain">
<div id="divFolders">
<ul>
<li><a href="http://docs/">Intranet Home</a></li>
<li><a href="http://docs:8088/default.aspx">Search Intranet</a></li>
</ul>
<ul>
<%
Set fo=fs.GetFolder("D:\docs\top\")

For Each x In fo.SubFolders
  'Print the name of all files in the test folder
  If (((x.Attributes And Hidden) = 0) And _
	(Left(x.Name,1) <> "_")) Then
	Response.write("<li><a href='" & Request.ServerVariables("SCRIPT_NAME") & "?" & Server.URLEncode(x.Name) & "'>" & Server.HTMLEncode(x.Name) & "</a></li>")
  End If
Next
%>
</ul>
</div>
<div id="divContent">
<% If (strPage = "") Then %>
<p>Home or top page text.</p>
<% Else %>
<%
Set fo=fs.GetFolder("D:\docs\top\" & strPage)
If (fo.Files.Count > 0) Then
	Response.Write("<ul>")
	For Each x In fo.Files
		If (((x.Attributes And Hidden) = 0) And _
			(Left(x.Name,1) <> "_")) Then
			Response.write("<li><a href='" & strPageEscape & "/" & x.Name & "'>" & Server.HTMLEncode(x.Name) & "</a></li>")
		End If
	Next
	Response.Write("</ul>")
Else
	Response.Write("No files found")
End If
%>
<% End If %>
</div>
</div>
<div id="divFooter">
<span class="float-left bolder">&copy; 2008-<% Response.Write(Year(Now)) %>&nbsp;Company, Inc.</span>
<span class="float-right">This information is for private internal use only.</span>
</div>
</body>
</html>
<%
set fo=nothing
set fs=nothing
%>

Base CSS file

Name this file style.css and place it in the css directory. You may add additional CSS files for each page. The CSS filenames are case-insensitive.

*
{
font-family: "Trebuchet MS","sans-serif";
margin:0;
padding:0;
}
body
{
width:1000px;
}
#divHeader
{
height:105px;
width:950px;
padding:25px 25px 0;
background:#fff url(../images/logo.jpg) no-repeat top right;
}
h1 
{
color:#000;
}
#divMain
{
border-style:solid;
border-width:1px 0;
border-color:#000;
height:450px;
width:1000px;
}
#divFolders
{
width:200px;
float:left;
background-color:yellow;
height:450px;
overflow:auto;
}
ul
{
list-style-type:none;
padding:5px;
margin:10px;
}
#divContent
{
padding:10px;
width:780px;
float:left;
}
#divFooter
{
background-color:#fff;
padding:15px;
}
.break
{
float:none;
clear:both;
}
.float-left
{
float:left;
}
.float-right
{
float:right;
}
.center
{
margin:0 auto;
}
.bolder
{
font-weight:bolder;
}
p
{
padding:5px;
margin:5px;
}
a
{
color:#000;
text-decoration:none;
}
a:hover
{
text-decoration:underline;
}
a:visited
{
color:#000;
}

Browser Cache Management - Ensure Updates

This post describes one way to ensure the javascript and CSS are requested by the browser when a new release is distributed.

The first approach is to prefix the file names with a version-release string, and create symlinks to the files during installation or the first execution. Many systems have a version identification mechanism.

To manage the symlinks, the following could be used:


#!/bin/bash

fclearold()
{
        echo 'fclearold'
        for g in $(find *.$1 -maxdepth 1 -type l);do
                echo $g
                rm -f $g
        done
}

fcreatenew()
{
        echo 'fcreatenew'
        for g in $(ls *.$1); do
                ln -s $g $2.$g
        done

}

version=`cat "$BASE/config/version`;
for f in 'js' 'css'; do
        echo $f
        pushd $f > /dev/null
        fclearold $f
        echo $version;
        fcreatenew $f $version
        popd > /dev/null
done

fclearold removes the old symlinks, fcreatenew makes new ones. It is assumed the javascript is in the js directory and all javascript files have a .js extension, and the CSS is in the css directory and all CSS files have a .css extension.

httpd.conf (or equivalent)

# Cache js and CSS files for 6 months - with a timestamp
<FilesMatch "\.(js|css)$">
  ExpiresActive On
  ExpiresDefault "access plus 6 months"
  Header set Cache-Control "max-age=15552000"
  RewriteEngine On
  RewriteRule (.*)/[0-9]+\.(.*)$ $1/$2
  FileETag MTime
</FilesMatch>

Timestamp Management Code (PHP)


        function sTimestamp()
        {
                $sTimestampFile = 'cache/timestamp';
                if (is_file($sTimestampFile))
                        $sRetVal = file_get_contents($sTimestampFile);
                else
                {
                        $sRetVal = time();
                        file_put_contents($sTimestampFile,$sRetVal);
                }
                return $sRetVal;
        }

Once the timestamp is set, it is cached in the cache/timestamp file. In this system, the cache is cleared when new releases are installed, so the absence of the timestamp file ensures an update and a new set of requested files.

The timestamp can applied to .js and .css file requests like so:

<script type="text/javascript" src="js/<?php echo $timestamp ?>.code.js"></script>

Zend Framework - Oauth - Get LinkedInContacts

Get a request token

            
            /* Set up the Oauth consumer */
            $oauth = new Zend_Oauth_Consumer(array(
                'consumerKey' => $this->configs->connections->consumerKey,
                'consumerSecret' => $this->configs->connections->consumerSecret));
            $oauth->setRequestTokenUrl($this->configs->token_uri);

            /* Get the request token */
            $token = $oauth->getRequestToken();

            /* This is the URI to allow the user to authorize access */
            $auth_uri = $token->xoauth_request_auth_url.'?oauth_token='.urlencode($token->oauth_token);

            /* Save the request token */
            $session=new Zend_Session_Namespace('linkedin_connections');
            $session->token = serialize($token);

Get the OAuth token and token secret for the user

              
                /* Set up the OAuth consumer */
                $oauth = new Zend_Oauth_Consumer(array(
                    'consumerKey' => $this->configs->connections->consumerKey,
                    'consumerSecret' => $this->configs->connections->consumerSecret));
                $oauth->setAccessTokenUrl($this->configs->access_uri);

                /* Get the request token */
                $session=new Zend_Session_Namespace('linkedin_connections');
                $token = unserialize($session->token);

                /* Get the access token and token secret */
                $token = $oauth->getAccessToken(
                    array('oauth_token' => $token->oauth_token,
                        'oauth_token_secret' => $token->oauth_token_secret,
                        'oauth_verifier' => $data['auth_code']),
                    $token,Zend_Oauth_Consumer::POST);

                $response = $token->getResponse();
                $this->linkedinconnections_data->oauth_token = $token->oauth_token;
                $this->linkedinconnections_data->oauth_token_secret = $token->oauth_token_secret;
                $this->linkedinconnections_data->oauth_expires_in = $token->oauth_expires_in;
                $this->linkedinconnections_data->oauth_authorization_expires_in = $token->oauth_authorization_expires_in;

Get the connections

            
            /* Set up the Oauth client */
            $oauth = new Zend_Oauth_Client(array(
                'consumerKey' => $this->configs->connections->consumerKey,
                'consumerSecret' => $this->configs->connections->consumerSecret),$this->configs->connections_uri);

            /* Set up the tokens for the user */
            $token = new Zend_Oauth_Token_Access();
            $token->setToken($this->linkedinconnections_data->oauth_token);
            $token->setTokenSecret($this->linkedinconnections_data->oauth_token_secret);

            /* Set the tokens for the client */
            $oauth->setToken($token);
            $oauth->setMethod(Zend_Oauth_Client::GET);

            /* Make the request */
            $response = $oauth->request();

Zend Framework Version 1.11