Never been to TextSnippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world (or not, you can keep them private!)

« Newer Snippets
Older Snippets »
8 total  XML / RSS feed 

Get remote file size, following redirects (PHP)

function get_remote_file_size($url, $readable = true){
   $parsed = parse_url($url);
   $host = $parsed["host"];
   $fp = @fsockopen($host, 80, $errno, $errstr, 20);
   if(!$fp) return false;
   else {
       @fputs($fp, "HEAD $url HTTP/1.1\r\n");
       @fputs($fp, "HOST: $host\r\n");
       @fputs($fp, "Connection: close\r\n\r\n");
       $headers = "";
       while(!@feof($fp))$headers .= @fgets ($fp, 128);
   }
   @fclose ($fp);
   $return = false;
   $arr_headers = explode("\n", $headers);
   foreach($arr_headers as $header) {
                        // follow redirect
                        $s = 'Location: ';
                        if(substr(strtolower ($header), 0, strlen($s)) == strtolower($s)) {
                                $url = trim(substr($header, strlen($s)));
                                return get_remote_file_size($url, $readable);
                        }
                        
                        // parse for content length
       $s = "Content-Length: ";
       if(substr(strtolower ($header), 0, strlen($s)) == strtolower($s)) {
           $return = trim(substr($header, strlen($s)));
           break;
       }
   }
   if($return && $readable) {
                        $size = round($return / 1024, 2);
                        $sz = "KB"; // Size In KB
                        if ($size > 1024) {
                                $size = round($size / 1024, 2);
                                $sz = "MB"; // Size in MB
                        }
                        $return = "$size $sz";
   }
   return $return;
}

Authenticated Digest for Net:HTTPHeader

Allows authenticated requests to be made.

Based off of http://theexciter.com/articles/bingo and updated for Ruby 1.8.6

Use by calling

    req.digest_auth(username, password, res)


on an HTTP request object before asking for a response.

# net_digest_auth.rb
require 'digest/md5'
require 'net/http'

module Net
  module HTTPHeader
    @@nonce_count = -1
    CNONCE = Digest::MD5.new.update("%x" % (Time.now.to_i + rand(65535))).hexdigest
    def digest_auth(user, password, response)
      # based on http://segment7.net/projects/ruby/snippets/digest_auth.rb
      @@nonce_count += 1

      response['www-authenticate'] =~ /^(\w+) (.*)/

      params = {}
      $2.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 }

      a_1 = "#{user}:#{params['realm']}:#{password}"
      a_2 = "#{@method}:#{@path}"
      request_digest = ''
      request_digest << Digest::MD5.new.update(a_1).hexdigest
      request_digest << ':' << params['nonce']
      request_digest << ':' << ('%08x' % @@nonce_count)
      request_digest << ':' << CNONCE
      request_digest << ':' << params['qop']
      request_digest << ':' << Digest::MD5.new.update(a_2).hexdigest

      header = []
      header << "Digest username=\"#{user}\""
      header << "realm=\"#{params['realm']}\""
      
      header << "qop=#{params['qop']}"

      header << "algorithm=MD5"
      header << "uri=\"#{@path}\""
      header << "nonce=\"#{params['nonce']}\""
      header << "nc=#{'%08x' % @@nonce_count}"
      header << "cnonce=\"#{CNONCE}\""
      header << "response=\"#{Digest::MD5.new.update(request_digest).hexdigest}\""

      @header['Authorization'] = header
    end
  end
end

httpd.rb

// Simple ruby webrick server

require 'webrick'

# The :AccessLog configuration takes an array.
# Each element of the array should be
# a two-element array where the first element
# is the stream (or anything responding to <<)  and
# the second element is the access log format.
# Please see webrick/accesslog.rb for available formats.

access_log_stream = File.open('C:\\Documents and Settings\\madann\\My Documents\\access.log', 'w')
access_log = [ [ access_log_stream, WEBrick::AccessLog::COMBINED_LOG_FORMAT ] ]

DocumentRoot = 'C:\\Documents and Settings\\madann\\My Documents\\Public_html\\';
HTTPPort = 8008

