

// if a string is valid urlsafe base64 ( and of a certain size, if specified )
function is_valid_base64 ( p_str, p_length ) {

	 // if we weren't passed a length parameter
    if ( arguments.length != 2 )
		  p_length = -1 ;

	 // all valid urlsafe base64 characters
	 var urlsafe_base64_str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_" ;

	 // if a length argument was passed in and the lengths don't match
	 if ( p_length != -1 && p_str.length != p_length )
		  return false ;

	 // if the string is base64 encoded
	 for ( var i = 0; i < p_str.length; i++ )
		  if ( urlsafe_base64_str.indexOf( p_str.charAt( i ) ) == -1 )
				return false ;

	 // default return of true
	 return true ;

}


// returns an object container all of the url parameters as key/value pairs
function get_urlparamobj ( p_url ) {

	 // url parameter object to return
	 var urlparams = new Object ;

	 // remove any site anchor
	 var urlhalfs = p_url.split( '#' ) ;
	 if ( urlhalfs.length >= 2 )
		  p_url = urlhalfs[ 0 ] ;
	 
	 // split the string by '?'
	 urlhalfs = p_url.split( '?' ) ;
	 if ( urlhalfs.length < 2 )
		  return new Object ;

	 // get each url argument
	 var urlargs = urlhalfs[ 1 ].split( '&' )
	 for ( var i = 0; i < urlargs.length; i++ ) {

		  // split this argument
		  var urlarg_pair = urlargs[ i ].split( '=' ) ;
		  if ( urlarg_pair.length != 2 )
				continue ;

		  // add this url parameter key/value pair
		  urlparams[ urlarg_pair[ 0 ] ] = urlarg_pair[ 1 ] ;

	 }

	 // return the url parameters object
	 return urlparams ;

}


// construct a url parameter string from an object of parameter names and values
//   if the values in this object are not url encoded, then the string might be mal-formatted
//   it is the user of this function's responsibility to make sure all names and values are properly url encoded
function url_construct_paramstr ( paramobj ) {
	 var paramstr = '' ; // the parameter string, like '?foo=a&blah=b'

	 // construct this parameter string
	 for ( var key in paramobj )
		  paramstr += '&' + key + '=' + paramobj[ key ] ;
	 
	 // replace the first '&' with ? and return the parameter string
	 if ( paramstr.length > 0 )
		  paramstr = '?' + paramstr.substring( 1 ) ; // replace the first '&' with '?'

	 return paramstr ;
}


// returns a url parameter parameter's value when passed its name
// if the url parameter doesnt exist, returns ''
//   ex: get_url_param( 'foo' ) returns 'asdf' when the window.location.href is 'www.blah.com?foo=asdf'
//   this function taken and modified from: http://www.netlobo.com/url_query_string_javascript.html
function get_url_param ( p_name ) {
	 p_name = p_name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
	 var regexS = "[\\?&]"+p_name+"=([^&#]*)";
	 var regex = new RegExp( regexS );
	 var results = regex.exec( window.location.href );
	 if( results == null )
		  return "";
	 else
		  return results[1];
}


// returns an array list of all of the url parameters
function get_url_params () {
	 var params = new Array( );
	 var regex = /[\?&]([^=]+)=/g;
	 while( ( results = regex.exec( window.location.href ) ) != null )
		 params.push( results[1] );
	 return params;
}


// sets ( changes or adds ) a url parameter of a url string
//   if the url doesnt have that url parameter originally, it is added
function url_setparam ( url, name, val ) {
	 var mainurl = '' ; // the base url, like 'http://dirpy.com/studio/'. no url parameters, no site anchor
	 var siteanchor = '' ; // the site anchor, like '#anchorme'

	 // get any url anchor
	 var urlhalfs = url.split( "#" ) ;
	 if ( urlhalfs.length >= 2 ) {
		  url = urlhalfs[ 0 ] ; // only care about everything before the site anchor now
		  for ( var i = 1; i < urlhalfs.length; i++ ) // assemble the site anchor string
				siteanchor += urlhalfs[ i ] ;
	 }

	 // get everything before the parameters ( split by '?' )
	 urlhalfs = url.split( '?' ) ;
	 if ( urlhalfs.length > 0 )
		  mainurl = urlhalfs[ 0 ] ;

	 // get the parameters for this url
	 params = get_urlparamobj( url ) ;

	 // set this parameters value
	 params[ name ] = val ;

	 // construct the url parameter string
	 paramstr = url_construct_paramstr( params ) ;

	 // return the fully reconstructed url ( main url + params + site anchor )
	 return mainurl + paramstr + siteanchor ;

}




