Hak5
Save 10% at GoDaddy.com with coupon code HAK

Episode 1x03

From Hak5

Jump to: navigation, search

Synopsis

In this episode of Hak5 the crew explores ways to hack RSS into your morning routine with a custom alarm clock and newspaper. Harrison makes us all a little more paranoid about network security with an ARP Cache Poisoning overview, then takes it to the streets. Wess gives the case a break and takes on the IBM Model M beast-keyboard while Alli goes retro with a classic arcade game review. All this plus a flaming-case-mod and a flame-proof blueberry hefeweizen.

Modding the IBM Model M Keyboard

Information on the Model M: http://www.shoppalstores.com/ibmmodelm/ http://en.wikipedia.org/wiki/IBM_Model_M_Keyboard

Creating an RSS Speaking Alarm Clock

  1. Install Additional Voices (optional)
    1. First install Microsoft Reader[1]
    2. Then install the Reader TTS package[2]
  2. Install Perl[3]
  3. Download nmake[4]
  4. Install XML-RSS perl module[5]
  5. Download the following perl script (rss2html5.pl), which is a modification of rss2html.pl[6]

Code:

#!/usr/bin/perl -w
# rss2html - converts an RSS file to HTML
# It take one argument, either a file on the local system,
# or an HTTP URL like http://slashdot.org/slashdot.rdf
# by Jonathan Eisenzopf. v1.0 19990901
# Copyright (c) 1999 Jupitermedia Corp. All Rights Reserved.
# See http://www.webreference.com/perl for more information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

# INCLUDES
use strict;
use XML::RSS;
use LWP::Simple;

# Declare variables
my $content;
my $file;

# MAIN
# check for command-line argument
die "Usage: rss2html.pl (<RSS file> | <URL>)\n" unless @ARGV == 1;

# get the command-line argument
my $arg = shift;

# create new instance of XML::RSS
my $rss = new XML::RSS;

# argument is a URL
if ($arg=~ /http:/i) {
    $content = get($arg);
    die "Could not retrieve $arg" unless $content;
    # parse the RSS content
    $rss->parse($content);

# argument is a file
} else {
    $file = $arg;
    die "File \"$file\" does't exist.\n" unless -e $file;
    # parse the RSS file
    $rss->parsefile($file);
}

# print the HTML channel
&print_html($rss);

# SUBROUTINES
sub print_html {
    my $rss = shift;
    print <<HTML;
HTML

    # print the channel items
    my $i = 0;
    foreach my $item (@{$rss->{'items'}})
    {
      next unless defined($item->{'title'});
      print "$item->{'title'}... ... ... ... ...\n";
      if($i==4){
         last;   
      }
       $i = $i + 1;
    }

    # if there's a copyright element
    if ($rss->{'channel'}->{'copyright'}) {
   print <<HTML;
<p><sub>$rss->{'channel'}->{'copyright'}</sub></p>
HTML
    }

    print <<HTML;
HTML
}



7. Download the following TextToWave.vbs

Code: (text may be clipped but will be copied)

'Drop a plain text file on this script, and it will create an
'identically-named WAV file (except for the file extension!).
'The default audio format is set in the script with the constant
'AUDIO_FORMAT, or you may supply a format as a number from
'4 to 68. The audio format number is supplied as an OPTIONAL
'second argument to this script.
'
'Common formats: 8 (8KHz 8-bit mono), 16 (16KHz 8-bit mono),
'35 (44KHz 16-bit Stereo), 65 (GSM 8KHz), 66 (GSM 11KHz)