begin
   d = Dir.open(DocumentRoot)
rescue
   puts "Creating Documentroot"
   mkdir DocumentRoot
end

class DownloadHandler < WEBrick::HTTPServlet::AbstractServlet
    def do_get(req,resp)
        p "req : ",req
        p "resp : ",resp
    end

    def go_post(req,resp)
        resp
    end
end


s = WEBrick::HTTPServer.new(
  :Port             => HTTPPort,
  :DocumentRoot     => DocumentRoot,
  :FancyIndexing    => true
  #:Logger          => WEBrick::Log.new('download.log'),
  #:AccessLog       => access_log
)

s.mount("/cgi-bin",
        WEBrick::HTTPServlet::FileHandler,
        "C:\\Documents and Settings\\madann\\My Documents\\Public_html\\cgi-bin\\",
        {:FancyIndexing=>true})

trap("INT"){ s.shutdown }
s.start

rsrcmeter v2

TextDrive: Simple disk usage and HTTP bandwidth counts
Updated version from http://textsnippets.com/posts/show/632
This script will allow a TextDrive account holder to easily see their disk usage and monthly HTTP bandwidth consumption, until TextPanel provides the information.
The first time you use rsrcmeter, it may take additional time, as it will be scanning every Apache/HTTP log file for usage information and caching it by month.

--> Get Easy Install Instructions, Etc. at http://rsrcmeter.textjoy.com/.

Sample output:
Disk usage: 23.7227 MiB (Quota: 10.0000 GiB | 0.2% used)
Bandwidth:
Nov 2006: 0.5494 MiB (Month to Date)
Oct 2006: 0.5087 MiB
Sep 2006: 0.5523 MiB
Aug 2006: 1.1567 MiB


#!/usr/local/bin/ruby
# Unofficial TxD Disk & HTTP Bandwidth Usage Meter (rsrcmeter)
# Version 2.0.2
# Written by AJ Zmudosky
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND WITHOUT WARRANTY OF
# ANY KIND. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
# DAMAGES HOWEVER CAUSED, AND ON ANY THEORY OF LIABILITY, ARISING IN ANY
# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
# OF SUCH DAMAGE.

require 'date'
require 'optparse'

# E-mail regexp
module RFC2822
  EmailAddress = begin
    alpha = "a-zA-Z"
    digit = "0-9"
    atext = "[#{alpha}#{digit}\!\#\$\%\&\'\*+\/\=\?\^\_\`\{\|\}\~\-]"
    dot_atom_text = "#{atext}+([.]#{atext}*)*"
    dot_atom = "#{dot_atom_text}"
    qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]'
    text = "[\\x01-\\x09\\x11\\x12\\x14-\\x7f]"
    quoted_pair = "(\\x5c#{text})"
    qcontent = "(?:#{qtext}|#{quoted_pair})"
    quoted_string = "[\"]#{qcontent}+[\"]"
    atom = "#{atext}+"
    word = "(?:#{atom}|#{quoted_string})"
    obs_local_part = "#{word}([.]#{word})*"
    local_part = "(?:#{dot_atom}|#{quoted_string}|#{obs_local_part})"
    no_ws_ctl = "\\x01-\\x08\\x11\\x12\\x14-\\x1f\\x7f"   
    dtext = "[#{no_ws_ctl}\\x21-\\x5a\\x5e-\\x7e]"
    dcontent = "(?:#{dtext}|#{quoted_pair})"
    domain_literal = "\\[#{dcontent}+\\]"
    obs_domain = "#{atom}([.]#{atom})*"
    domain = "(?:#{dot_atom}|#{domain_literal}|#{obs_domain})"
    addr_spec = "#{local_part}\@#{domain}"
    pattern = /^#{addr_spec}$/
  end
end

# Default options
opt = {
  :base_dir => ENV['HOME'],
  :stat_file => 'histstat',
  :temp_file => 'temp-rsrcmeter-bwcalc',
  :bw_months => 5
}