// the index of the last character in the whole protocol string protocol + ":// "
// e.g. returns 6 when passed "http:// foo"
function protocol_end_pos ( p_str ) {
	 // find the protocol string in the beginning and temporarily remove it until later
	 // find the last '/' in the string
	 var protocol_loc ;
  
	 protocol_loc = p_str.indexOf ( ":// " ) ;

	 // if it wasn't found, return the beginning of the string (or index = 0)
	 if ( protocol_loc == -1 ) {
		  return 0 ;
	 }  
	 // otherwise, return the END of the protocol string, e.g. 6 in "http:// foo"
	 else {
		  return protocol_loc + 2 ;
	 }
}



// returns the highest order directory in a url
// e.g. when passed "http:// www.foo.com/dir/boo/blah.html" returns "http:// www.foo.com/dir/boo/" 
function highest_order_url_dir ( p_str ) {
	 // find the last '/' in the string
	 var loc ;
  
	 loc = p_str.lastIndexOf ( "/" ) ;

	 // if it wasn't found, return the original string
	 // or the first / of the protocol string was found
	 if ( loc == -1 ||
			loc == protocol_end_pos ( p_str ) ) {
		  return p_str ;
	 }

	 // if it exists, return that highest order dir url
	 return p_str.substring( 0, loc + 1 ) ;
}



// returns whether or not a string is a valid open directory title
// e.g. "Index of /foo" is a valid html directory title and "This my homepage" is not
// worthy links have their anchor content text begin with:
//    "Index of /" 
//    or "Index of ./" 
//    or "Index of ../" 
//    BUT NOT "Index of /resources", "Index of ./resources", or "Index of ../resources"
function is_valid_html_dir_title ( p_str ) {
    // test this anchor's content text
    if (
        // shorter than 10 characters ( smaller than "Index of /", the shortest valid title )
        ( p_str.length < 10 ) ||
				
		  (   // doesn't start with "Index of /"
				p_str.substring( 0, 10 ) != "Index of /" &&

				// doesnt start with "Index of ./"
				p_str.substring( 0, 11 ) != "Index of ./" &&

				// doesnt start with "Index of ../"
				p_str.substring( 0, 12 ) != "Index of ../" ) ||

        // starts with "Index of /resources"
        ( p_str.length >= 19 &&
          p_str.substring( 0, 19 ) == "Index of /resources" ) ||

        // starts with "Index of ./resources"
        ( p_str.length >= 20 &&
          p_str.substring( 0, 20 ) == "Index of ./resources" ) ||

        // starts with "Index of /resources"
        ( p_str.length >= 21 &&
          p_str.substring( 0, 21 ) == "Index of ../resources" ) ) {
  
        // invalid url directory title
        return false ;
    }

    // valid url directory title
    return true ;
}


//  url encodes a string
//     e.g. "+bat" becomes "%2Bbat"
function url_encode ( p_str ) {
	 //  valid characters that don't need to be encoded
	 var VALIDCHARS = "0123456789" +
		  "abcdefghijklmnopqrstuvwxyz" +
		  "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
		  //  url characters
		  ":/&?=" +

		  //  RFC2396
		  "-_.!~*'()" ;

	 //  hexadecimal string for output formatting
	 var HEXADECIMAL = "0123456789ABCDEF" ;
	 
	 //  the encoded string to be returned
	 var retstr = "" ;

	 //  loop over the string and convert each character
	 for ( var i = 0; i < p_str.length; i++ ) {
		  //  get the character
		  var thechar = p_str.charAt(i);
		  
		  //  space
	     if (thechar == " ") {
				retstr += "%20" ;
		  } 
		  //  valid character we don't need to change at all
		  else if ( VALIDCHARS.indexOf( thechar ) != -1 ) {
				retstr += thechar ;
		  }
		  //  unknown character that probably needs to be url encoded
		  else {
				//  character code ( 0 - 255 )
				var code = thechar.charCodeAt( 0 ) ;

				//  valid ascii encoded character
				if ( code < 255 ) {
					 //  add the encoded character for this string
					 retstr += "%" +
						  HEXADECIMAL.charAt( ( code >> 4 ) & 0xF ) +
						  HEXADECIMAL.charAt( code & 0xF ) ;
				}
				//  otherwise we have an unkown character ( maybe unicode? ) and we'll just add a space to replace it
				else {
					 retstr += " " ;
				}
		  }
	 }

	 //  return the 
	 return retstr ;
}