Option Explicit
dim tts, fs, ts, ss, strFile, strText, blnError, lngFormat
Const ForReading = 1
Const SSFMCreateForWrite = 3
Const AUDIO_FORMAT = 65 'Please refer to the SAFT function for value description

   'Check argument count
   If WScript.Arguments.Count = 0 Then
      MsgBox "Drop a text file on this script and I'll convert it into a WAV sound file."
      WScript.Quit 1
   End If
   'Make sure the argument is a file
   Set fs = CreateObject("Scripting.FileSystemObject")
   strFile = WScript.Arguments(0)
   strFile = Trim(strFile)
   If strFile = "" Then
      MsgBox "I can't read nothing! Give me the name of a text file."
      WScript.Quit 1
   End If
   If InStr(strFile, "\\") <> 1 And InStr(strFile, ":\") <> 2 Then
      strFile = fs.GetAbsolutePathName(fs.BuildPath(fs.GetFolder(".").Path, strFile))
   End If
   If Not fs.FileExists(strFile) Then
      MsgBox "I can't locate a file named """ & WScript.Arguments(0) & """. Try using a fully-qualified path and file name."
      WScript.Quit 1
   End If
   'Is there an optional second argument for the audio format?
   If WScript.Arguments.Count > 1 Then
      lngFormat = WScript.Arguments(1)
      If Not IsNumeric(lngFormat) Then
         MsgBox "The second argument, if supplied, must be a NUMBER. Yours wasn't!"
         WScript.Quit 1
      End If
      lngFormat = Int(Abs(lngFormat)) - 1
   Else
      lngFormat = AUDIO_FORMAT - 1
   End If
   'Get the SAPI 5text-to-voice engine.
   Set tts = Nothing
   Set tts = CreateObject("Sapi.SpVoice")
   If tts Is Nothing Then
      InputBox "You don't have SAPI 5! Please hop on the internet, download, and install the Microsoft SAPI 5 speech development kit from here:", "Error", "http://download.microsoft.com/download/speechSDK/SDK/5.1/WXP/EN-US/speechsdk51.exe"
      WScript.Quit 1
   End If
   'Read the file
   Status "Reading text file"
   Set ts = fs.OpenTextFile(WScript.Arguments(0), ForReading, True)
   strText = ts.ReadAll
   ts.Close
   Set ts = Nothing
   'Generate a file name for the output WAV file
   strFile = Left(strFile, InStrRev(strFile, ".")) & "wav"
   'Check to see that chosen audio format is supported
   Err.Clear
   blnError = True
   On Error Resume Next
   Do While blnError
      lngFormat = lngFormat + 1
      If fs.FileExists(strFile) Then fs.DeleteFile strFile
      Set ss = CreateObject("Sapi.SpFileStream")
      ss.Format.Type = lngFormat
      ss.Open strFile, SSFMCreateForWrite, False
      Set tts.AudioOutputStream = ss
      Err.Clear
      If Err.Number = 0 Then
         Status "USING:  Format " & lngFormat & " (" & SAFT(lngFormat) & ")"
         blnError = False
      Else
         Status "FAILED: Format " & lngFormat & " (" & SAFT(lngFormat) & ")"
         Set tts.AudioOutputStream = Nothing
         ss.Close
         Set ss = Nothing
         blnError = True
      End If
   Loop
   'Convert text to WAV!
   Status "Converting to WAV"
   tts.Speak strText
   'Clean up
   ss.Close
   Set ss = Nothing
   Set tts = Nothing

Sub Status(strMessage)
   If Lcase(Right(Wscript.FullName, 12)) = "\cscript.exe" Then
      Wscript.Echo strMessage
   End If
End Sub

Function SAFT(lngSpeechAudioFormatType)
'Returns a text description of the format type
'Values from SpeechLib.SpeechAudioFormatType
Dim strSAFT, lngSAFT
   'Preserve input variable
   lngSAFT = lngSpeechAudioFormatType
   'Stop bad input
   If Not IsNumeric(lngSAFT) Then
      SAFT = "Unknown"
      Exit Function
   End If
   If lngSAFT < 4 Or lngSAFT > 68 Then
      SAFT = "Unknown"
      Exit Function
   End If
   'NORMAL for values between 0 and 39
   'stereo = add 1
   '16-bit = add 2
   '8KHz = 4
   '11KHz = 8
   '12KHz = 12
   '16KHz = 16
   '22KHz = 20
   '24KHz = 24
   '32KHz = 28
   '44KHz = 32
   '48KHz = 36
   If lngSAFT < 40 Then
      lngSAFT = lngSAFT - 4 'Offset so it starts at zero
      strSAFT = Split("8 11 12 16 22 24 32 44 48")(lngSAFT \ 4) & "KHz"
      strSAFT = strSAFT & " "
      strSAFT = strSAFT & Split("8 16")((lngSAFT And 2) \ 2) & "bit"
      strSAFT = strSAFT & " "
      strSAFT = strSAFT & Split("Mono Stereo")(lngSAFT And 1)
   End If
   'TrueSpeech_8kHz1BitMono = 40
   If lngSAFT = 40 Then
      strSAFT = "TrueSpeech 8KHz 1bit Mono"
   End If
   'stereo = add 1 to below values
   'CCITT_ALaw for values between 41 and 48
   '8KHz = 41
   '11KHz = 43
   '22KHz = 45
   '44KHz = 47
   'CCITT_uLaw for values between 49 and 56
   '8KHz = 49
   '11KHz = 51
   '22KHz = 53
   '44KHz = 55
   'ADPCM for values between 57 and 64
   '8KHz = 57
   '11KHz = 59
   '22KHz = 61
   '44KHz = 63
   If ((lngSAFT > 40) And (lngSAFT < 65)) Then
      lngSAFT = lngSAFT - 41 'Offset so it starts at zero
      strSAFT = Split("CCITT_ALaw CCITT_uLaw ADPCM")(lngSAFT \ 8)
      strSAFT = strSAFT & " "
      strSAFT = strSAFT & Split("8 11 22 44")((lngSAFT \ 2) And 3) & "KHz"
      strSAFT = strSAFT & " "
      strSAFT = strSAFT & Split("Mono Stereo")(lngSAFT And 1)
   End If
   'GSM_610 for values between 65 and 68 (no stereo)
   '8KHz = 65
   '11KHz = 66
   '22KHz = 67
   '44KHz = 68
   If lngSAFT > 64 Then
      Select Case lngSAFT
         Case 65
            strSAFT = "GSM_610 8KHz Mono"
         Case 66
            strSAFT = "GSM_610 11KHz Mono"
         Case 67
            strSAFT = "GSM_610 22KHz Mono"
         Case 68
            strSAFT = "GSM_610 44KHz Mono"
         Case Else
            strSAFT = "Unknown"
      End Select
   End If
   'Return the value
   SAFT = strSAFT
End Function



8. Create the following batch script:

Code:

echo "Good Morning Your-Name-Goes-Here... ... ... ..." >> alarm.txt
echo "Top 5 stories from Dig this morning are:... ..." >> alarm.txt
perl rss2html5.pl http://www.digg.com/rss/index.xml >> alarm.txt

echo "Top 5 stories from Slash Dot this morning are:... ..." >> alarm.txt
perl rss2html5.pl http://rss.slashdot.org/Slashdot/slashdot >> alarm.txt

echo "Top 5 stories from Boing Boing are:... ..." >> alarm.txt
perl rss2html5.pl http://feeds.feedburner.com/boingboing/iBag >> alarm.txt

echo "... ... Have a nice day!... ... ... ... ... ... ... ... ..." >> alarm.txt
echo "Oh, and by the way, Hack point five owns!" >> alarm.txt

del alarm.wav
TextToWave.vbs alarm.txt 35
del alarm.txt
start alarm.m3u



(Replace RSS feeds as you so desire)

8. Create the alarm.m3u playlist file pointing to your wake-up-song and alarm.wav using the following example:

Code:

#EXTM3U
#EXTINF:30,B-52's - Love Shack
love_shack.mp3
#EXTINF:81,alarm
alarm.wav



9. Schedule the batch script using the AT command[7].

Example:

AT 07:30 /EVERY:m,t,w,th,f c:\alarm\alarm.bat



Links:

  1. http://www.microsoft.com/reader/downloads/default.asp
  2. http://www.microsoft.com/reader/developers/downloads/tts.asp
  3. http://activestate.com/
  4. http://support.microsoft.com/default.aspx?scid=kb;en-us;Q132084
  5. http://search.cpan.org/dist/XML-RSS/
  6. http://www.webreference.com/perl/tutorial/8/index.html
  7. http://www.ss64.com/nt/at.html

Festival: http://cstr.ed.ac.uk/projects/festival Linux Distors: http://linux.org/dist

ARP Cache Poisoning Attack Overview

Arp Cache Poisoning

I. Tools

  1. Nmap (win/unix) - http://www.insecure.org/nmap
    1. Security scanner for network enumeration.
    2. Great for scanning ports and finding server apps
  2. Cain&Abel (win) - http://www.oxid.it/cain.html
    1. ARP attack tool.
    2. "Password recovery tool" for sniffing passwords
  3. Ettercap (unix) - http://ettercap.sourceforge.net/
    1. Arp attack tool for unix
    2. Supports active and passive disection of many protocols
  4. Ethereal (win/unix)- http://www.ethereal.com/
    1. Network protocol analyzer
    2. Creates excellent capture files

II. Procedure

  1. Scan the network and choose a target.
    1. Nmap allows you do get detailed information on the host.
    2. Cain&Abel also has a built in network scanner if time is an issue.
  2. Perform the Arp Attack.
    1. Spoof mac address.
    2. Start poisining.
  3. Intercept network traffic with ethereal
    1. Select the appropriate ethernet device.
    2. Filter traffic by typing in the protocol.

III. Further Reading

  1. Check out a tool called Taranis.
  2. ARPoison (unix) - http://arpoison.sourceforge.net/
  3. Parasite - http://www.securityfocus.com/data/tools/parasite-0.5.tar.gz
  4. Dsniff - http://www.monkey.org/~dugsong/dsniff/
  5. Snort - http://www.snort.org
  6. Arpwatch - http://www.redhat.com/swr/i386/arpwatch-2.1a4-29.i386.html

IV. Countermeasures

  1. Certain firewalls will store ARP tables and not accept new entries
  2. Insecure.org - http://seclists.org/lists/pen-test/2001/May/0106.html

Creating an RSS Newspaper

  1. Download cURL[1]
  2. Download html2pdf[2]
  3. Download nircmd[3]
  4. Download the following css_2.css

Code:

/* CSS Document */
   
   body {
      text-align:center;
      }
     
   
   
   #frame {
      width: 750px;
      margin-right:auto;
      margin-left:auto;
      margin-top:10px;
      padding:0px;
      text-align:left;
      border-style: solid;
       border-width: 1px;
       border-color:#003366;
      }
     
   #contentleft {
      width:150px;
      padding:10px;
      float:left;
      background:#fff;
      border-style: solid;
       border-width: 1px;
       border-color:#003366;
       border-left-width: 0px;
       border-top-width: 0px;
      }
   
   #contentcenter {
      width:550px;
      padding:10px;
      float: left;
      background:#fff;
      }
   
   #contentright {
      width:150px;
      padding:0px;
      float:right;
      background:#fff;
      border-style: solid;
       border-width: 1px;
       border-color:#003366;
       border-right-width: 0px;
       border-top-width: 0px;
      }
   
   #contentheader {
      background: #fff;
      border-bottom-width: 1px;
      border-top-width: 0px;
      border-right-width: 0px;
      border-left-width: 0px;
      border-style: solid;
       border-color:#003366;
      }
     
   p,h1,pre {
      margin:0px 10px 10px 10px;
      }
     
   h1 {
      font-size:14px;
      padding-top:10px;
      }
   h2 {
   font-size:12px;
      padding-top:10px;
      }
   
     
   #contentheader h1 {
      font-size:14px;
      margin:0px 10px 10px 10px;
      font-family: verdana;
      color: #003366;
      font-weight: bold;
      }
     
   #contentheader h2
   {
       font-size:12px;
      margin:0px;
      font-family: verdana;
      color: #003366;
      font-weight: bold;
   
   }
   
   #contentright p { font-size:12px}
   
   #contentleft p { font-size:12px}
   
   #contentcenter p
   {
     font-size:12px;
     font-family: verdana;   
   }
   
   #contentleft h1
   {
    font-size: 12px;
    font-family: verdana;     
   }
   
   #contentright h1
   {
    font-size: 12px;
    font-family: verdana;     
   }
   
   #contentcenter h1
   {
    font-size: 12px;
    font-family: verdana;
   
   }

   
   a:link {
    color: #f60;
   }
   
   a:visited {
    color: #666;
   }
   
   a:active {
    color: #369;
   }
   
   h a:link
   {
     margin:0px 10px 10px 10px;
     font-size:12px;
     font-family: verdana;
     font-weight: bold;
     color: #003366;
     margin: 0px;
   }
   
   
   h a:visited
   {
     margin:0px 10px 10px 10px;   
     font-size:12px;
     font-family: verdana;
     font-weight: bold;
     color: #666;
     margin: 0px;
   }
   
   h a:active
   {
     margin:0px 10px 10px 10px;
     font-size:12px;
     font-family: verdana;
     font-weight: bold;
     color: #369;
     margin: 0px;
   }
   
    hr {
    color: #999999;
     height: 1px;
     width: 80%;
     }



5. Download the following news.php

Code: (text may be clipped but will be copied)

<?php
class rssNews
{
   
   var $default_cp = 'UTF-8';
   var $CDATA = 'nochange';
   var $cp = '';
   var $items_limit = 3;
   var $stripHTML = False;
   var $date_format = '';

   var $channeltags = array ('title', 'link', 'description', 'language', 'copyright', 'managingEditor', 'webMaster', 'lastBuildDate', 'rating', 'docs');
   var $itemtags = array('title', 'link', 'description', 'author', 'category', 'comments', 'enclosure', 'guid', 'pubDate', 'source');
   var $imagetags = array('title', 'url', 'link', 'width', 'height');
   var $textinputtags = array('title', 'description', 'name', 'link');

   // Parse RSS file and returns associative array.
   function parseRSS ($rss_url)
   {     
      // If cache is enabled
      if ($this->cache_dir != '')
      {
         $cache_file = $this->cache_dir . '/rsscache_' . md5($rss_url);
         $timedif = @(time() - filemtime($cache_file));
         //cached file is fresh enough just return old array
         if ($timedif < $this->cache_time)
         {
            $result = unserialize(join('', file($cache_file)));
            // set 'cached' to 1 only if cached file is correct
            if ($result) $result['cached'] = 1;
         }
         //else get fresh data
         else
         {
            //creating a new parse
            $result = $this->Parse($rss_url);
            $serialized = serialize($result);
            if ($f = @fopen($cache_file, 'w'))
            {
               fwrite ($f, $serialized, strlen($serialized));
               fclose($f);
            }
            if($result)
            {
                $result['cached'] = 0;
            }
         }
      }
      // If cache is disabled, load and parse the file directly
      else
      {
         $result = $this->Parse($rss_url);
         if($result)
         {
            $result['cached'] = 0;
         }
      }
      // return result
      return $result;
   }
   
   // -------------------------------------------------------------------
   // Modification of preg_match(); return trimed field with index 1
   // from 'classic' preg_match() array output
   // -------------------------------------------------------------------
   function my_preg_match ($pattern, $subject)
   {
      // start regullar expression
      preg_match($pattern, $subject, $out);

      // if there is some result... process it and return it
      if(isset($out[1]))
      {
         // Process CDATA (if present)
         if ($this->CDATA == 'content')
         {    // Get CDATA content (without CDATA tag)
            $out[1] = strtr($out[1], array('<![CDATA['=>'', ']]>'=>''));
         }
         elseif ($this->CDATA == 'strip')
         {    // Strip CDATA
            $out[1] = strtr($out[1], array('<![CDATA['=>'', ']]>'=>''));
         }

         // If code page is set convert character encoding to required
         if ($this->cp != '')
         {
            $out[1] = iconv($this->rsscp, $this->cp.'//TRANSLIT', $out[1]);
         }
         // Return result
         return trim($out[1]);
      } else
      {
         // if there is NO result, return empty string
         return '';
      }
   }

   // -------------------------------------------------------------------
   // Replace HTML entities &something; by real characters
   // -------------------------------------------------------------------
   function unhtmlentities ($string)
   {
      // Get HTML entities table
      $trans_tbl = get_html_translation_table (HTML_ENTITIES, ENT_QUOTES);
      // Flip keys<==>values
      $trans_tbl = array_flip ($trans_tbl);
      // Add support for &apos; entity (missing in HTML_ENTITIES)
      $trans_tbl += array('&apos;' => "'");
      // Replace entities by values
      return strtr ($string, $trans_tbl);
   }

   // -------------------------------------------------------------------
   // Parse() is private method used by parseRSS() to load and parse RSS file.
   // Don't use Parse() in your scripts - use parseRSS($rss_file) instead.
   // -------------------------------------------------------------------
   function Parse ($rss_url)
   {
      // Open and load RSS file
      if ($f = @fopen($rss_url, 'r'))
      {
         $rss_content = '';
         while (!feof($f))
         {
            $rss_content .= fgets($f, 4096);
         }
         fclose($f);

         // Parse document encoding
         $result['encoding'] = $this->my_preg_match("'encoding=[\'\"](.*?)[\'\"]'si", $rss_content);
         // if document codepage is specified, use it
         if ($result['encoding'] != '')
         {
            $this->rsscp = $result['encoding']; // This is used in my_preg_match()
         }
         // otherwise use the default codepage
         else
         {
            $this->rsscp = $this->default_cp; // This is used in my_preg_match()
         }
         // Parse CHANNEL info
         preg_match("'<channel.*?>(.*?)</channel>'si", $rss_content, $out_channel);
         foreach($this->channeltags as $channeltag)
         {
            $temp = $this->my_preg_match("'<$channeltag.*?>(.*?)</$channeltag>'si", $out_channel[1]);
            if($temp != '')
            {
               $result[$channeltag] = $temp; // Set only if not empty
            }
         }
         preg_match("'<textinput(|[^>]*[^/])>(.*?)</textinput>'si", $rss_content, $out_textinfo);
         
         
         if (isset($out_textinfo[2]))
         {
            foreach($this->textinputtags as $textinputtag)
            {
               $temp = $this->my_preg_match("'<$textinputtag.*?>(.*?)</$textinputtag>'si", $out_textinfo[2]);
               if($temp != '') $result['textinput_'.$textinputtag] = $temp; // Set only if not empty
            }
         }
         
         
         //image
         preg_match("'<image.*?>(.*?)</image>'si", $rss_content, $out_imageinfo);
         if (isset($out_imageinfo[1]))
         {
            foreach($this->imagetags as $imagetag)
            {
               $temp = $this->my_preg_match("'<$imagetag.*?>(.*?)</$imagetag>'si", $out_imageinfo[1]);
               if ($temp != '')
               {
                  $result['image_'.$imagetag] = $temp; // Set only if not empty
               }
            }
         }

         // Parse ITEMS
         preg_match_all("'<item(| .*?)>(.*?)</item>'si", $rss_content, $items);
         $rss_items = $items[2];
         $i = 0;
         $result['items'] = array(); // create array even if there are no items
         foreach( $rss_items as $rss_item)
         {
            // If number of items is lower then limit: Parse one item
            if ($i < $this->items_limit || $this->items_limit == 0)
            {
               foreach($this->itemtags as $itemtag)
               {
                  $temp = $this->my_preg_match("'<$itemtag.*?>(.*?)</$itemtag>'si", $rss_item);
                  if ($temp != '')
                  {
                     $result['items'][$i][$itemtag] = $temp; // Set only if not empty
                  }
               }
               
               // Strip HTML tags from DESCRIPTION
               if ($this->stripHTML && $result['items'][$i]['description'])
               {
                  $result['items'][$i]['description'] = strip_tags($this->unhtmlentities(strip_tags($result['items'][$i]['description'])));
               }
               
               // Strip HTML tags from TITLE
               if ($this->stripHTML && $result['items'][$i]['title'])
               {
                  $result['items'][$i]['title'] = strip_tags($this->unhtmlentities(strip_tags($result['items'][$i]['title'])));
               }
               // Item counter
               $i++;
            }
         }

         $result['items_count'] = $i;
         return $result;
      }
      else // Error in opening return False
      {
         return False;
      }
   }
   
   function printRows($rssObject)
   {
         //validation of object   
         if ( isset($rssObject) )
         {
         
      ?>      <h><a href="<?= $rssObject[link] ?>"><?= $rssObject[title] ?></a><h>
            <p><i><?= $rssObject[description] ?></i></p>
      <?
            foreach( $rssObject['items'] as $item)
            {
      ?>
               <h2><a href="<?= $item[link] ?>"><?= strip_tags($item[title]) ?></a></h2>
               <p><?= strip_tags($item[description]) ?></p>   
      <?
            }
         
         }else
         {
               echo "Error: It's not possible to get $rssurl...";
         }
   }
}

?>



6. Download the following index.php

Code: (text may be clipped but will be copied)

<html>
<link rel="StyleSheet" href="css_2.css" type="text/css">
<?php

       //Include Once the News.php code for parsing
   include_once "./news.php";
   
   //Creation of URL array
   $url = Array();
      $url[0] = "http://xml.weather.yahoo.com/forecastrss?p=94102";
      $url[1] = "http://rss.slashdot.org/Slashdot/slashdot";
      $url[2] = "http://www.wired.com/news/feeds/rss2/0,2610,31,00.xml";
      $url[3] = "http://www.traffic.com/feeds/rss_sanfrancisco.xml";
      $url[4] = "http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/front_page/rss.xml";
   
   //Creation of URL Objects
   $rssFeed = Array();
      $rssFeed[0] = new rssNews;
      $rssFeed[1] = new rssNews;
      $rssFeed[2] = new rssNews;
      $rssFeed[3] = new rssNews;
      $rssFeed[4] = new rssNews;
   
   //Creation of cache directories
   for( $i = 0; $i <= 4; $i++ )
   {   
      $rssFeed[$i]->cache_dir = './temp';
      $rssFeed[$i]->cache_time = 1200;
   }
   
   //Parsing URL's
   $rsFeed = Array();
      $rsFeed[0] = $rssFeed[0]->parseRSS($url[0]);
      $rsFeed[1] = $rssFeed[1]->parseRSS($url[1]);
      $rsFeed[2] = $rssFeed[2]->parseRSS($url[2]);
      $rsFeed[3] = $rssFeed[3]->parseRSS($url[3]);
      $rsFeed[4] = $rssFeed[4]->parseRSS($url[4]);

?>
<body>
   
<div id="frame">

   <div id="contentheader">
      <div style="clear:left;">   
         <h1>Hak.5 RSS Newspaper</h1>
      </div>
      <!-- <div style="clear:right;">   
         <h2><? //echo date("l dS \of F Y"); ?></h2>
      </div>-->
   </div>
<div id="contentleft">
   <div style="clear:left;">
<?
   $rssFeed[0]->printRows($rsFeed[0]);   
?>
   </div>
   <div style="clear:left;">
<?
   $rssFeed[3]->printRows($rsFeed[3]);   
?>
   </div>
</div>


<div id="contentcenter">
   <div style="clear:center;">
<?
   $rssFeed[4]->printRows($rsFeed[4]);   
?>
   </div>

   <div style="clear:center;">
<?
   $rssFeed[1]->printRows($rsFeed[1]);   
?>
   </div>
</div>

   <br clear="all" /><!-- without this little <br /> NS6 and IE5PC do not stretch the frame div down to encopass the content DIVs -->
</div>

   </body>
</html>



7. Create the following newspaper.bat batch script:

Code:

del newspaper.html
del newspaper.pdf
del css_2.css
curl http://yourserver/rssnewspaper/css_2.css >> css_2.css
curl http://yourserver/rssnewspaper/index.php >> newspaper.html
doc2pdf.exe /nogui .\newspaper.html /outfile .\newspaper.pdf
nircmd shexec "print" "newspaper.pdf"



8. Schedule the batch script with the AT command Example: AT 07:00 /EVERY:m,t,w,th,f c:\news\newspaper.bat

Links: