#!/usr/bin/perl use Socket; use MIME::Base64 qw(encode_base64 decode_base64); use Digest::SHA qw(sha1); use Time::Piece; # Ruslan Mayorov $command = $ARGV[0]; $host = $ARGV[1]; $stream = $ARGV[2]; $lp = $ARGV[3]; $com1 = "info"; $com2 = "profiles"; $com3 = "play"; $hr = "-----------------------------------------------------\n"; if ($command eq $com1) { ($login, $pwd) = split(":", $stream) } if ($command eq $com2) { ($login, $pwd) = split(":", $stream) } if ($command eq $com3) { ($login, $pwd) = split(":", $lp) } if ($pwd eq "" and $login eq "") { $pwd = "admin" } if ($login eq "") { $login = "admin" } $passwd = $pwd; $pref = ""; if ($command ne $com1 and $command ne $com2 and $command ne $com3) { print "ONVIF Camera Info Ver. 1.0\nUsage:\nonvif $com1 host[:port] [user:password]\nonvif $com3 host[:port] [profile] [user:password]\nonvif $com2 host[:port] [user:password]\nDefault user:password = admin:admin\n"; exit(0); } $date = time(); $tz = 3; $date = $date - ($tz * 3600); $date=Time::Piece -> new($date); $date = $date -> strftime ( "%Y-%m-%dT%H:%M:%SZ" ),"\n"; @set = ('0' .. '9', 'A' .. 'Z', 'a' .. 'z'); $non = join '' => map $set[rand @set], 1 .. 32; substr($digest = encode_base64(sha1(sprintf("%s%s%s", decode_base64($non), $date, $pwd))), -1) = ""; ($host, $port) = split(":", $host); if ($port eq "") {$port = "80"} $iaddr = inet_aton($host); $paddr = sockaddr_in($port, $iaddr); $upwd = "$digest"; @onvr[0] = "http://www.onvif.org/ver10/device/wsdl/GetSystemDateAndTime"; @onvr[1] = ""; @onvr[2] = "onvif/device_service"; onvif(); if ($onv eq "") { print "Error: Not ONVIF port\n"; exit(0); } if ($subcode eq "wsse:InvalidSecurity") { print "Error: $reason\n"; exit(0); } ($n, $udt2) = split("", $onv, 2); ($tz, $udt2) = split("", $udt2, 2); ($n, $udt2) = split("", $onv, 2); ($udt, $udt2) = split("", $udt2, 2); ($n, $ldt2) = split("", $onv, 2); ($ldt, $ldt2) = split("", $ldt2, 2); ($n, $udt1) = split("", $udt, 2); ($uh, $udt1) = split("", $udt1, 2); ($n, $udt1) = split("", $udt, 2); ($um, $udt1) = split("", $udt1, 2); ($n, $udt1) = split("", $udt, 2); ($us, $udt1) = split("", $udt1, 2); ($n, $udt1) = split("", $udt, 2); ($uy, $udt1) = split("", $udt1, 2); ($n, $udt1) = split("", $udt, 2); ($umo, $udt1) = split("", $udt1, 2); ($n, $udt1) = split("", $udt, 2); ($ud, $udt1) = split("", $udt1, 2); ($n, $ldt1) = split("", $ldt, 2); ($lh, $ldt1) = split("", $ldt1, 2); ($n, $ldt1) = split("", $ldt, 2); ($lm, $ldt1) = split("", $ldt1, 2); ($n, $ldt1) = split("", $ldt, 2); ($ls, $ldt1) = split("", $ldt1, 2); ($n, $ldt1) = split("", $ldt, 2); ($ly, $ldt1) = split("", $ldt1, 2); ($n, $ldt1) = split("", $ldt, 2); ($lmo, $ldt1) = split("", $ldt1, 2); ($n, $ldt1) = split("", $ldt, 2); ($ld, $ldt1) = split("", $ldt1, 2); $udtime = sprintf("%02i:%02i:%02i %02i.%02i.%04i", $uh, $um, $us, $ud, $umo, $uy); $ldtime = sprintf("%02i:%02i:%02i %02i.%02i.%04i", $lh, $lm, $ls, $ld, $lmo, $ly); @onvr[0] = "http://www.onvif.org/ver10/device/wsdl/GetDeviceInformation"; @onvr[1] = ""; @onvr[2] = "onvif/device_service"; onvif(); ($n, $inf) = split("", $onv, 2); ($man, $inf) = split("", $inf, 2); ($n, $inf) = split("", $onv, 2); ($mod, $inf) = split("", $inf, 2); ($n, $inf) = split("", $onv, 2); ($fw, $inf) = split("", $inf, 2); ($n, $inf) = split("", $onv, 2); ($sn, $inf) = split("", $inf, 2); ($n, $inf) = split("", $onv, 2); ($hw, $inf) = split("", $inf, 2); if ($subcode eq "ter:NotAuthorized") { print "Error: $reason\n"; exit(0); } print "Camera Info:\n"; print "$hr"; if ($man ne "" ) { print "Manufacer : $man\n"; } if ($mod ne "" ) { print "Model : $mod\n"; } if ($fw ne "" ) { print "Firmware Ver. : $fw\n"; } if ($sn ne "" ) { print "Serial Number : $sn\n"; } if ($hw ne "" ) { print "Hardware : $hw\n"; } if ($udtime ne "00:00:00 00.00.0000" ) { print "UTC Time/Date : $udtime\n"; } if ($ldtime ne "00:00:00 00.00.0000" ) { print "Local Time/Date : $ldtime\n"; } if ($tz ne "" ) { print "Timezone : $tz\n"; } $onv = ""; @onvr[0] = "http://www.onvif.org/ver10/device/wsdl/GetCapabilities"; @onvr[1] = ""; @onvr[2] = "onvif/device_service"; onvif(); ($n, $device) = split ("", $onv, 2); ($device) = split ("", $device); ($n, $daddr) = split ("", $device, 2); ($daddr) = split ("", $daddr); ($n, $media) = split ("", $onv, 2); ($media) = split ("", $media); ($n, $maddr) = split ("", $media, 2); ($maddr) = split ("", $maddr); ($n, $img) = split ("", $onv, 2); ($img) = split ("", $img); ($n, $iaddr) = split ("", $img, 2); ($iaddr) = split ("", $iaddr); ($n, $io) = split ("", $onv, 2); ($io) = split ("", $io); ($n, $ioaddr) = split ("", $io, 2); ($ioaddr) = split ("", $ioaddr); ($n, $n, $n, $daddr) = split("/", $daddr, 4); ($n, $n, $n, $maddr) = split("/", $maddr, 4); ($n, $n, $n, $iaddr) = split("/", $iaddr, 4); ($n, $n, $n, $ioaddr) = split("/", $ioaddr, 4); $am = "Digest"; @onvr[0] = "http://www.onvif.org/ver10/media/wsdl/GetProfiles"; @onvr[1] = ""; @onvr[2] = "$maddr"; onvif(); if ($subcode eq "ter:NotAuthorized") { $upwd = "$pwd"; @onvr[0] = "http://www.onvif.org/ver10/media/wsdl/GetProfiles"; @onvr[1] = ""; @onvr[2] = "$maddr"; onvif(); if ($subcode eq "ter:NotAuthorized") { print "Error: $reason\n"; exit(0); } $am = "UserPassword"; } $c1 = "0"; $onv1 = $onv; while ($onv1 ne "") { ($n, $onv1) = split ("", $onv1, 2); ($n, $tok) = split ("token=\"", $ve, 2); ($tok) = split ("\"", $tok); ($n, $enc) = split ("", $ve, 2); ($enc) = split ("", $enc); ($n, $wd) = split ("", $ve, 2); ($wd) = split ("", $wd); ($n, $he) = split ("", $ve, 2); ($he) = split ("", $he); ($n, $brate) = split ("", $ve, 2); ($brate) = split ("", $brate); ($n, $frate) = split ("", $ve, 2); ($frate) = split ("", $frate); ($n, $frame) = split ("", $ve, 2); ($frame) = split ("", $frame); ($n, $frame1) = split ("", $ve, 2); ($frame1) = split ("", $frame1); if ($frame < "3" and $frame1 > "1") { $frame = $frame1; } $enc = sprintf(" %-29s: Resolution: %sx%s; Bitrate: %s kbit/s; Framerate: %s fps; I-Frame: %s", $enc, $wd, $he, $brate, $frate, $frame); @pp2[$c1] = $enc; $c1++; } print "Auth Method : $am\n"; print "$hr"; $c1 = "0"; while ($onv ne "") { ($n, $onv) = split ("", $onv, 2); ($n, $tok) = split ("token=\"", $trt, 2); ($tok) = split ("\"", $tok); ($n, $tname) = split ("", $trt, 2); ($tname) = split ("", $tname); @pp[$c1] = $tok; @pp1[$c1] = $tname; $c1++; } if ($command eq $com3 and $stream eq "") { $stream = @pp1[0]; } $c = "0"; if ($command eq $com1) { while ($c ne $c1-1) { @onvr[0] = "http://www.onvif.org/ver10/media/wsdl/GetSnapshotUri"; @onvr[1] = "@pp[$c]"; @onvr[2] = "$iaddr"; onvif(); ($n, $onv) = split("", $onv, 2); ($snap, $onv) = split("", $onv, 2); $snap =~ s/&/&/g; if ($command eq $com1 and $snap ne "") { $ss = sprintf("Snapshot: %-20s: %s", @pp1[$c], $snap); print "$ss\n"; } $c++; } } $c = "0"; while ($c ne $c1-1) { @onvr[0] = "http://www.onvif.org/ver10/device/wsdl/GetStreamUri"; @onvr[1] = "RTP-UnicastRTSP@pp[$c]"; @onvr[2] = "$maddr"; onvif(); ($n, $p) = split ("", $onv); ($p, $n) = split ("", $p); $p =~ s/&/&/g; $p =~ s/\?ptype\=tcp/\?/; if ($command eq $com2) { print "@pp1[$c]\n"; } if ($p ne "" and $command eq $com1) { $pp1 = sprintf("%-30s", @pp1[$c]); print "$pp1: $p\n@pp2[$c]\n"; } if (@pp1[$c] eq $stream and $command eq $com3) { if ($p eq "") { print "No stream found for $stream\n"; exit(0); } ($n, $p) = split("//", $p); $p = sprintf("rtsp://%s:%s@%s", $login, $passwd, $p); print "Playing stream : $stream\n@pp2[$c]\n"; system ("ffplay -hide_banner -loglevel error \"$p\""); exit(0); } $c++; } if ($command eq $com3) { print "No stream found for $stream\n"; exit(0); } sub onvif { $reason = ""; $str0 = " $login $upwd $non $date @onvr[1] "; my $l = length($str0); $str1 = "POST /@onvr[2] HTTP/1.1\r\nHost: $host:$port\r\nUser-Agent: IpcamInfo/Utils\r\nAccept: */*\r\nConnection: Close\r\nContent-Type: application/soap+xml; charset=utf-8; action=\"@onvr[0]\"\r\nContent-Length: $l\r\n\r\n"; my @data; socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp')); connect(SOCK, $paddr) or die "Error: $!\n"; send (SOCK, $str1, 0); send (SOCK, $str0, 0); @data=; close (SOCK); $onv = ""; $c0 = "0"; ($n, $httpcode) = split(" ", @data[0]); # if ($httpcode eq "404") {print "ONVIF Error 404: http://$host:$port/@onvr[2]\n";} while (@data[$c0] ne "") { $onv = sprintf ("%s%s", $onv, @data[$c0]); $c0++; } ($n, $onv) = split(/<\S+:Envelope/, $onv, 2); #($onv) = split(/<\/\S+:Envelope>/, $onv, 1); ($n, $re) = split("<*:Reason>", $onv, 2); ($re) = split(/<\/\S+:Reason/, $re); ($n, $reason) = split (">", $re, 2); ($reason) = split("<", $reason); ($n, $re) = split("<*:Subcode>", $onv, 2); ($re) = split(/<\/\S+:Subcode/, $re); ($n, $subcode) = split ("<*:Value>", $re, 2); ($subcode) = split(/<\/\S+:Value/, $subcode); if ($subcode eq "wsse:InvalidSecurity") {$subcode = "ter:NotAuthorized"; } }