#!/usr/bin/perl # license: GPL V2 # (c)2014 rudi, forum.chdk-treff.de use URI::Escape; my $unzip = "/usr/bin/unzip"; my $srcfolder = "/tmp/"; my $mainhtml = "/chdk.html"; my $form; my $qsChdkZip; #querystring filename my $qsChdkZipSize; #querystring filesize my $qsChdkFileCount = 0; #querystring file count my $qsTime = 0; #time for set server time my $chdkZip; #full path filename my $chdkFileCount = 0; #checkZipContent file count my $chdkUPsize = 0; #unpacked size of chdk files my $fullChdk = 0; #zip type my $updTime = 0; #time need update my $langDE = ($ENV{'HTTP_ACCEPT_LANGUAGE'} =~ /^de/)?1:0; #user language german from HTTP_ACCEPT_LANGUAGE my $htmlTitle = (!$langDE)?"install CHDK":"CHDK einrichten"; my $htmlCheckErr; sub isSvrTime { my (undef, $min, $hour, $day, $mon, $year) = localtime(); $year = $year+1900; $mon = $mon+1; $mon = ($mon > 9)?$mon:"0".$mon; $day = ($day > 9)?$day:"0".$day; $hour = ($hour > 9)?$hour:"0".$hour; $min = ($min > 9)?$min:"0".$min; my $svrTime = "$year$mon$day$hour$min"; $updTime = ($qsTime > $svrTime)?1:0; } sub setSvrTime { if ($updTime) { `date -s $qsTime`; } } sub checkZipContent { my $fn; my $us = 0; my @res = `unzip -l $chdkZip`; my $res = 0; my $fDiskboot = 0; my $dModules = 0; foreach $line (@res) { if ($line =~ /(\d+) \d\d-\d\d-\d\d \d\d:\d\d ([\w+\/]*[\w\-]+\.\w\w\w)/) { $fn = $2; $us +=$1; if ($fn =~ /^CHDK\//) { #dir exist if ($fn =~ /^CHDK\/MODULES\//) { $dModules += 1; } else { $fullChdk = 1; } } else { #not chdk dir => root dir if ($fn =~ /\//) { $res = 0; last; } # '/' in line if ($fn =~ /^DISKBOOT.BIN$/) { $fDiskboot += 1; } } $res += 1; } } if ($res == 0 || $fDiskboot != 1 || $dModules == 0) { return 1; } $chdkFileCount = $res; $chdkUPsize = $us; return 0; } sub deleteFile { my $err = system("rm $chdkZip"); if ($err == 0) { my @text = ("uploaded file deleted", "hochgeladene Datei gelöscht"); print "
  • $text[$langDE]
  • \n"; } else { my @text = ("Can't delete uploaded file!", "Hochgeledene Datei konnte nicht gelöscht werden!"); print "
  • $text[$langDE]
  • \n"; } return ($err)?1:0; } sub refreshSD { my $duration = shift @_; my @text = ( ["synchronize files, need approximate %d seconds time ...", "synchronisiere Dateien, dauert etwa %d Sekunden ..."], ["... completed", "... abgeschlossen"], ["synchronize failed!", "Synchronisation fehlgeschlagen!"] ); if ($duration > 1) { printf "
  • $text[0][$langDE]
  • \n", $duration+1; } #add time for sync my $err = system("sync") || system("sleep $duration") || system("sync") || system("mount -o remount /mnt/sd"); if ($duration > 1) { print "
  • $text[1][$langDE]
  • \n"; } if ($err) { print "
  • $text[2][$langDE]
  • \n"; } return ($err)?1:0; } sub checkChdkZip { if ($abort != 0) { $htmlCheckErr = (!$langDE)?"Installation canceled!":"Einrichtung abgebrochen!"; return 1; } if (length($chdkZip) == 0) { $htmlCheckErr = (!$langDE)?"Missing file name!":"Dateiname fehlt!"; return 1; } if ($chdkZip !~ /.zip$/) { $htmlCheckErr = (!$langDE)?"ZIP file required!":"ZIP-Datei erwartet!"; return 1; } if (checkZipContent != 0) { $htmlCheckErr = (!$langDE)?"CHDK ZIP file required!":"CHDK-ZIP-Datei erwartet!"; return 1; } return 0; } sub processInstall { my @text = ( ["Extract and copy CHDK files, please wait ...", "CHDK-Dateien werden entpackt und kopiert, bitte warten ..."], ["... completed", "... abgeschlossen"], ["Error on copy files!
    Check filesystem with fsck/chkdsk and try installation again.", "Fehler beim Kopieren!
    Überprüfe das Dateisystem mit fsck/chkdsk und führe die Einrichtung erneut aus."], ["Copied %d from %d files", "%d von %d Dateien kopiert"], ["Press Button 'OK' and restart the camera!", "Drücke die 'OK'-Schaltfläche und starte die Kamera neu!"] ); $| = 1; #flush for print print "
  • $text[0][$langDE]
  • \n"; my $err = refreshSD(1); if (!$err) { my @res = `unzip -o $chdkZip -d /mnt/sd/`; my $res = 0; foreach $line (@res) { if ($line =~ /inflating:/) { $res += 1; } } if ($qsChdkFileCount == $res) { print "
  • $text[1][$langDE]
  • \n"; } else { print "
  • $text[2][$langDE]
  • \n"; } printf "
  • $text[3][$langDE]
  • \n", $res, $qsChdkFileCount; #wait duration for sync #highest value from data volume, ref=250'000 byte/sec my $wd = $chdkUPsize/250000; #or file count, ref=25 files/sec if ($res/25 > $wd) { $wd = $res/25; } $err = refreshSD(int($wd)+1); #round up } deleteFile; if (!$err) { print "
  • $text[4][$langDE]
  • \n"; } return ($err)?1:0; } sub qsSplit { my @nameValuePairs = split (/&/, $queryString); foreach $nameValue (@nameValuePairs) { my ($name, $value) = split (/=/, $nameValue); $value =~ tr/+/ /; $value =~ s/%([\dA-Fa-f][\dA-Fa-f])/ pack ("C",hex ($1))/eg; $form{$name} = $value; } } sub writeChdkFileinfo { my @text = ( ["Update", "Aktualisierung"], ["Complete", "Komplett"], ["CHDK (absent value)", "CHDK (Angabe fehlt)"], ["Uploaded file", "hochgeladene Datei"], ["Name", "Name"], ["Size", "Größe"], ["File content", "Inhalt der Datei"], ["Package", "Paket"], ["Files", "Dateien"], ["Informations from filename", "Informationen aus dem Dateinamen"], ["Type", "Typ"], ["Camera", "Kamera"], ["Version", "Version"], ["Revision", "Revision"] ); my $package = ($fullChdk == 0)?$text[0][$langDE]:$text[1][$langDE]; my $typ = (!$langDE)?"unknown":"unbekannt"; my $cam = $typ; my $ver = $typ; my $rev = $typ; my $err = 1; if ($qsChdkZip =~ /^(CHDK\-DE|CHDK_DE|CHDK)?[-_]?([a-z]+\d+[a-z]*_?\w*\-\d\d\d[a-z])\-(\d+\.\d+\.\d+)\-[-_A-Za-z]*(\d+).*\.zip/) { if ($1) { $typ = $1 } if ($2) { $cam = $2 } if ($3) { $ver = $3 } if ($4) { $rev = $4 } if (!$1 && $2 && $3 && $4) { $typ = $text[2][$langDE] } $err = 0; } print "
    \n"; if($qsChdkZipSize > 0) { print "\n"; print "\n"; print "\n"; print "\n"; print "
    $text[3][$langDE]
    $text[4][$langDE]:$qsChdkZip
    $text[5][$langDE]:$qsChdkZipSize Byte
    \n"; } print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "
    $text[6][$langDE]
    $text[7][$langDE]:$package
    $text[8][$langDE]:$chdkFileCount
    $text[5][$langDE]:$chdkUPsize Byte
    \n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "
    $text[9][$langDE]
    $text[10][$langDE]:$typ
    $text[11][$langDE]:$cam
    $text[12][$langDE]:$ver
    $text[13][$langDE]:$rev
    \n"; print "
    \n"; return $err; } #POST required if($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $queryString, $ENV{'CONTENT_LENGTH'}); qsSplit; } if (length($form{fn}) > 0) { $qsChdkZip = $form{fn}; $chdkZip = $srcfolder.$qsChdkZip; } if (length($form{fc}) > 0) { $qsChdkFileCount = $form{fc}; } if (length($form{fs}) > 0) { $qsChdkZipSize = $form{fs}; } if (length($form{time}) > 0) { $qsTime = $form{time}; } if (length($form{utime}) > 0) { $updTime = $form{utime}; } if (length($form{abort}) > 0) { $abort = $form{abort}; } if (checkChdkZip == 0) { $htmlTitle = ($qsChdkFileCount == $chdkFileCount)?"$htmlTitle : 2":"$htmlTitle : 1"; } # HTML HEADER BEGIN print "Content-type: text/html\n\n"; print "\n"; print "\n"; print "\n"; print "$htmlTitle\n"; print "\n"; print "\n"; print "\n"; print "

    $htmlTitle

    \n"; print "
    \n"; print "
    \n"; print "
    \n"; #HTML HEADER END if (checkChdkZip == 0) { if ($qsChdkFileCount == $chdkFileCount) { #step 2: install my @text = ( ["Step 2 - Copy files", "Schritt 2 - CHDK-Dateien kopieren"], ["Current server time", "Aktuelle Serverzeit"], ["Unsafe filename!", "Unsicherer Dateiname!"], ["Step 2 completed", "Schritt 2 abgeschlossen"], ["Error on step 2", "Fehler im Schritt 2"] ); print "$text[0][$langDE]\n"; my $pi = writeChdkFileinfo; print "
    \n"; print "
      \n"; if ($updTime == 1) { my $lt = localtime; print "
    • $text[1][$langDE]: $lt
    • \n"; } if ($pi) { print "
    • $text[2][$langDE]
    • \n"; } $pi = processInstall; print "
    \n"; print "
    \n"; print "
    \n"; print "$text[3+$pi][$langDE]\n"; print "\n"; print "
    \n"; } else { #step 1: check my @text = ( ["Step 1 completed", "Schritt 1 abgeschlossen"], ["Unsafe filename!", "Unsicherer Dateiname!"], ["Step 2 - Copy files", "Schritt 2 - CHDK-Dateien kopieren"], ["Cancel", "Abbrechen"], ["Next", "Weiter"] ); $| = 1; #flush for print isSvrTime; print "$text[0][$langDE]"; my $fi = writeChdkFileinfo; print "
    \n"; print "
    \n"; print "\n"; print "\n"; print "\n"; print "\n"; if ($fi) { print "
    $text[1][$langDE]
    " } print "$text[2][$langDE]\n"; print "\n"; print "\n"; print "
    \n"; } } else { my @text = ( ["Error", "Fehler"], ["", ""] ); #check error print "$text[0][$langDE]\n"; print "

    $htmlCheckErr

    \n"; print "
      \n"; deleteFile; print "
    \n"; print "
    \n"; print "
    \n"; print "$text[1][$langDE]\n"; print "\n"; print "
    \n"; } # HTML FOOTER BEGIN print "
    \n"; print "
    \n"; print "
    \n"; print "
    (C)2014 rudi, forum.chdk-treff.de
    \n"; print "
    chdk_install.cgi: v1.6
    \n"; print "\n"; print "\n"; # HTML FOOTER END #! push to end of script # webserver output fails with set date on execute cgi # at first time after boot setSvrTime;