Automated vBulletin Database Backup to RapidShare.com

Status
Not open for further replies.

desiboy

Active Member
1,544
2008
7
0
Hi Wj !
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:
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:
#!/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 [ ! -e "$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 [ ! -n "$servername" ]
then
        echo "FAIL-Unable to read server name"
        exit 1
fi

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

if [ ! -n "$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 [ -n "$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 0

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:
chmod +x vb_backup.sh
** Rapidshare perl uploader


PHP:
#!/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 (-e "$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 = 1 }
  } else {
    $chunks = 0;
    $chunksize = $size;
  }

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

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

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

    $contentheader .= qq|$boundary\r\nContent-Disposition: form-data; name="password"\r\n\r\n$password\r\n|;
    $contentheader .= qq|$boundary\r\nContent-Disposition: form-data; name="realfolder"\r\n\r\n$realfolder\r\n|;
    $contentheader .= qq|$boundary\r\nContent-Disposition: form-data; name="replacefileid"\r\n\r\n$replacefileid\r\n|;
    $contentheader .= qq|$boundary\r\nContent-Disposition: form-data; name="replacekillcode"\r\n\r\n$replacekillcode\r\n|;
    $contentheader .= qq|$boundary\r\nContent-Disposition: form-data; name="bodtype"\r\n\r\n$bodtype\r\n|;

    if ($chunks) { $contentheader .= qq|$boundary\r\nContent-Disposition: form-data; name="incomplete"\r\n\r\n1\r\n| }
  }

  $contentheader .= qq|$boundary\r\nContent-Disposition: form-data; name="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-Type: multipart/form-data; boundary=$boundary\r\nContent-Length: $contentlength\r\n\r\n|;
  } else {
    $header = qq|POST /cgi-bin/upload.cgi HTTP/1.0\r\nContent-Type: multipart/form-data; boundary=$boundary\r\nContent-Length: $contentlength\r\n\r\n|;
  }

  print $socket "$header$contentheader";

  sysseek($fh, $cursize, 0);
  $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 = $1 } else { die "Server result did not contain a file ID.\n" }
    unless ($result =~ /File1\.3=(\d+)/ and $1 == $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 O "$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 (0 .. 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:
./vb_backup.sh backup
** if it was successful, you can see the url to download in rsulres.txt



** Creating a Cron to automate .
PHP:
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 wj exclusive !!
post a link back to this thread if you copy this tutorial !

Thanks for reading !


 
30 comments
rapidshare search scripts scrapes pages that have the rapidshare link on!

as long as you dont post your link on forums or any public place, you are safe from all rs spiders!
 
I'm kinda stuck with one part of it,

What do we do with Rapidshare perl uploader part of it. Do we create a file for it if so where?
 
Thanks,

I'm also getting this when I try to test it:
Unmatched [ in regex; marked by <-- HERE in m/[ <-- HERE / at rsapi.pl line 38.
 
Status
Not open for further replies.
Back
Top