Hi KWWH !
this method requires ssh access , so you need a vps , or dedi to make use of this script. ( or request your shared hosting to provide a chrooted jail shell )
and assumes that you have some basic knowledge about *nux and ssh.
and perl must be installed or else it wont work.

Code: 
apt-get install perl for deb/ubuntu/
yum install perl for  centos
Limitations that I know .
*200 Mb upload limit on collectors acc..
* ?

*make a working directory of your choice

PHP Code: 
cd /home
mkdir backuptors
cd backuptors 

*creating the shell file which will backup the database , upload to rs using the perl uploader .


create a new file called
vb_backup.sh with the below content


PHP Code: 
#!/bin/bash
# credits to jelsoft
# put the path to your vBulletin config.php
path_to_config="/PATH_TO_VBULLETIN_FOLDER/includes/config.php"

# If you need the full path to the mysqldump binaries or gzip binaries set below
mysqldumpcmd=mysqldump
gzipcmd
=gzip

# Edit at your own risk !

if [ ! -"$path_to_config]
then
    
echo "$path_to_config doesn't exist"
    
exit 1
fi

servername
=`perl -n -e "if (/MasterServer']\['servername'\]\s*=\s*'(.*)'/) { print \\$1; } else { print ''; }" $path_to_config`
dbusername=`perl -n -e "if (/MasterServer']\['username'\]\s*=\s*'(.*)'/) { print \\$1; } else { print ''; }" $path_to_config`
dbpassword=`perl -n -e "if (/MasterServer']\['password'\]\s*=\s*'(.*)'/) { print \\$1; } else { print ''; }" $path_to_config`
dbname=`perl -n -e "if (/Database']\['dbname'\]\s*=\s*'(.*)'/) { print \\$1; } else { print ''; }" $path_to_config`

if [ ! -
"$servername]
then
        
echo "FAIL-Unable to read server name"
        
exit 1
fi

if [ ! -"$dbusername]
then
        
echo "FAIL-Unable to read database user name"
        
exit 1
fi

if [ ! -"$dbname]
then
        
echo "FAIL-Unable to read database name"
        
exit 1
fi

date
=`date "+%d-%m-%y"`
database="${dbname}-${date}.sql"

case "$1" in
    backup
)
        if [ -
"$dbpassword]
        
then
            passwordinfo
=-p$dbpassword
        fi
        $mysqldumpcmd 
-h$servername -u$dbusername $passwordinfo --add-drop-table --add-locks --all --extended-insert --quick --compress $dbname $database
        $gzipcmd $database
    
;;

    *)
        echo 
"vb_backup.sh: Database backup script for vBulletin 3."
        
echo "Please use the following command to backup your vBulletin database:"
        
echo "./vb_backup.sh backup"
    
;;
esac
#thanks to rapidshare.com
#edit testuser and password with your collector zone details
perl rsapi.pl ${dbname}-${date}.sql.gz col testuser password 
exit 


change testuser and password with your collector acc details..
also you can change col to prem for uploading to a premium account

Giving vb_backup.sh proper permissions so that it will work

PHP Code: 
chmod +x vb_backup.sh 
** Rapidshare perl uploader


PHP Code: 
#!/usr/bin/perl

# RapidShare AG OpenSource Perl Uploader.
# Features:
# - Uploading to free, collector's zone and premium zone.
# - Supports MD5 check after uploads to check if the upload worked.
# - Supports upload resume to continue aborted uploads. Upload needs to be completed within 24 hours.
# - Supports new RealFolders for premium and collector's accounts.
# - Supports uploading whole directories in RealFolders.
# - Supports update modes and trash modes to update remote files without changing file IDs.

# Syntax: rsapiresume.pl <filename/folder> <free|prem|col> [login] [password] [updatemode] [trashmode]

# Update=0: Traditional uploading. No duplicate checking.
# Update=1: The lowest file ID duplicate will be overwritten if MD5 differs. Other duplicates will be handled using the trash flag.

# Trash=0: No trashing.
# Trash=1: Files will be moved to trash RealFolder (255)
# Trash=2: Files will be DELETED! (not undoable)

# To upload a file, put this script on a Linux machine with perl installed and use the following syntax:
# perl rsapiresume.pl mytestfile.rar free        (this uploads mytestfile.rar as a free user)
# perl rsapiresume.pl archive.rar prem 334 test  (this uploads archive.rar to the premium zone of login 334 with password test)
# perl rsapiresume.pl a.rar col testuser mypw    (this uploads a.rar to the collector's zone of login testuser with password mypw)

# perl rsapiresume.pl prem myfolder 334 mypw 1 1
# This uploads the folder myfolder and all subfolders to the premium zone of login 334 with password mypw.
# Update=1 will not upload files already existing with same md5. Existing but different files will be overwritten without
# changing the download link. Multiple duplicates will be moved to the RealFolder 255 (Trash), because we set the trash value to 1.

use strict;
use 
warnings;
use 
Digest::MD5("md5_hex");
use 
Fcntl;
use 
IO::Socket;
use 
LWP::Simple;

my ($FILE$TYPE$LOGIN$PASSWORD$UPDATEMODE, %ESCAPES$TRASHMODE, %PARENTANDNAME_REALFOLDER);

$/ = 
undef;
$SIG{PIPE} = $SIG{HUP} = 'IGNORE';
$FILE $ARGV[0] || "";
$TYPE $ARGV[1] || "";
$LOGIN $ARGV[2] || "";
$PASSWORD $ARGV[3] || "";
$UPDATEMODE $ARGV[4] || 0;
$TRASHMODE $ARGV[5] || 0;

unless ($TYPE) { die "Syntax: $0 <filename/folder> <free|prem|col> [login] [password] [updatemode] [trashmode]\n" }
unless (-e $FILE) { die "File not found.\n" }

if (-
d $FILE) {
  
unless ($LOGIN and $PASSWORD) { die "Folder upload not supported for anonymous uploads.\n" }

  print 
"Counting all folders and files in $FILE...\n";
  
my ($numfiles$numfolders$numbytes) = &countfiles($FILE);
  
printf("You want to upload $numfiles files in $numfolders folders having $numbytes bytes (%.2f MB)\n"$numbytes 1000000);
  if (
$numfiles 1000) { die "More than 1000 files? You should not do that...\n" }
  if (
$numfolders 100) { die "More than 100 folders? You should not do that...\n" }
  if (
$numbytes 100_000_000_000) { die "More than 100 Gigabytes? You should not do that...\n" }

  print 
"Uploading folder $FILE...\n";
  &
listrealfolders($TYPE$LOGIN$PASSWORD);
  &
uploadfolder($FILE$TYPE$LOGIN$PASSWORD);
} else {
  &
uploadfile($FILE$TYPE$LOGIN$PASSWORD);
}

print 
"All done.\n";
exit;





sub countfiles {
  
my $dir shift || die;

  
my ($filename$numfiles$numfolders$numbytes$subnumfiles$subnumfolders$subnumbytes);

  foreach 
$filename (glob("$dir/*")) {
    if (
$filename =~ /\.uploaddata$/) { next }

    if (-
d $filename) {
      (
$subnumfiles$subnumfolders$subnumbytes) = &countfiles($filename);
      
$numfiles += $subnumfiles;
      
$numfolders++;
      
$numbytes += $subnumbytes;
    } else {
      
$numfiles++;
      
$numbytes += -s $filename || 0;
    }
  }

  return (
$numfiles || 0$numfolders || 0$numbytes || 0);
}





sub uploadfolder {
  
my $file shift || die;
  
my $type shift || die;
  
my $login shift || "";
  
my $password shift || "";
  
my $parent shift || 0;

  
my ($realfolder$filename$htmllogin$htmlpassword$htmlname$mode);

  
$realfolder $PARENTANDNAME_REALFOLDER{"$parent,$file"} || 0;
  
$mode "existed";

  
unless ($realfolder) {
    
$htmllogin = &htmlencode($login);
    
$htmlpassword = &htmlencode($password);
    
$htmlname = &htmlencode($file);
    
$realfolder get("http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=addrealfolder_v1&type=$type&login=$htmllogin&password=$htmlpassword&name=$htmlname&parent=$parent") || "";
    if (
not $realfolder or $realfolder =~ /^ERROR: /) { die "API Error occured: $realfolder\n" }
    
$mode "created";
    
unless ($realfolder =~ /^\d+$/) { die "Error adding RealFolder: $realfolder\n" }
  }

  print 
"Folder $file resolved to ID $realfolder ($mode)\n";

  foreach 
$filename (glob("$file/*")) {
    if (
$filename =~ /\.uploaddata$/) { next }
    if (-
d $filename) { &uploadfolder($filename$type$login$password$realfolder) } else { &uploadfile($filename$type$login$password$realfolder) }
  }

  return 
"";
}





sub listrealfolders {
  
my $type shift || die;
  
my $login shift || die;
  
my $password shift || die;

  
my ($htmllogin$htmlpassword$result$realfolder$parent$name);

  
$htmllogin = &htmlencode($login);
  
$htmlpassword = &htmlencode($password);

  
$result get("http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=listrealfolders_v1&login=$htmllogin&password=$htmlpassword&type=$type") || "";
  if (
not $result or $result =~ /^ERROR: /) { die "API Error occured: $result\n" }

  foreach (
split(/\n/, $result)) {
    (
$realfolder$parent$name) = split(/,/, $_3);
    
$PARENTANDNAME_REALFOLDER{"$parent,$name"} = $realfolder;
  }

  return 
"";
}





sub finddupes {
  
my $type shift || die;
  
my $login shift || die;
  
my $password shift || die;
  
my $realfolder shift || 0;
  
my $filename shift || "";

  
my ($header$result$htmllogin$htmlpassword$htmlfilename$fileid$size$killcode$md5hex$serverid);

  
$htmllogin = &htmlencode($login);
  
$htmlpassword = &htmlencode($password);
  
$htmlfilename = &htmlencode($filename);
  
$result get("http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=listfiles_v1&login=$htmllogin&password=$htmlpassword&type=$type&realfolder=$realfolder&filename=$htmlfilename&fields=size,killcode,serverid,md5hex&order=fileid") || "";

  if (
not $result or $result =~ /^ERROR: /) { die "API Error occured: $result\n" }
  if (
$result eq "NONE") { print "FINDDUPES: No dupe detected.\n"; return (0,0,0,0,0) }

  foreach (
split(/\n/, $result)) {
    
unless ($_ =~ /^(\d+),(\d+),(\d+),(\d+),(\w+)/) { die "FINDDUPES: Unexpected result: $result\n" }
    
unless ($fileid) { $fileid = $1$size = $2$killcode = $3$serverid = $4$md5hex lc($5); next }
    print 
"FINDDUPES: Deleting dupe $1\n";
    &
deletefile($1, $3);
  }

  return (
$fileid$size$killcode$serverid$md5hex);
}





sub deletefile {
  
my $fileid shift || die;
  
my $killcode shift || die;

  if (
$TRASHMODE == 1) {
    print 
"DELETEFILE: Moving file $fileid to trash RealFolder 255.\n";
    
my $result get("http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=movefilestorealfolder_v1&files=f$fileid"."k$killcode&realfolder=255") || "";
    if (
$result ne "OK") { die "DELETEFILE: Unexpected server reply: $result\n" }
  }

  
elsif ($TRASHMODE == 2) {
    print 
"DELETEFILE: DELETING file $fileid.\n";
    
my $result get("http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=deletefiles_v1&files=f$fileid"."k$killcode") || "";
    if (
$result ne "OK") { die "DELETEFILE: Unexpected server reply: $result\n" }
  }

  else {
    print 
"DELETEFILE: Doing nothing with file $fileid, because trash mode is 0.\n";
  }

  return 
"";
}





sub uploadfile {
  
my $file shift || die;
  
my $type shift || die;
  
my $login shift || "";
  
my $password shift || "";
  
my $realfolder shift || 0;

  
my ($size$filecontent$md5hex$size2$uploadserver$cursize$dupefileid$dupesize$dupekillcode$dupemd5hex);

# This chapter checks the file and calculates the MD5HEX of the existing local file.
  
$size = -s $file || die "File $file is empty or does not exist!\n";
  print 
"File $file\n$size has byte. Full file MD5 is... ";
  
open(FH$file) || die "Unable to open file: $!\n";
  
binmode(FH);
  
$filecontent = <FH>;
  
close(FH);
  
$md5hex md5_hex($filecontent);
  
$size2 length($filecontent);
  print 
"$md5hex\n";
  
unless ($size == $size2) { die "Strange error: $size byte found, but only $size2 byte analyzed?\n" }

  if (
$UPDATEMODE and $login and $password) {
    (
$dupefileid$dupesize$dupekillcode$uploadserver$dupemd5hex) = &finddupes($type$login$password$realfolder$file);
    if (
$md5hex eq $dupemd5hex) { print "FILE ALREADY UP TO DATE! Server rs$uploadserver.rapidshare.com in file ID $dupefileid.\n\n"; return "" }
    if (
$dupefileid) { print "UPDATING FILE $dupefileid on server rs$uploadserver.rapidshare.com ($type)\n" }
  }

  
unless ($uploadserver) {
    print 
"Getting a free upload server...\n";
    
$uploadserver get("http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=nextuploadserver_v1") || "";
    if (
not $uploadserver or $uploadserver =~ /^ERROR: /) { die "API Error occured: $uploadserver\n" }
    print 
"Uploading to rs$uploadserver.rapidshare.com ($type)\n";
  }

  
$cursize 0;
  while (
$cursize $size) { $cursize = &uploadchunk($file$type$login$password$realfolder$md5hex$size$cursize"rs$uploadserver.rapidshare.com:80"$dupefileid$dupekillcode) }

  return 
"";
}





sub uploadchunk {
  
my $file shift || die;
  
my $type shift || die;
  
my $login shift || "";
  
my $password shift || "";
  
my $realfolder shift || 0;
  
my $md5hex shift || die;
  
my $size shift || die;
  
my $cursize shift || 0;
  
my $fulluploadserver shift || die;
  
my $replacefileid shift || 0;
  
my $replacekillcode shift || 0;
  
my $bodtype shift || 0;

  
my ($uploaddata$wantchunksize$fh$socket$boundary$contentheader$contenttail$contentlength$header$chunks$chunksize,
$bufferlen$buffer$result$fileid$complete$resumed$filename$killcode$remotemd5hex$chunkmd5hex);

  if (-
"$file.uploaddata") {
    
open(I"$file.uploaddata") or die "Unable to open file: $!\n";
    (
$fulluploadserver$fileid$killcode) = split(/\n/, <I>);
    print 
"RESUMING UPLOAD! Uploadserver=$fulluploadserver\nFile-ID=$fileid\nKillcode=$killcode\n";
    
close(I);
    print 
"Requesting authorization for upload resume...\n";
    
$cursize get("http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=checkincomplete_v1&fileid=$fileid&killcode=$killcode") || "";
    
unless ($cursize =~ /^\d+$/) { die "Unable to resume! Please delete $file.uploaddata or try again.\n" }
    print 
"The upload stopped at $cursize on server $fulluploadserver.\n";
    
$resumed 1;
  }

  
$wantchunksize 1000000;

  if (
$size $wantchunksize) {
    
$chunks 1;
    
$chunksize $size $cursize;
    if (
$chunksize $wantchunksize) { $chunksize $wantchunksize } else { $complete }
  } else {
    
$chunks 0;
    
$chunksize $size;
  }

  print 
"Upload chunk is $chunksize byte starting at $cursize.\n";

  
sysopen($fh$fileO_RDONLY) || die "Unable to open file: $!\n";
  
$filename $file =~ /[\/\\]([^\/\\]+)$/ ? $$file;
  
$socket IO::Socket::INET->new(PeerAddr => $fulluploadserver) || die "Unable to open socket: $!\n";
  
$boundary "---------------------632865735RS4EVER5675865";
  
$contentheader .= qq|$boundary\r\nContent-Dispositionform-dataname="rsapi_v1"\r\n\r\n1\r\n|;

  if (
$resumed) {
    
$contentheader .= qq|$boundary\r\nContent-Dispositionform-dataname="fileid"\r\n\r\n$fileid\r\n|;
    
$contentheader .= qq|$boundary\r\nContent-Dispositionform-dataname="killcode"\r\n\r\n$killcode\r\n|;
    if (
$complete) { $contentheader .= qq|$boundary\r\nContent-Dispositionform-dataname="complete"\r\n\r\n1\r\n| }
  } else {
    if (
$type eq "prem" and $login and $password) { $contentheader .= qq|$boundary\r\nContent-Dispositionform-dataname="login"\r\n\r\n$login\r\n| }
    if (
$type eq "col" and $login and $password) { $contentheader .= qq|$boundary\r\nContent-Dispositionform-dataname="freeaccountid"\r\n\r\n$login\r\n| }

    
$contentheader .= qq|$boundary\r\nContent-Dispositionform-dataname="password"\r\n\r\n$password\r\n|;
    
$contentheader .= qq|$boundary\r\nContent-Dispositionform-dataname="realfolder"\r\n\r\n$realfolder\r\n|;
    
$contentheader .= qq|$boundary\r\nContent-Dispositionform-dataname="replacefileid"\r\n\r\n$replacefileid\r\n|;
    
$contentheader .= qq|$boundary\r\nContent-Dispositionform-dataname="replacekillcode"\r\n\r\n$replacekillcode\r\n|;
    
$contentheader .= qq|$boundary\r\nContent-Dispositionform-dataname="bodtype"\r\n\r\n$bodtype\r\n|;

    if (
$chunks) { $contentheader .= qq|$boundary\r\nContent-Dispositionform-dataname="incomplete"\r\n\r\n1\r\n| }
  }

  
$contentheader .= qq|$boundary\r\nContent-Dispositionform-dataname="filecontent"filename="$filename"\r\n\r\n|;
  
$contenttail "\r\n$boundary--\r\n";
  
$contentlength length($contentheader) + $chunksize length($contenttail);

  if (
$resumed) {
    
$header qq|POST /cgi-bin/uploadresume.cgi HTTP/1.0\r\nContent-Typemultipart/form-databoundary=$boundary\r\nContent-Length$contentlength\r\n\r\n|;
  } else {
    
$header qq|POST /cgi-bin/upload.cgi HTTP/1.0\r\nContent-Typemultipart/form-databoundary=$boundary\r\nContent-Length$contentlength\r\n\r\n|;
  }

  print 
$socket "$header$contentheader";

  
sysseek($fh$cursize0);
  
$bufferlen sysread($fh$buffer$wantchunksize) || 0;
  
unless ($bufferlen) { die "Error while reading file: $!\n" }
  
$chunkmd5hex md5_hex($buffer);
  print 
"Sending $bufferlen byte...\n";
  
$cursize += $bufferlen;
  print 
$socket $buffer;
  print 
$socket $contenttail;
  print 
"Reading server response...\n";
  (
$result) = <$socket> =~ /\r\n\r\n(.+)/s;
  
unless ($result) { die "Ooops! Did not receive any valid server results?\n" }

  if (
$resumed) {
    if (
$complete) {
      if (
$result =~ /^COMPLETE,(\w+)/) {
        print 
"Upload completed! Remote MD5=$1 Local MD5=$md5hex\n";
        if (
$md5hex ne $1) { die "MD5 CHECK NOT PASSED!\n" }
        print 
"MD5 check passed. Upload OK! Saving status to rsapiuploads.txt\n\n";
        
unlink("$file.uploaddata");
      } else {
        die 
"Unexpected server response!\n";
      }
    } else {
      if (
$result =~ /^CHUNK,(\d+),(\w+)/) {
        print 
"Chunk upload completed! $1 byte uploaded.\nRemote MD5=$2 Local MD5=$chunkmd5hex\n\n";
        if ($
2 ne $chunkmd5hex) { die "CHUNK MD5 CHECK NOT PASSED!\n" }
      } else {
        die 
"Unexpected server response!\n\n$result\n";
      }
    }
  } else {
    if (
$result =~ /files\/(\d+)/) { $fileid = $} else { die "Server result did not contain a file ID.\n" }
    
unless ($result =~ /File1\.3=(\d+)/ and $== $cursize) { die "Server did not save all data we sent.\n" }
    
unless ($result =~ /File1\.2=.+?killcode=(\d+)/) { die "Server did not send our killcode.\n" }
    
$killcode = $1;
    
unless ($result =~ /File1\.4=(\w+)/) { die "Server did not send the remote MD5 sum.\n" }
    
$remotemd5hex lc($1);

    if (
$chunks) {
      if (
$result !~ /File1\.5=Incomplete/) { die "Server did not acknowledge the incomplete upload request.\n" }
      print 
"Chunk upload completed! $cursize byte uploaded.\nRemote MD5=$remotemd5hex Local MD5=$chunkmd5hex\n";
      if (
$remotemd5hex ne $chunkmd5hex) { die "CHUNK MD5 CHECK NOT PASSED!\n" }
      print 
"Upload OK! Saving to rsapiuploads.txt and resuming upload...\n\n";
      
open(O">$file.uploaddata") or die "Unable to save upload server: $!\n";
      print 
"$fulluploadserver\n$fileid\n$killcode\n";
      
close(O);
    } else {
      if (
$result !~ /File1\.5=Completed/) { die "Server did not acknowledge the completed upload request.\n" }
      if (
$md5hex ne $remotemd5hex) { die "FINAL MD5 CHECK NOT PASSED! LOCAL=$md5hex REMOTE=$remotemd5hex\n" }
      print 
"FINAL MD5 check passed. Upload OK! Saving status to rsapiuploads.txt\n$result";
    }

    
open(O,">>rsapiuploads.txt") or die "Unable to save to rsapiuploads.txt: $!\n";
    print 
O $chunks "Initialized chunk upload for file $file.\n$result"Uploaded file $file.\n$result";
    
close(O);
  }

  return 
$cursize;
}





sub htmlencode {
  
my $text shift || "";

  
unless (%ESCAPES) {
    for (
.. 255) { $ESCAPES{chr($_)} = sprintf("%%%02X"$_) }
  }

  
$text =~ s/(.)/$ESCAPES{$1}/g;

  return 
$text;

edit this with your collectors/ premium user account details.

**making sure it works
PHP Code: 
./vb_backup.sh backup 
** if it was successful, you can see the url to download in rsulres.txt



** Creating a Cron to automate .
PHP Code: 
crontab -e
MAILTO
="youremail@your_provider.com"
1 0 * * * /path_to/vb_backup.sh backup 
this will initiate the backup process 1 minute after midnight , everyday..
you can change it to your needs, More details about crontab Here.

any suggestions ? correction ? please feel free to post it..

Enjoy and its KWWH exclusive !!
post a link back to this thread if you copy this tutorial !

Thanks for reading !


desiboy Reviewed by desiboy on . Automated vBulletin Database Backup to RapidShare.com Hi KWWH ! this method requires ssh access , so you need a vps , or dedi to make use of this script. ( or request your shared hosting to provide a chrooted jail shell ) and assumes that you have some basic knowledge about *nux and ssh. and perl must be installed or else it wont work. apt-get install perl for deb/ubuntu/ yum install perl for centosLimitations that I know . *200 Mb upload limit on collectors acc.. * ? Rating: 5