# Our option flag parsing
OptionParser.new do |opts|
  opts.banner = "Unofficial TxD Disk & HTTP Bandwidth Usage Meter\nUsage: rsrcmeter [options]"
  
  opts.on("-b", "--base BASE", "Change the base directory, defaults to user's $HOME", String) {|base|
    if File.exists?(base)
      opt[:base_dir] = base
    else
      raise(ArgumentError, "Directory (#{base}) specified with -b does not exist")
    end
  }
  
  opts.on("--stat-file FILE", "Change default historical data file from '#{opt[:stat_file]}'", String) {|file|
    opt[:stat_file] = file
  }
  
  opts.on("--temp-file FILE", "Change default temporary file from '#{opt[:temp_file]}'", String) {|file|
    opt[:temp_file] = file
  }
  
  opts.on("-m NUM", "Number of months' bandwidth to show prior to current month (default: #{opt[:bw_months]})", Integer) {|mons|
    opt[:bw_months] = mons if mons > 0
  }
  
  opts.on("-e", "--email ADDRESS", "E-mail results to ADDRESS *instead* of outputting to the screen", String) {|addr|
    if RFC2822::EmailAddress =~ addr
      opt[:email_to] = addr
    else
      raise(ArgumentError, "Invalid e-mail address provided to -e")
    end
  }
  
  opts.on_tail("-h", "--help", "Show this message") do
    puts opts
    exit
  end
end.parse!

Dir.chdir(opt[:base_dir])
File.delete(opt[:temp_file]) if File.exists?(opt[:temp_file])

# Look for existing monthly statistics file
if File.exists?(opt[:stat_file])
  # Load and process existing stats
  @stats = Array.new
  lines = File.readlines(opt[:stat_file])
  lines.each {|l| (@stats << [l.chomp.split(',')[0], l.chomp.split(',')[1].to_f]) unless (l.strip)[0,1] == '#'}
  @stats.sort!
  # Determine if any months need to be added
  if Date.today.month == 1
    pm_year = Date.today.year - 1
    pm_month = 12
  else
    pm_year = Date.today.year
    pm_month = Date.today.month - 1
  end
  stop_month = pm_year.to_s + (pm_month < 10 ? '0' : '') + pm_month.to_s
  proc_year = @stats.last[0][0,4].to_i
  proc_month = @stats.last[0][4,2].to_i
  proc_year += 1 if proc_month == 12
  proc_month = (proc_month == 12) ? 1 : proc_month + 1
  proc_str = proc_year.to_s + (proc_month < 10 ? '0' : '') + proc_month.to_s
  # Add any months not already calculated
  while proc_str <= stop_month
    datestr = proc_str + "??"
    File.delete(opt[:temp_file]) if File.exists?(opt[:temp_file])
    `cat logs/access_log.#{datestr} 2>/dev/null > #{opt[:temp_file]}`
    `cat domains/*/logs/access_log.#{datestr} 2>/dev/null >> #{opt[:temp_file]}`
    `zcat logs/access_log.#{datestr}.gz 2>/dev/null >> #{opt[:temp_file]}`
    `zcat domains/*/logs/access_log.#{datestr}.gz 2>/dev/null >> #{opt[:temp_file]}`
    month_usage = `cat #{opt[:temp_file]} | awk '{sum += $10} END {print sum}'`.chomp.to_i
    @stats << [proc_str, month_usage]
    # advance counting
    proc_year += 1 if proc_month == 12
    proc_month = (proc_month == 12) ? 1 : proc_month + 1
    proc_str = proc_year.to_s + (proc_month < 10 ? '0' : '') + proc_month.to_s
  end
# Statistics files doesn't exist
else
  # Look for earliest log file
  file_list = Array.new
  Dir.foreach(opt[:base_dir] + "/logs") {|i| file_list << i if /^access_log.\d{8}/ =~ i}
  if File.exists?(opt[:base_dir] + "/domains")
    domains = Array.new
    Dir.foreach(opt[:base_dir] + "/domains") {|dom| domains << dom if /^\w+\.\w+/ =~ dom}
    domains.each {|dom| Dir.foreach(opt[:base_dir] + "/domains/" + dom + "/logs") {|i| file_list << i if /^access_log.\d{8}/  =~ i}}
  end
  file_list.sort!
  unless Date.today.year.to_s + Date.today.month.to_s == file_list.first[11,6]
    # Process from earliest_log year/month forward
    earliest_log_year = file_list.first[11,4]
    earliest_log_month = file_list.first[15,2]
    @stats = Array.new
    earliest_log_year.to_i.upto(Date.today.year) do |year|
      start_month = (earliest_log_year.to_i == year) ? earliest_log_month.to_i : 1;
      start_month.upto(12) do |month|
        unless (year == Date.today.year and month >= Date.today.month)
          month = "0" + month.to_s if month < 10
          datestr = year.to_s + month.to_s + '??'
          File.delete(opt[:temp_file]) if File.exists?(opt[:temp_file])
          `cat logs/access_log.#{datestr} 2>/dev/null > #{opt[:temp_file]}`
          `cat domains/*/logs/access_log.#{datestr} 2>/dev/null >> #{opt[:temp_file]}`
          `zcat logs/access_log.#{datestr}.gz 2>/dev/null >> #{opt[:temp_file]}`
          `zcat domains/*/logs/access_log.#{datestr}.gz 2>/dev/null >> #{opt[:temp_file]}`
          month_usage = `cat #{opt[:temp_file]} | awk '{sum += $10} END {print sum}'`.chomp.to_i
          @stats << [year.to_s + month.to_s, month_usage]
        end
      end
    end
  end
end

# Write @stats back to opt[:stat_file] to record any changes
File.open(opt[:stat_file], 'w') {|f|
  f.puts "# rsrcmeter historical statistics file"
  f.puts "# Contains only completed months"
  @stats.each {|i| f.puts i[0] + ',' + i[1].to_s}
}

# Calculate bandwidth consumption for current month
datestr = Date.today.year.to_s + Date.today.month.to_s + "??"
`cat logs/access_log 2>/dev/null > #{opt[:temp_file]}`
`cat domains/*/logs/access_log 2>/dev/null >> #{opt[:temp_file]}`
`cat logs/access_log.#{datestr} 2>/dev/null >> #{opt[:temp_file]}`
`cat domains/*/logs/access_log.#{datestr} 2>/dev/null >> #{opt[:temp_file]}`
`zcat logs/access_log.#{datestr}.gz 2>/dev/null >> #{opt[:temp_file]}`
`zcat domains/*/logs/access_log.#{datestr}.gz 2>/dev/null >> #{opt[:temp_file]}`
usage = `cat #{opt[:temp_file]} | awk '{sum += $10} END {print sum}'`.chomp.to_f / 1024 / 1024
File.delete(opt[:temp_file]) if File.exists?(opt[:temp_file])
# Determine disk usage
quotaline = `quota -g | tail -n 1`
disk_usage = `echo -n "#{quotaline}" | awk '{print $2}'`.to_f
disk_quota = `echo -n "#{quotaline}" | awk '{print $3}'`.to_f
disk_percent_used = (disk_usage / disk_quota) * 100

# Output results
results = ""
results << "Disk usage: " + sprintf("%.4f", disk_usage / 1024) + " MiB (Quota: " + sprintf("%.4f", disk_quota / 1024 / 1024) +" GiB | " + sprintf("%.1f", disk_percent_used) + "% used)\n"
results << "Bandwidth:\n" + Date::ABBR_MONTHNAMES[Date.today.month] + " " + Date.today.year.to_s + ": " + sprintf("%.4f", usage) + " MiB (Month to Date)\n"
hist_usage = @stats.last(opt[:bw_months]).reverse
hist_usage.each {|h| results << Date::ABBR_MONTHNAMES[Date.parse(h[0] + "01").month] + ' ' + h[0][0,4] + ": " + sprintf("%.4f", (h[1].to_f / 1024 / 1024)) + " MiB\n"}

# We're either e-mailing or outputting
if opt[:email_to]
  t = Time.now.strftime("%a %d %B %Y %H:%M:%S %Z")
  message = <<EOM
From: TxD Resource Meter <#{ENV['USER']}-noreply@#{`/bin/hostname`.chomp}>
To: #{opt[:email_to]}
Subject: [TxD Resource Meter] #{t} report for #{ENV['USER']}
X-Mailer: rsrcmeter | http://textsnippets.com/posts/show/842

Resource Report - #{t}
#{results}
---------------
Generated by rsrcmeter
EOM
  File.open("temp-emailresult", "w") { |file| file.print message }
  `cat temp-emailresult | /usr/sbin/sendmail -t`
  File.delete("temp-emailresult")
else
  puts results
end

rsrcmeter for TxD

Newer version at http://textsnippets.com/posts/show/842

TextDrive: Simple disk usage and HTTP bandwidth counts
This is an updated version of http://textsnippets.com/posts/show/621

#!/usr/local/bin/ruby
Dir.chdir(ENV['HOME'])
# Disk usage
quotaline = `quota -g | tail -n 1`
usage = `echo -n "#{quotaline}" | awk '{print $2}'`.to_f
quota = `echo -n "#{quotaline}" | awk '{print $3}'`.to_f
percent_used = (usage / quota) * 100
puts "Disk usage: " + sprintf("%.4f", usage/1024) + " MiB (Quota: " + sprintf("%.4f", quota/1024/1024) +" GiB; " + sprintf("%.1f", percent_used) + "% used)"

# HTTP Bandwidth
print "Calculating Bandwidth Usage..."
month = `date +"%B %Y"`.chomp
access_logs="access_log." + `date +%Y%m`.chomp + "??"
system("cat logs/access_log 2>/dev/null > temp-bandwidthcount") # Today's log
system("cat domains/*/logs/access_log 2>/dev/null >> temp-bandwidthcount")
system("cat logs/#{access_logs} 2>/dev/null >> temp-bandwidthcount") # Any logs not (yet) gzipped
system("cat domains/*/logs/#{access_logs} 2>/dev/null >> temp-bandwidthcount")
system("zcat logs/#{access_logs}.gz 2>/dev/null >> temp-bandwidthcount") # Gzipped logs from previous days
system("zcat domains/*/logs/#{access_logs}.gz 2>/dev/null >> temp-bandwidthcount")

usage = `cat temp-bandwidthcount | awk '{sum += $10} END {print sum}'`.chomp.to_f / 1024 / 1024
File.delete("temp-bandwidthcount")

30.times {print "\b"}
puts "Bandwidth used for #{month}: " + sprintf("%.4f", usage) + " MiB"


Installing:
Easy as 1..2..3:
curl -o rsrcmeter http://ajz.textdriven.com/rsrcmeter.txt
chmod u+x rsrcmeter
./rsrcmeter

Using in Webmin (Under Run Processes, Command to run):
export HOME="/users/home/YOURUSERNAME"; $HOME/rsrcmeter


MD5 hash: 0364b47675fee1902db1a32703cecf3f

Sample output:
Disk usage: 2.2910 MiB (Quota: 1.9073 GiB; 0.1% used)
Bandwidth used for August 2006: 0.5773 MiB


Confirmed to work on:
- Cardero,
- Davie (by rsimplicio),
- Pendrell (by iolaire),
- Thurlow (by janovetz),
- Bidwell & Jervis (by springworks),
- Chilco (by atl),
- Burnaby (by igner),
- Broughton (Biz Server, by Rich),
- Howe (scoobyfoo),
- Nicola (lderezinski),
- Jervis (mjboyle), and
- One (robertb)
*Should work on any TxD shared/business server.*

Getting HTTP Auth to play nice with PHP run under FastCGI

<?php
/**
 * Get HTTP Auth to work with PHP+FastCGI
 *
 * @author  Jacques Marneweck 
 * @license PHP License v3.01
 */

/**
 * Get HTTP Auth to work with PHP+FastCGI
 */

    

if (isset($_SERVER["AUTHORIZATION"]) && !empty($_SERVER["AUTHORIZATION"])) {

    list ($type, $cred) = split (" ", $_SERVER['AUTHORIZATION']);

    if ($type == 'Basic') {
        list ($user, $pass) = explode (":", base64_decode($cred));
        $_SERVER['PHP_AUTH_USER'] = $user;
        $_SERVER['PHP_AUTH_PW'] = $pass;
    }

}

PHP HTTP Connection class

class HttpConnection {
  private $host;
  private $port;
  private $headers;
  
  public function __construct($host, $port) {
    $this->host    = $host;
    $this->port    = $port;
    $this->headers = new HeaderList(array(), "\r\n");
  }
  
  public function get($path, $params = array(), $headers = array()) {
    return $this->send($path, 'get', $params, $headers);
  }
  
  public function post($path, $params = array(), $headers = array()) {
    return $this->send($path, 'post', $params, $headers);
  }
  
  public static function serialize_auth($user, $pass) {
    return base64_encode("$user:$pass");
  }
  
  public static function serialize_params($params) {
   $query_string = array();
    foreach ($params as $key => $value) {
      $query_string[] = urlencode($key) . '=' . urlencode($value);
    }
    return implode('&', $query_string);
  }
  
  private function send($path, $method, $params = array(), $headers = array()) {  
    $this->headers->add($headers);  
    $params = self::serialize_params($params);
    
    $this->request = strtoupper($method) . " http://{$this->host}{$path}?{$params} HTTP/1.0\r\n";
    $this->request .= $this->headers->to_s() . "\r\n";    

    if ($fp = fsockopen($this->host, $this->port, $errno, $errstr, 15)) {
      if (fwrite($fp, $this->request)) {
        while (!feof($fp)) {
         $this->response .= fread($fp, 4096);
       }
      }
      fclose($fp);
    } else {
      throw new Exception("could not establish connection with $host");
    }
    
    return $this->parse_response();
  }
  
  private function parse_response() {
    $this->response = str_replace("\r\n", "\n", $this->response);
    list($headers, $body) = explode("\n\n", $this->response, 2);
    $headers = new HeaderList($headers);
    return array('headers' => $headers->to_a(), 'body' => $body, 'code' => $headers->get_response_code());
  }
}

class HeaderList {
  private $headers;
  private $response_code;
  private $linebreak;
  
  public function __construct($headers = array(), $linebreak = "\n") {
    $this->linebreak = $linebreak;
    $this->headers   = $headers;
    if (is_string($this->headers)) {
      $this->parse_headers_string();
    }
  }
  
  public function to_s() {
    $headers = '';
    foreach ($this->headers as $header => $value) {
      $headers .= "$header: $value{$this->linebreak}";
    }
    return $headers;
  }
  
  public function to_a() {
    return $this->headers;
  }
  
  public function __toString() {
    return $this->to_s();
  }
  
  public function add($headers) {
    $this->headers = array_merge($this->headers, $headers);
  }
  
  public function get($header) {
    return $this->headers[$header];
  }
  
  public function get_response_code() {
    return $this->response_code;
  }
  
  private function parse_headers_string() {
    $replace = ($this->linebreak == "\n" ? "\r\n" : "\n");
    $headers = str_replace($replace, $this->linebreak, trim($this->headers));
    $headers = explode($this->linebreak, $headers);
    $this->headers = array();
    if (preg_match('/^HTTP\/\d\.\d (\d{3})/', $headers[0], $matches)) {
      $this->response_code = $matches[1];
      array_shift($headers);
    }
    foreach ($headers as $string) {
      list($header, $value) = explode(': ', $string, 2);
      $this->headers[$header] = $value;
    }
  }
}

Using HTTP conditions and url.access-deny to have Lighttpd block some user agents and referers

# deny access for Indy Library a Tester
$HTTP["useragent"] =~ "Indy" { url.access-deny = ( "" ) }
 
# deny access for a hydrocodone containing refer 
$HTTP["referer"] =~ "hydrocodone" { url.access-deny = ( "" ) }
« Newer Snippets
Older Snippets »
8 total  XML / RSS feed