Darwin-Streaming-Server/WebAdmin/WebAdminHtml/parse_xml.cgi
Darren VanBuren 849723c9cf Add even more of the source
This should be about everything needed to build so far?
2017-03-07 17:14:16 -08:00

1808 lines
58 KiB
Perl

#!/usr/bin/perl
#
# @APPLE_LICENSE_HEADER_START@
#
#
# Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
#
# This file contains Original Code and/or Modifications of Original Code
# as defined in and that are subject to the Apple Public Source License
# Version 2.0 (the 'License'). You may not use this file except in
# compliance with the License. Please obtain a copy of the License at
# http://www.opensource.apple.com/apsl/ and read it before using this
# file.
#
# The Original Code and all software distributed under the License are
# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
# Please see the License for the specific language governing rights and
# limitations under the License.
#
# @APPLE_LICENSE_HEADER_END@
#
require('tag_vals.pl');
require('tag_types.pl');
require('tag_formats.pl');
require('adminprotocol-lib.pl');
require('cgi-lib.pl');
require('playlist-lib.pl');
require('relayxmlparser.pl');
require('password-utils.pl');
# Get the server name, QTSS IP address, and Port from ENV hash
$servername = $ENV{"SERVER_SOFTWARE"};
$qtssip = $ENV{"QTSSADMINSERVER_QTSSIP"};
$qtssport = $ENV{"QTSSADMINSERVER_QTSSPORT"};
$remoteip = $ENV{"REMOTE_HOST"};
$accessdir = $ENV{"LANGDIR"};
$nonAuthenticatedActions = ("|login|logout|AssistSetPassword|");
$displayedLoginMessage = 0;
$auth = '';
$authheader = '';
$messageHash = &adminprotolib::GetMessageHash();
$cookie = '';
$password = '';
$iteration = '';
$cookieExpireSecs = $ENV{"COOKIE_EXPIRE_SECONDS"};
# this array will get filled by the foundTag function
my %endTags = ();
# tag depth variable
my $tag_depth = 0;
sub encodeBase64 {
my $res = '';
pos($_[0]) = 0; # ensure start at the beginning
while ($_[0] =~ /(.{1,45})/gs) {
$res .= substr(pack('u', $1), 1);
chop($res);
}
$res =~ tr|` -_|AA-Za-z0-9+/|; # `# help emacs
# fix padding at the end
my $padding = (3 - length($_[0]) % 3) % 3;
$res =~ s/.{$padding}$/'=' x $padding/e if $padding;
return $res;
}
# b64decode(string)
# Converts a string from base64 format to normal
sub b64decode {
local($str) = $_[0];
local($res);
$str =~ tr|A-Za-z0-9+=/||cd;
$str =~ s/=+$//;
$str =~ tr|A-Za-z0-9+/| -_|;
while ($str =~ /(.{1,60})/gs) {
my $len = chr(32 + length($1)*3/4);
$res .= unpack("u", $len . $1 );
}
return $res;
}
sub repeaterExists {
my $testRepeater = $_[0];
my $i = 0;
my $foundItem = '';
my $currentItem = '';
foreach $theItem (@returnedKeys) {
if ($theItem eq $testRepeater) {
$foundItem = 1;
last;
}
}
return $foundItem;
}
sub addIterationAttribute {
my $tagAttributes = $_[0];
my $endTagSlash = $_[1];
my $singleTagSlash = $_[2];
my $iterationNumber = $_[3];
if ($endTagSlash eq '/') {
return '</qtssobject>';
}
else {
return '<qtssobject' . $tagAttributes . " iteration=$iterationNumber" . $singleTagSlash . '>';
}
}
# this routine, erm, expands repeater tags. Adds an iteration attribute to all contained qtssobject tags.
sub expandRepeater {
my $tagAttributes = $_[0];
my $tagContents = $_[1];
my $name = '';
my $arraySize = 0;
my $currentIteration = 0;
my $returnedText = '';
$_ = $tagAttributes;
if (/ name="[^"]*"| name=[^ (\/>)]*/si) {
$name = $&;
$name =~ s/ *name="*//;
$name =~ s/"//;
}
$arraySize = getRepeaterArray($name);
# return '@' . $returnedKeys[0];
# $arraySize = scalar(eval('@' . $returnedKeys[0]));
for ($currentIteration = 0; $currentIteration < $arraySize; $currentIteration++) {
$_ = $tagContents;
s{ < ( /*? ) qtssobject ( .*? ) (/*?) >}
{ addIterationAttribute($2, $1, $3, $currentIteration) }isgxe;
$returnedText .= $_;
}
return $returnedText;
}
# this routine takes the contents of a qtssobject tag and deals with it accordingly
sub foundTag {
my $data = '';
my $tagAttributes = $_[0];
my $endTagSlash = $_[1];
my $singleTagSlash = $_[2];
my $name = '';
my $type = '';
my $value = '';
my $format = '';
my $userParam = '';
my $final_value = '';
$iteration = '';
$_ = $tagAttributes;
if ($endTagSlash eq "/") {
$final_value = $endTags{$tag_depth};
$tag_depth--;
return $final_value;
}
if (/ name="[^"]*"| name=[^ (\/>)]*/si) {
$name = $&;
$name =~ s/ *name="*//;
$name =~ s/"//;
}
if (/ type="[^"]*"| type=[^ (\/>)]*/si) {
$type = $&;
$type =~ s/ *type="*//;
$type =~ s/"//;
}
else {
$type = $defaultTypes{$name};
}
if (/ iteration="[^"]*"| iteration=[^ (\/>)]*/si) {
$iteration = $&;
$iteration =~ s/ *iteration="*//;
$iteration =~ s/"//;
}
# get the end tag, if necessary
if ($singleTagSlash eq '') {
$tag_depth++;
$endTags{$tag_depth} = $endTagTypes{$type};
}
if (/ format="[^"]*"| format=[^ (\/>)]*/si) {
$format = $&;
$format =~ s/ *format="*//;
$format =~ s/"//;
}
else {
$format = $defaultFormats{$name};
}
if (/ param="[^"]*"| param=[^ (\/>)]*/si) {
$userParam = $&;
$userParam =~ s/ *param="*//;
$userParam =~ s/"//;
}
else {
$userParam = '';
}
$value = $tagVals{$name};
#check to see if there's an iteration
#if so, check to see if a repeater with this name exists
if ($iteration ne '') {
# return $name;
if (repeaterExists($name)) {
$value = eval('$' . $name . "[$iteration]");
$name .= $iteration;
}
}
$_ = $value;
#if it starts with / then we'll assume it's a path to a server var
if (($_ ne '') && (/^\//) && ($iteration eq '')) {
my $messHash = adminprotolib::GetMessageHash();
$status = adminprotolib::EchoData($data, $messHash, $authheader, $qtssip, $qtssport, $value, $value);
if (($status == 500) and ($data =~ /Connection refused/) and ($displayedLoginMessage == 0)) {
$displayedLoginMessage = 1;
$wasAuth = 0;
my $loginText = '';
open(LOGINFILE, "start_server.html") or die "Can't open server start file!";
while ($line = <LOGINFILE>) {
$loginText .= $line;
}
close(LOGINFILE);
$loginText = parseTags($loginText);
&cgilib::PrintOKTextHeader($servername);
print $loginText;
return 0;
}
if ($status == 401) {
my $isAuthenticated = 0;
if ($wasAuth == (-1)) {
$value = '';
return '';
}
# only try default authentication if setup assistant on mac os x
if (($^O eq "darwin") and (-e "index.html") and ($ENV{"REMOTE_HOST"} eq '127.0.0.1') and (MacQTGroupsContainsAdminGroup() == 0)) {
if (wasAuth >= 0) { # first pass
open(LOGINFILE, "setup_assistant.html");
my $loginText = '';
while ($line = <LOGINFILE>) {
$loginText .= $line;
}
close(LOGINFILE);
$wasAuth = (-1);
$loginText = parseTags($loginText);
&cgilib::PrintOKTextHeader($servername);
print $loginText;
return 0;
}
}
if (($displayedLoginMessage == 0) && ($isAuthenticated == 0)) {
$displayedLoginMessage = 1;
# now using cookies to store password; return login page
my $loginText = '';
open(LOGINFILE, "login.html") or die "Can't open login file!";
while ($line = <LOGINFILE>) {
$loginText .= $line;
}
close(LOGINFILE);
$loginText = parseTags($loginText);
&cgilib::PrintOKTextHeader($servername);
print $loginText;
$wasAuth = 0;
return 0;
}
}
$value = $data;
}
# if it starts with = then we'll evaluate it, replacing stuff first
# small possibility for nasty recursion exists here
# be sure not to include another evaluating tag inside this one
$_ = $value;
if (/^=/) {
$value =~ s/^=//;
$value = parseTags($value);
$value = eval($value);
}
# format value
$value = runFormatter($value, $format, $userParam, $name);
$final_value = $tagTypes{$type};
if ($final_value eq '') {
$final_value = $tagTypes{'plaintext'};
}
$final_value =~ s/<value\/>/$value/gi;
$final_value =~ s/<name\/>/$name/gi;
$final_value =~ s/<param\/>/$userParam/gi;
$final_value =~ s/<filename\/>/$filename/gi;
$_ = $final_value;
return $final_value;
}
#this routine replaces localized strings from the messages file
sub foundString {
my $tagAttributes = $_[0];
my $endTagSlash = $_[1];
my $singleTagSlash = $_[2];
my $name = '';
$_ = $tagAttributes;
if (/ name="[^"]*"| name=[^ (\/>)]*/si) {
$name = $&;
$name =~ s/ *name="*//;
$name =~ s/"//;
}
my $messHash = adminprotolib::GetMessageHash();
my %messages = %$messHash;
my $QTName = 'QT' . $name;
if (($^O eq "darwin") and ($messages{$QTName} ne '')) {
return $messages{$QTName};
}
return "$messages{$name}";
}
#this routine calls foundTag for each tag found.
sub parseTags {
$_[0] =~ s{ <qtssrepeater ( .*? ) > ( .*?) </qtssrepeater> }
{ expandRepeater($1, $2) }isgxe;
$_[0] =~ s{ < ( /*? ) qtssobject ( .*? ) (/*?) >}
{ foundTag($2, $1, $3) }isgxe;
$_[0] =~ s{ < ( /*? ) qtssstring ( .*? ) (/*?) >}
{ foundString($2, $1, $3) }isgxe;
return "$_[0]";
}
sub StartStopServer {
my $messageHash = &adminprotolib::GetMessageHash();
my $data = "";
my $status = &adminprotolib::EchoData($data, $messageHash, $authheader, $qtssip, $qtssport, "/modules/admin/server/qtssSvrState", "/server/qtssSvrState");
# if the server is not running, launch process
if($status == 200) {
# if server is running, then put it in idle mode or if server is idle/not running, then put it in running mode
if($data == 1) {
$status = &adminprotolib::SetAttribute($data, $messageHash, $authheader, $qtssip, $qtssport, "/admin/server/qtssSvrState", 5);
}
else {
$status = &adminprotolib::SetAttribute($data, $messageHash, $authheader, $qtssip, $qtssport, "/admin/server/qtssSvrState", 1);
}
}
}
sub SaveGeneralSettings {
my $messHash = adminprotolib::GetMessageHash();
my %messages = %$messHash;
my $settingsPath = '/admin/server/qtssSvrPreferences/';
my $data = '';
my $configFilePath = $ENV{"QTSSADMINSERVER_CONFIG"};
my $sslValue = $query->{'adminSSL'};
my $autoStartValue = $query->{'qtssExtraGenSettings0'};
my $name = '';
my $val = '';
if ($sslValue ne '1') {
$sslValue = '0';
}
if ($autoStartValue ne '1') {
$autoStartValue = '0';
}
if ($query->{'qtssMovieFolder'} ne $query->{'qtssMovieFolder_shadow'}) {
$status = &adminprotolib::SetAttribute($data, $messHash, $authheader, $qtssip, $qtssport, $settingsPath."movie_folder", $query->{'qtssMovieFolder'});
}
if ($query->{'qtssMaxConn'} ne $query->{'qtssMaxConn_shadow'}) {
$status = &adminprotolib::SetAttribute($data, $messHash, $authheader, $qtssip, $qtssport, $settingsPath."maximum_connections", $query->{'qtssMaxConn'});
}
if (($query->{'bpsinput'} ne $query->{'bpsinput_shadow'}) or ($query->{'kbpstype'} ne $query->{'kbpstype_shadow'})) {
my $amt = $query->{'bpsinput'};
if ($query->{'kbpstype'} eq 'mbps') {
$amt = $amt * 1024
}
$status = &adminprotolib::SetAttribute($data, $messHash, $authheader, $qtssip, $qtssport, $settingsPath."maximum_bandwidth", $amt);
}
if ($query->{'qtssAuthScheme'} ne $query->{'qtssAuthScheme_shadow'}) {
$status = &adminprotolib::SetAttribute($data, $messHash, $authheader, $qtssip, $qtssport, $settingsPath."authentication_scheme", $query->{'qtssAuthScheme'});
}
if ($sslValue ne parseForSSL()) {
$configLine = qq(ssl=$sslValue\n);
if(!(-e $configFilePath)) {
open(CONFIGFILE, ">$configFilePath");
print CONFIGFILE $configLine;
close(CONFIGFILE);
FixFileGroup($configFilePath);
if($sslValue == 1)
{
$ENV{"HTTPS"} = "ON";
}
else
{
$ENV{"HTTPS"} = "OFF";
}
}
else {
if( -r $configFilePath && -w _) {
$tmpname = $configFilePath . ".tmp";
open(TEMPFILE, ">$tmpname");
open(CONFIGFILE, "<$configFilePath");
while($line = <CONFIGFILE>) {
$_ = $line;
chop;
if (/^#/ || !/\S/) {
print TEMPFILE $line;
next;
}
/^([^=]+)=(.*)$/;
$name = $1; $val = $2;
$name =~ s/^\s+//g; $name =~ s/\s+$//g;
$val =~ s/^\s+//g; $val =~ s/\s+$//g;
if($name eq "ssl") {
$val = $sslValue;
}
$config{$name} = $val;
print TEMPFILE qq($name=$val\n);
}
if(!defined($config{'ssl'})) {
print TEMPFILE $configLine;
}
close(CONFIGFILE);
close(TEMPFILE);
rename $tmpname, $configFilePath;
if($sslValue == 1)
{
$ENV{"HTTPS"} = "ON";
}
else
{
$ENV{"HTTPS"} = "OFF";
}
}
else {
print STDERR "couldn't open $configFilePath for writing\n";
}
}
}
$confirmMessage = $messages{'GenSetSettingsSavedText'};
}
sub RunAssistant {
my $messHash = adminprotolib::GetMessageHash();
my %messages = %$messHash;
my $settingsPath = '/admin/server/qtssSvrPreferences/';
my $MP3BroadcastPasswordPath = "/admin/server/qtssSvrModuleObjects/QTSSMP3StreamingModule/qtssModPrefs/mp3_broadcast_password";
my $data = '';
my $configFilePath = $ENV{"QTSSADMINSERVER_CONFIG"};
my $sslValue = $query->{'assistSSL'};
my $name = '';
my $val = '';
if ($sslValue ne '1') {
$sslValue = '0';
}
# set MP3 Broadcast Password
$status = &adminprotolib::SetAttribute($data, $messHash, $authheader, $qtssip, $qtssport, $MP3BroadcastPasswordPath, $query->{'assistMP3Pass'});
# set media folder
$status = &adminprotolib::SetAttribute($data, $messHash, $authheader, $qtssip, $qtssport, $settingsPath."movie_folder", $query->{'assistMovieFolder'});
# set streaming on port 80
SavePortSettings();
$confirmMessage = ''; # reset the confirm message
# set SSL on/off
$configLine = qq(ssl=$sslValue\n);
if(!(-e $configFilePath)) {
open(CONFIGFILE, ">$configFilePath");
print CONFIGFILE $configLine;
close(CONFIGFILE);
FixFileGroup($configFilePath);
if($sslValue == 1)
{
$ENV{"HTTPS"} = "ON";
}
else
{
$ENV{"HTTPS"} = "OFF";
}
}
else {
if( -r $configFilePath && -w _) {
$tmpname = $configFilePath . ".tmp";
open(TEMPFILE, ">$tmpname");
open(CONFIGFILE, "<$configFilePath");
while($line = <CONFIGFILE>) {
$_ = $line;
chop;
if (/^#/ || !/\S/) {
print TEMPFILE $line;
next;
}
/^([^=]+)=(.*)$/;
$name = $1; $val = $2;
$name =~ s/^\s+//g; $name =~ s/\s+$//g;
$val =~ s/^\s+//g; $val =~ s/\s+$//g;
if($name eq "ssl") {
$val = $sslValue;
}
$config{$name} = $val;
print TEMPFILE qq($name=$val\n);
}
if(!defined($config{'ssl'})) {
print TEMPFILE $configLine;
}
close(CONFIGFILE);
close(TEMPFILE);
rename $tmpname, $configFilePath;
if($sslValue == 1)
{
$ENV{"HTTPS"} = "ON";
}
else
{
$ENV{"HTTPS"} = "OFF";
}
}
else {
print STDERR "couldn't open $configFilePath for writing\n";
}
}
}
sub SavePortSettings {
my $messHash = adminprotolib::GetMessageHash();
my %messages = %$messHash;
my $data = '';
my $settingsPath = '/admin/server/qtssSvrPreferences/';
if ($query->{'qtssIsStreamingOn80'} ne $query->{'qtssIsStreamingOn80_shadow'}) {
if($query->{'qtssIsStreamingOn80'} eq "true") {
# set the pref
$status = &adminprotolib::AddValueToAttribute($data, $messHash, $authheader, $qtssip, $qtssport, $settingsPath."rtsp_port", 80);
# find out where the pid file is
my $pidfileloc = '';
my $status = &adminprotolib::EchoData($pidfileloc, $messageHash, $authheader, $qtssip, $qtssport, "/modules/admin/server/qtssSvrPreferences/pid_file", "/server/qtssSvrPreferences/pid_file");
# if the pid file exists...
if (-e $pidfileloc) {
# read in the file into an array
my @splitPidFile = ();
my $line;
if (open(PIDFILE, $pidfileloc)) {
while ($line = <PIDFILE>) {
push(@splitPidFile, $line);
}
close(PIDFILE);
}
if (scalar(@splitPidFile) > 0) {
if ($splitPidFile[1] ne '') {
kill 2, $splitPidFile[1];
sleep(2);
}
}
}
}
else {
$status = &adminprotolib::DeleteValueFromAttribute($data, $messHash, $authheader, $qtssip, $qtssport, $settingsPath."rtsp_port", 80);
}
}
$confirmMessage = $messages{'PortSetSavedText'};
}
sub SaveLogSettings {
my $messHash = adminprotolib::GetMessageHash();
my %messages = %$messHash;
my $errorPath = "/admin/server/qtssSvrPreferences/";
my $accessPath = "/admin/server/qtssSvrModuleObjects/QTSSAccessLogModule/qtssModPrefs/";
my $data = '';
$nextFilename = 'log_settings.html';
if ($query->{'qtssErrorLogging'} ne $query->{'qtssErrorLogging_shadow'}) {
if ($query->{'qtssErrorLogging'} eq 'true') {
$status = &adminprotolib::SetAttribute($data, $messHash, $authheader, $qtssip, $qtssport, $errorPath."error_logging", true);
}
else {
$status = &adminprotolib::SetAttribute($data, $messHash, $authheader, $qtssip, $qtssport, $errorPath."error_logging", false);
}
}
if ($query->{'qtssErrorLogInterval'} ne $query->{'qtssErrorLogInterval_shadow'}) {
$status = &adminprotolib::SetAttribute($data, $messHash, $authheader, $qtssip, $qtssport, $errorPath."error_logfile_interval", $query->{'qtssErrorLogInterval'});
}
if ($query->{'qtssErrorLogSize'} ne $query->{'qtssErrorLogSize_shadow'}) {
$status = &adminprotolib::SetAttribute($data, $messageHash, $authheader, $qtssip, $qtssport, $errorPath."error_logfile_size", ($query->{'qtssErrorLogSize'} * 1024));
}
if ($query->{'qtssRequestLogging'} ne $query->{'qtssRequestLogging_shadow'}) {
if ($query->{'qtssRequestLogging'} eq 'true') {
$status = &adminprotolib::SetAttribute($data, $messHash, $authheader, $qtssip, $qtssport, $accessPath."request_logging", true);
}
else {
$status = &adminprotolib::SetAttribute($data, $messHash, $authheader, $qtssip, $qtssport, $accessPath."request_logging", false);
}
}
if ($query->{'qtssRequestLogInterval'} ne $query->{'qtssRequestLogInterval_shadow'}) {
$status = &adminprotolib::SetAttribute($data, $messHash, $authheader, $qtssip, $qtssport, $accessPath."request_logfile_interval", $query->{'qtssRequestLogInterval'});
}
if ($query->{'qtssRequestLogSize'} ne $query->{'qtssRequestLogSize_shadow'}) {
$status = &adminprotolib::SetAttribute($data, $messageHash, $authheader, $qtssip, $qtssport, $accessPath."request_logfile_size", ($query->{'qtssRequestLogSize'} * 1024));
}
$filename = 'log_settings.html';
$confirmMessage = $messages{'LogSetSavedText'};
}
sub ChangePassword {
my $messHash = adminprotolib::GetMessageHash();
my %messages = %$messHash;
my $usersFileAttributePath = "/server/qtssSvrModuleObjects/QTSSAccessModule/qtssModPrefs/modAccess_usersfilepath";
my $groupsFileAttributePath = "/server/qtssSvrModuleObjects/QTSSAccessModule/qtssModPrefs/modAccess_groupsfilepath";
my $usersFilePath = '';
my $groupsFilePath = '';
my $qtssPasswdName = $ENV{"QTSSADMINSERVER_QTSSQTPASSWD"};
my $data = '';
my $line = '';
my $oldUsername = $query->{'old_username'};
my $newUsername = $query->{'new_user'};
my $groupsFileText = '';
my $usersFileText = '';
$nextFilename = 'change_password.html';
# if username or password is blank
if (($query->{'new_user'} eq '') or ($query->{'new_password1'} eq '')) {
$dialogHeader = $messages{'SetupAssistNoUsernameHeader'};
$dialogText = $messages{'SetupAssistNoUsername'};
return;
}
# if username has more than 255 characters
if (length($query->{'new_user'}) > 255) {
$dialogHeader = $messages{'ChPassUsernameNotLongerThan255Header'};
$dialogText = $messages{'ChPassUsernameNotLongerThan255Text'};
return;
}
# if username has a colon
if ($query->{'new_user'} =~ /:/) {
$dialogHeader = $messages{'ChPassUsernameCannotHaveColonHeader'};
$dialogText = $messages{'ChPassUsernameCannotHaveColonText'};
return;
}
# if username or password has a single or a double quote
if ( ($query->{'new_user'} =~ /['"]/) || ($query->{'new_password1'} =~ /['"]/) ) {
$dialogHeader = $messages{'ChPassCannotHaveQuotesHeader'};
$dialogText = $messages{'ChPassCannotHaveQuotesText'};
return;
}
# if password has more than 80 characters
if (length($query->{'new_password1'}) > 80) {
$dialogHeader = $messages{'ChPassNotLongerThan80Header'};
$dialogText = $messages{'ChPassNotLongerThan80Text'};
return;
}
# if old username:password doesn't match the current username:password
if (encodeBase64($oldUsername.':'.$query->{'old_password'}) ne getCookie('qtsspassword')) {
$dialogHeader = $messages{'ChPassOldPasswdWrongHeader'};
$dialogText = $messages{'ChPassOldPasswdWrongText'};
return;
}
# if new password #1 and new password #2 don't match
if ($query->{'new_password1'} ne $query->{'new_password2'}) {
$dialogHeader = $messages{'ChPassNoMatchHeader'};
$dialogText = $messages{'ChPassNoMatchText'};
return;
}
my $status = &adminprotolib::EchoData($groupsFilePath, $messHash, $authheader, $qtssip, $qtssport, "/modules/admin$groupsFileAttributePath", "/modules/admin$groupsFileAttributePath");
if ($status != 200) {
$dialogHeader = $messages{'ChPassErrorHeader'};
$dialogText = $messages{'ChPassErrorText'}." ($status - $data)";
return;
}
$status = &adminprotolib::EchoData($usersFilePath, $messHash, $authheader, $qtssip, $qtssport, "/modules/admin$usersFileAttributePath", "/modules/admin$usersFileAttributePath");
if ($status != 200) {
$dialogHeader = $messages{'ChPassErrorHeader'};
$dialogText = $messages{'ChPassErrorText'}." ($status - $data)";
return;
}
open(FILEHDL, "$groupsFilePath") or die "Can't open groups file '$groupsFilePath'!";
while ($line = <FILEHDL>) {
$groupsFileText .= $line;
}
close(FILEHDL);
my $quotedOldUsername = quotemeta($oldUsername);
$groupsFileText =~ s/([ \t:]+)$quotedOldUsername([\r\n\s]+)/$1$newUsername$2/;
$status = &adminprotolib::SetPassword($data, $messageHash, $authheader, $qtssip, $qtssport, $usersFileAttributePath, $query->{'new_password1'}, $qtssPasswdName, $newUsername);
sleep(2);
if ($status != 200) {
$dialogHeader = $messages{'ChPassErrorHeader'};
$dialogText = $messages{'ChPassErrorText'}." ($status - $data)";
return;
}
open(FILEHDL, ">$groupsFilePath") or die "Can't open groups file '$groupsFilePath'!";
print FILEHDL $groupsFileText;
close(FILEHDL);
FixFileGroup($groupsFilePath);
$newcookieval = encodeBase64($newUsername.':'.$query->{'new_password1'});
$cookie = 'qtsspassword='.$newcookieval.';path=/';
$auth = $newcookieval;
$authheader = "Authorization: Basic $auth\r\n";
if ($oldUsername ne $newUsername)
{
&adminprotolib::DeleteUsername($data, $messageHash, $authheader, $qtssip, $qtssport, $usersFileAttributePath, $qtssPasswdName, $oldUsername);
}
# $confirmMessage = $messages{'ChPassSavedText'};
$filename = 'change_password_redirect.html';
}
sub ChangeBroadcastPassword {
my $messHash = adminprotolib::GetMessageHash();
my %messages = %$messHash;
my $filedelim = &playlistlib::GetFileDelimChar();
my $moviesFolderPath;
my $status = &adminprotolib::EchoData($moviesFolderPath, $messHash, $authheader, $qtssip, $qtssport, "/modules/admin/server/qtssSvrPreferences/movie_folder", "movie_folder");
my $accessFilename;
$status = &adminprotolib::EchoData($accessFilename, $messHash, $authheader, $qtssip, $qtssport, "/modules/admin/server/qtssSvrModuleObjects/QTSSAccessModule/qtssModPrefs/modAccess_qtaccessfilename", "modAccess_qtaccessfilename");
my $usersFilename;
$status = &adminprotolib::EchoData($usersFilename, $messHash, $authheader, $qtssip, $qtssport, "/modules/admin/server/qtssSvrModuleObjects/QTSSAccessModule/qtssModPrefs/modAccess_usersfilepath", "modAccess_usersfilepath");
my $groupsFilename;
$status = &adminprotolib::EchoData($groupsFilename, $messHash, $authheader, $qtssip, $qtssport, "/modules/admin/server/qtssSvrModuleObjects/QTSSAccessModule/qtssModPrefs/modAccess_groupsfilepath", "modAccess_groupsfilepath");
$moviesFolderPath =~ s/[\/\\]$//o;
my $filename = "$moviesFolderPath$filedelim$accessFilename";
my $viewingUsersArrayRef = &passwordutils::GetViewingRestrictionsFromFile($filename);
my @viewingUsersArray = @$viewingUsersArrayRef;
my $viewingUsersString = join(' ', @viewingUsersArray);
my $broadcastUsersArrayRef = &passwordutils::GetBroadcastRestrictionsFromFile($filename);
my @broadcastUsersArray = @$broadcastUsersArrayRef;
my $oldBroadcastUser = '';
my $broadcastRestrictionString = '';
my ($currentAdminUsername, $currentAdminPass) = split(/:/, b64decode($auth));
my $qtpasswdpath = $ENV{"QTSSADMINSERVER_QTSSQTPASSWD"};
if ($broadcastUsersArray[1] eq 'user') {
$oldBroadcastUser = $broadcastUsersArray[2];
}
# change the password in the passwords file
# work on a copy if it's the current admin user
if ($query->{'new_user'} ne $oldBroadcastUser) {
if ($oldBroadcastUser ne $currentAdminUsername) {
&passwordutils::DeleteUser($qtpasswdpath, $usersFilename, $groupsFilename, $oldBroadcastUser);
}
if (($query-{'allowUnrestrictedBroadcast'} ne '1') && ($query->{'new_user'} ne '')) {
&passwordutils::AddOrEditBroadcastUser($qtpasswdpath, $usersFilename, $query->{'new_user'}, $query->{'new_password1'});
}
}
if ($query->{'allowUnrestrictedBroadcast'} eq '1') {
$broadcastRestrictionString = "require any-user";
}
elsif (($query->{'new_user'} ne '') && ($query->{'new_password1'} ne '')) {
$broadcastRestrictionString = "require user " . $query->{'new_user'};
}
my $viewingRestrictionString = join(' ', @$viewingUsersArrayRef);
#&passwordutils::WriteRestrictionsToFile($filename, $broadcastRestrictionString, $viewingRestrictionString);
# RemoveRestrictionsFile is for QTSS to sync with the server admin. Use WriteRestrictionsToFile above on Darwin Web Admins
&passwordutils::RemoveRestrictionsFile($filename);
$confirmMessage = $messages{'ChMP3PassSavedText'};
$filename = 'general_settings.html';
}
sub ChangeMP3Password {
my $messHash = adminprotolib::GetMessageHash();
my %messages = %$messHash;
my $MP3BroadcastPasswordPath = "/admin/server/qtssSvrModuleObjects/QTSSMP3StreamingModule/qtssModPrefs/mp3_broadcast_password";
my $qtssPasswdName = $ENV{"QTSSADMINSERVER_QTSSQTPASSWD"};
my $qtssAdmin = $ENV{"QTSSADMINSERVER_QTSSADMIN"};
my $data = '';
$nextFilename = 'change_mp3_password.html';
if ($query->{'new_password1'} ne $query->{'new_password2'}) {
$dialogHeader = $messages{'ChMP3PassNoMatchHeader'};
$dialogText = $messages{'ChMP3PassNoMatchText'};
return;
}
$status = &adminprotolib::SetAttribute($data, $messHash, $authheader, $qtssip, $qtssport, $MP3BroadcastPasswordPath, $query->{'new_password1'});
$confirmMessage = $messages{'ChMP3PassSavedText'};
$filename = $query->{'replaceFilename'};
if ($filename eq '') {
$filename = 'general_settings.html';
}
}
# AssistSetPassword
# returns 0 => failure
# 1 => success
sub AssistSetPassword {
my $messHash = adminprotolib::GetMessageHash();
my %messages = %$messHash;
my $usersFileAttributePath = "/server/qtssSvrModuleObjects/QTSSAccessModule/qtssModPrefs/modAccess_usersfilepath";
my $groupsFileAttributePath = "/server/qtssSvrModuleObjects/QTSSAccessModule/qtssModPrefs/modAccess_groupsfilepath";
my $usersFilePath = '';
my $groupsFilePath = '';
my $qtssPasswdName = $ENV{"QTSSADMINSERVER_QTSSQTPASSWD"};
my $qtssAdmin = $ENV{"QTSSADMINSERVER_QTSSADMIN"};
my $data = '';
my $line = '';
my $newUsername = $query->{'new_user'};
my $newPassword = $query->{'new_password1'};
my ($oldUsername, $authpass) = split(/:/, b64decode($auth));
$nextFilename = 'setup_assistant.html';
# if username or password is blank
if (($query->{'new_user'} eq '') or ($query->{'new_password1'} eq '')) {
$dialogHeader = $messages{'SetupAssistNoUsernameHeader'};
$dialogText = $messages{'SetupAssistNoUsername'};
return 0;
}
# if username has more than 255 characters
if (length($query->{'new_user'}) > 255) {
$dialogHeader = $messages{'ChPassUsernameNotLongerThan255Header'};
$dialogText = $messages{'ChPassUsernameNotLongerThan255Text'};
return 0;
}
# if username has a colon
if ($query->{'new_user'} =~ /:/) {
$dialogHeader = $messages{'ChPassUsernameCannotHaveColonHeader'};
$dialogText = $messages{'ChPassUsernameCannotHaveColonText'};
return 0;
}
# if username or password has a single quote or a double quote
if ( ($query->{'new_user'} =~ /['"]/) || ($query->{'new_password1'} =~ /['"]/) ) {
$dialogHeader = $messages{'ChPassCannotHaveQuotesHeader'};
$dialogText = $messages{'ChPassCannotHaveQuotesText'};
return 0;
}
# if password has more than 80 characters
if (length($query->{'new_password1'}) > 80) {
$dialogHeader = $messages{'ChPassNotLongerThan80Header'};
$dialogText = $messages{'ChPassNotLongerThan80Text'};
return 0;
}
# if new password #1 and new password #2 don't match
if ($query->{'new_password1'} ne $query->{'new_password2'}) {
$dialogHeader = $messages{'ChPassNoMatchHeader'};
$dialogText = $messages{'ChPassNoMatchText'};
return 0;
}
my $status = 200;
if (($^O eq "darwin") and (-e "index.html") and (MacQTGroupsContainsAdminGroup() == 0)) {
my $line = '';
$groupsFileText = '';
if (-e '/Library/QuickTimeStreaming/Config/qtgroups') {
open(GROUPSFILE, '/Library/QuickTimeStreaming/Config/qtgroups') or die("Can't open groups file!");
while ($line = <GROUPSFILE>) {
$groupsFileText .= $line;
}
close(GROUPSFILE);
}
$groupsFileText .= "admin: $newUsername\n";
$groupsFilePath = '/Library/QuickTimeStreaming/Config/qtgroups';
my $extraargs = '';
my $qtpasswdpath = $ENV{'QTSSADMINSERVER_QTSSQTPASSWD'};
if (!(-e '/Library/QuickTimeStreaming/Config/qtusers')) {
$extraargs = ' -c';
}
if(system("$qtpasswdpath$extraargs -p \'$newPassword\' \'$newUsername\'") != 0) {
$dialogHeader = $messages{'ChPassErrorHeader'};
$dialogText = $messages{'ChPassErrorText'};
return 0;
}
else {
$status = 200
}
}
else {
$status = &adminprotolib::EchoData($groupsFilePath, $messHash, $authheader, $qtssip, $qtssport, "/modules/admin$groupsFileAttributePath", "/modules/admin$groupsFileAttributePath");
if ($status == 401) {
$auth = encodeBase64('aGFja21l:aGFja21l');
$authheader = "Authorization: Basic $auth\r\n";
$oldUsername = 'aGFja21l';
$status = &adminprotolib::EchoData($groupsFilePath, $messHash, $authheader, $qtssip, $qtssport, "/modules/admin$groupsFileAttributePath", "/modules/admin$groupsFileAttributePath");
}
if ($status != 200) {
$dialogHeader = $messages{'ChPassErrorHeader'};
$dialogText = $messages{'ChPassErrorText'}." ($status - $data)";
return 0;
}
$status = &adminprotolib::EchoData($usersFilePath, $messHash, $authheader, $qtssip, $qtssport, "/modules/admin$usersFileAttributePath", "/modules/admin$usersFileAttributePath");
if ($status != 200) {
$dialogHeader = $messages{'ChPassErrorHeader'};
$dialogText = $messages{'ChPassErrorText'}." ($status - $data)";
return 0;
}
open(FILEHDL, "$groupsFilePath") or die "Can't open groups file '$groupsFilePath'!";
while ($line = <FILEHDL>) {
$groupsFileText .= $line;
}
close(FILEHDL);
my $quotedOldUsername = quotemeta($oldUsername);
$groupsFileText =~ s/([ \t:]+)$quotedOldUsername([\r\n\s]+)/$1$newUsername$2/;
$status = &adminprotolib::SetPassword($data, $messageHash, $authheader, $qtssip, $qtssport, $usersFileAttributePath, $query->{'new_password1'}, $qtssPasswdName, $newUsername);
if ($status != 200) {
$dialogHeader = $messages{'ChPassErrorHeader'};
$dialogText = $messages{'ChPassErrorText'}." ($status - $data)";
return 0;
}
}
open(FILEHDL, ">$groupsFilePath") or die "Can't open groups file '$groupsFilePath'!";
print FILEHDL $groupsFileText;
close(FILEHDL);
FixFileGroup($groupsFileText);
# set the cookie and the auth header before calling DeleteUsername as the server expects the new username:password now
my $newcookieval = encodeBase64($newUsername.':'.$query->{'new_password1'});
$cookie = 'qtsspassword='.$newcookieval.'; path=/';
$auth = $newcookieval;
$authheader = "Authorization: Basic $auth\r\n";
if ($oldUsername ne $newUsername)
{
&adminprotolib::DeleteUsername($data, $messageHash, $authheader, $qtssip, $qtssport, $usersFileAttributePath, $qtssPasswdName, $oldUsername);
}
$dialogHeader = $messages{'ChPassSavedHeader'};
$dialogText = $messages{'ChPassSavedText'};
$filename = 'setup_assistant2.html';
return 1;
}
sub StartPlaylist {
my $messHash = adminprotolib::GetMessageHash();
my %messages = %$messHash;
my $curplaylist = $query->{'curplaylist'};
my $isRunning = &playlistlib::GetPlayListState($curplaylist);
my $filedelim = &playlistlib::GetFileDelimChar();
my $plroot = &playlistlib::GetPLRootDir();
my $filedelim = &playlistlib::GetFileDelimChar();
my $targ = '';
my $targline = '';
my $plfiletext = '';
my $success = 0;
my $targ = "$plroot$curplaylist$filedelim$curplaylist";
my $isRunning = &playlistlib::GetPlayListState($curplaylist);
# open the playlist and re-save it so that the MP3 broadcast password is updated if necessary
my $playlistdataref = &playlistlib::ParsePlayListEntry($curplaylist, $messHash);
my $movieDir = '';
my $mp3BroadcastPassword = '';
my $status = adminprotolib::EchoData($movieDir, $messHash, $authheader, $qtssip, $qtssport, "/modules/admin/server/qtssSvrPreferences/movie_folder", "/modules/admin/server/qtssSvrPreferences/movie_folder");
$status = adminprotolib::EchoData($mp3BroadcastPassword, $messHash, $authheader, $qtssip, $qtssport, "/modules/admin/server/qtssSvrModuleObjects/QTSSMP3StreamingModule/qtssModPrefs/mp3_broadcast_password", "/modules/admin/server/qtssSvrModuleObjects/QTSSMP3StreamingModule/qtssModPrefs/mp3_broadcast_password");
if (&playlistlib::CreatePlayListEntry($curplaylist, $playlistdataref, $movieDir, $mp3BroadcastPassword) == 0) {
$confirmMessage = '';
$filename = 'confirm.html';
$dialogHeader = $messages{'PLErrorHeader'};
$dialogText = $messages{'PLErrorHeader'};
$nextFilename = 'playlists.html';
return;
}
# playlist is re-saved
if ("$isRunning" ne 1) {
open(PLFILE, "$targ.config");
while ($targline = <PLFILE>) {
$plfiletext .= $targline;
}
close(PLFILE);
if ($plfiletext =~ /broadcast_genre /) {
$isMP3 = 1;
}
else {
$isMP3 = 0;
}
$success = &playlistlib::StartPlayList($curplaylist, $isMP3);
if ($success != 1) {
$filename = 'confirm.html';
$nextFilename = 'playlists.html';
$dialogHeader = $messages{'PLErrorHeader'};
$dialogText = $messages{'PLErrorText'};
return;
}
else
{
# successfully started the playlist!
my $startfile = "$plroot$curplaylist$filedelim" . '.started';
# create a file in the playlist directory called .started
# which we shall delete when we stop the playlist later
open(STARTFILE, ">$startfile");
close(STARTFILE);
FixFileGroup($startfile);
chmod(0644, $startfile);
}
}
# $confirmMessage = $messages{'PLChangedText'};
}
sub StopPlaylist
{
my $messHash = adminprotolib::GetMessageHash();
my %messages = %$messHash;
my $plroot = &playlistlib::GetPLRootDir();
my $filedelim = &playlistlib::GetFileDelimChar();
my $curplaylist = $query->{'curplaylist'};
my $isRunning = &playlistlib::GetPlayListState($curplaylist);
my $filedelim = &playlistlib::GetFileDelimChar();
my $targ = '';
my $targline = '';
my $plfiletext = '';
my $targ = "$plroot$curplaylist$filedelim$curplaylist";
my $isRunning = &playlistlib::GetPlayListState($curplaylist);
if ("$isRunning" ne $startstop{$i})
{
# delete the file created when we started the playlist
# even if we don't succeed in stopping the playlist
# (which would only happen if we were reporting the wrong status
# and the playlist was already stopped)
my $startfile = "$plroot$curplaylist$filedelim" . '.started';
if ( -e $startfile)
{
unlink($startfile);
}
if (&playlistlib::StopPlayList($curplaylist) != 1)
{
$dialogHeader = $messages{'PLErrorHeader'};
$dialogText = $messages{'PLErrorText'};
return;
}
}
# $confirmMessage = $messages{'PLChangedText'};
}
sub ShowPlaylistLog {
my $curplaylist = $query->{'curplaylist'};
$playlistErrorLogText = &playlistlib::EmitPlayListErrLogFile($curplaylist);
}
sub PLOpenDir {
my $messHash = adminprotolib::GetMessageHash();
my %messages = %$messHash;
my $genreArrayRef = adminprotolib::GetGenreArray();
$curplaylist = $query->{'curplaylist'};
$movieDir = $query->{'submitcurrentdir'};
}
sub GetPlaylist {
my $messHash = adminprotolib::GetMessageHash();
my %messages = %$messHash;
my $genreArrayRef = adminprotolib::GetGenreArray();
$curplaylist = $query->{'curplaylist'};
my $playlistdataref = &playlistlib::ParsePlayListEntry($curplaylist, $messHash);
my @playlistdata = @$playlistdataref;
my $status = adminprotolib::EchoData($movieDir, $messHash, $authheader, $qtssip, $qtssport, "/modules/admin/server/qtssSvrPreferences/movie_folder", "/modules/admin/server/qtssSvrPreferences/movie_folder");
$currentDir = $movieDir;
$plfilename = $playlistdata[0];
$plmode = $playlistdata[1];
$pllogging = $playlistdata[2];
$plfilesref = $playlistdata[3];
@plfiles = @$plfilesref;
$plrep = $playlistdata[4];
$plgenre = $playlistdata[5];
$plbroadcastip = $playlistdata[6];
$plbroadcastusername = $playlistdata[7];
$plbroadcastpassword = $playlistdata[8];
$pltitle = $playlistdata[9];
if ($plgenre eq '') {
$isMP3 = 0;
$doctitle = $messages{'PLMoviePlaylistDetails'};
$extraFieldLabel = '';
$extraFieldHTML = '<input type=hidden name=PLGenre value="">';
$playlistUsernameHTML = '<tr><td align=left>&nbsp;</td><td align=right>'.$messages{'Username'}.'</td><td align=left><input type=text name=plbroadcastusername value="' . $plbroadcastusername . '"></td></tr>';
}
else {
$isMP3 = 1;
$doctitle = $messages{'PLMP3PlaylistDetails'};
$extraFieldLabel = $messages{'PLGenre'};
$extraFieldHTML = '<select name=PLGenre>'.&playlistlib::GetGenreOptions($plgenre, $messages{'PLDefaultGenre'}, $genreArrayRef).'</select>';
$playlistUsernameHTML = '';
}
if ($plbroadcastip eq '127.0.0.1') {
$plexternal = '0';
$plbroadcastusername = '';
$plbroadcastpassword = '';
}
else {
$plexternal = '1';
}
}
sub CreatePlaylist {
my $messHash = adminprotolib::GetMessageHash();
my %messages = %$messHash;
my $plroot = &playlistlib::GetPLRootDir();
my $fileDelimChar = &playlistlib::GetFileDelimChar();
my $movieDir = '';
my $mp3BroadcastPassword = '';
my $status = adminprotolib::EchoData($movieDir, $messHash, $authheader, $qtssip, $qtssport, "/modules/admin/server/qtssSvrPreferences/movie_folder", "/modules/admin/server/qtssSvrPreferences/movie_folder");
my $status = adminprotolib::EchoData($mp3BroadcastPassword, $messHash, $authheader, $qtssip, $qtssport, "/modules/admin/server/qtssSvrModuleObjects/QTSSMP3StreamingModule/qtssModPrefs/mp3_broadcast_password", "/modules/admin/server/qtssSvrModuleObjects/QTSSMP3StreamingModule/qtssModPrefs/mp3_broadcast_password");
my @plcontents = ();
my $item = '';
my $plname = $query->{'qtssCurPlaylistName'};
my $i = 2;
if ($plname eq '') {
# no playlist filename yet... means this is a new playlist
# set it to the playlist title
$plname = $query->{'qtssCurPlaylistTitle'};
# drop all non-alphanumeric characters
$plname =~ s/[^a-zA-Z0-9]//go;
if (($plname eq '') or (-e "$plroot$plname$fileDelimChar")) {
while (-e "$plroot$plname$fileDelimChar$i") {
$i++;
}
$plname = "$plname$i";
}
}
else {
if (-e "$plroot$plname$fileDelimChar$plname.err") {
unlink "$plroot$plname$fileDelimChar$plname.err";
}
}
$i = 0;
$nextFilename = 'playlists.html';
$confirmMessage = $messages{'PLCreatedText'};
my $qtssCurPlaylistURL = $plname.'.sdp';
if ($query->{'qtssCurPlaylistURL'} ne '') {
$qtssCurPlaylistURL = $query->{'qtssCurPlaylistURL'};
}
my $qtssCurPlaylistMode = $query->{'qtssCurPlaylistMode'};
my $playlistFiles = $query->{'submitplaylistfiles'};
$playlistFiles =~ s/%(..)/pack("c",hex($1))/ge;
@plcontents = split(/\t/, $playlistFiles);
my @submitplaylistweights = split(/\t/, $query->{'submitplaylistweights'});
foreach $item (@plcontents) {
$item = "$item:$submitplaylistweights[$i++]";
}
my $qtssCurPlaylistRep = '1';
if ($query->{'qtssCurPlaylistRep'} ne '') {
$qtssCurPlaylistRep = $query->{'qtssCurPlaylistRep'};
}
my $destipaddr = $query->{'plbroadcastip'};
my $broadcastusername = $query->{'plbroadcastusername'};
my $broadcastpassword = $query->{'plbroadcastpassword'};
if (($query->{'plexternal'} ne '1') or ($destipaddr eq '')) {
$destipaddr = '127.0.0.1';
$broadcastusername = '';
$broadcastpassword = '';
}
my @plsettings = ($qtssCurPlaylistURL,$qtssCurPlaylistMode,$query->{'pllogging'},\@plcontents,$qtssCurPlaylistRep,$query->{'PLGenre'},$destipaddr,$broadcastusername,$broadcastpassword,$query->{'qtssCurPlaylistTitle'});
if (&playlistlib::CreatePlayListEntry($plname, \@plsettings, $movieDir, $mp3BroadcastPassword) == 0) {
$confirmMessage = '';
$filename = 'confirm.html';
$dialogHeader = $messages{'PLCreateErrorHeader'};
$dialogText = $messages{'PLCreateErrorText'};
$nextFilename = 'playlists.html';
}
}
# NewPlaylist expects the var isMP3 to be set to 0 or 1
sub NewPlaylist {
my $messHash = adminprotolib::GetMessageHash();
my %messages = %$messHash;
my $genreArrayRef = &adminprotolib::GetGenreArray();
my @genreArray = @$genreArrayRef;
my $status = adminprotolib::EchoData($movieDir, $messHash, $authheader, $qtssip, $qtssport, "/modules/admin/server/qtssSvrPreferences/movie_folder", "/modules/admin/server/qtssSvrPreferences/movie_folder");
$currentDir = useDefaultIfBlank($query->{'currentdir'}, $movieDir);
$plrep = 1;
@plfiles = ();
$plrep = '1';
$curplaylist = '';
$pltitle = '';
$plfilename = '';
$plmode = '';
$pllogging = '';
$plbroadcastip = '127.0.0.1';
$plbroadcastusername = '';
$plbroadcastpassword = '';
if ($isMP3 == 1) {
$doctitle = $messages{'PLMP3PlaylistDetails'};
$extraFieldLabel = $messages{'PLGenre'};
$extraFieldHTML = '<select name=PLGenre>'.&playlistlib::GetGenreOptions('', $messages{'PLDefaultGenre'}, $genreArrayRef).'</select>';
$playlistUsernameHTML = '';
$pltitle = $messages{'PLDefaultPlaylistName'};
$plfilename = $messages{'PLDefaultMP3PlaylistMountPoint'};
}
else {
$doctitle = $messages{'PLMoviePlaylistDetails'};
$extraFieldLabel = '';
$extraFieldHTML = '';
$playlistUsernameHTML = '<tr><td align=left>&nbsp;</td><td align=right>'.$messages{'Username'}.'</td><td align=left><input type=text name=plbroadcastusername></td></tr>';
$pltitle = $messages{'PLDefaultPlaylistName'};
$plfilename = $messages{'PLDefaultMoviePlaylistSDP'};
}
}
sub RefreshPlaylistDir() {
my $messHash = adminprotolib::GetMessageHash();
my %messages = %$messHash;
my $genreArrayRef = &adminprotolib::GetGenreArray();
my @genreArray = @$genreArrayRef;
my $i = 0;
my $playlistFiles = $query->{'submitplaylistfiles'};
$playlistFiles =~ s/%(..)/pack("c",hex($1))/ge;
my @plcontents = split(/\t/, $playlistFiles);
my @submitplaylistweights = split(/\t/, $query->{'submitplaylistweights'});
@plfiles = ();
my $status = adminprotolib::EchoData($movieDir, $messHash, $authheader, $qtssip, $qtssport, "/modules/admin/server/qtssSvrPreferences/movie_folder", "/modules/admin/server/qtssSvrPreferences/movie_folder");
foreach $item (@plcontents) {
push(@plfiles, "$item:$submitplaylistweights[$i++]");
}
$currentDir = $query->{'submitcurrentdir'};
$currentDir =~ s/%(..)/pack("c",hex($1))/ge;
$query->{'submitcurrentdir'} = '';
$isMP3 = $query->{'isMP3'};
$plrep = $query->{'qtssCurPlaylistRep'};
$curplaylist = $query->{'qtssCurPlaylistName'};
$pltitle = $query->{'qtssCurPlaylistTitle'};
$plfilename = $query->{'qtssCurPlaylistURL'};
$plmode = $query->{'qtssCurPlaylistMode'};
$plrep = $query->{'qtssCurPlaylistRep'};
$plgenre = $query->{'PLGenre'};
$pllogging = $query->{'pllogging'};
$plbroadcastip = $query->{'plbroadcastip'};
$plbroadcastusername = $query->{'plbroadcastusername'};
$plbroadcastpassword = $query->{'plbroadcastpassword'};
if ($isMP3 == 0) {
$doctitle = $messages{'PLMoviePlaylistDetails'};
$extraFieldLabel = '';
$extraFieldHTML = '<input type=hidden name=PLGenre value="">';
$playlistUsernameHTML = '<tr><td>&nbsp;</td><td align=right>'.$messages{'Username'}.'</td><td><input type=text name=plbroadcastusername value="' . $plbroadcastusername . '"></td></tr>';
}
else {
$doctitle = $messages{'PLMP3PlaylistDetails'};
$extraFieldLabel = $messages{'PLGenre'};
$extraFieldHTML = '<select name=PLGenre>'.&playlistlib::GetGenreOptions($plgenre, $messages{'PLDefaultGenre'}, $genreArrayRef).'</select>';
$playlistUsernameHTML = '';
}
if (($plbroadcastip eq '127.0.0.1') or ($plbroadcastip eq '')) {
$plexternal = '0';
$plbroadcastusername = '';
$plbroadcastpassword = '';
}
else {
$plexternal = '1';
}
}
sub DeletePlaylist {
my $messHash = adminprotolib::GetMessageHash();
my %messages = %$messHash;
if (&playlistlib::RemovePlaylistDir($query->{'curplaylist'}) == 1) {
$confirmText = $messages{'PLDeleteText'};
}
else {
$filename = 'confirm.html';
$nextFilename = 'playlists.html';
$dialogHeader = $messages{'PLDeleteErrorHeader'};
$dialogText = $messages{'PLDeleteErrorText'};
}
}
sub ResetErrorLog {
my $chdelim = &playlistlib::GetFileDelimChar();
my $messHash = adminprotolib::GetMessageHash();
my %messages = %$messHash;
my $responseText = '';
my $status = adminprotolib::GetData($responseText, $messHash, $authheader, $qtssip, $qtssport, '/modules/admin/server/qtssSvrPreferences/error_logfile_dir');
$_ = $responseText;
$confirmMessage = 'redirect';
if (!(/error_logfile_dir="([^"]+)"/)) {
die('Error getting logfile dir.');
}
my $dirname = $1;
$status = adminprotolib::GetData($responseText, $messHash, $authheader, $qtssip, $qtssport, '/modules/admin/server/qtssSvrPreferences/error_logfile_name');
$_ = $responseText;
if (!(/error_logfile_name="([^"]+)"/)) {
die('Error getting filename.');
}
$logname = $1;
$logfilename = $dirname . $chdelim . $logname . '.log';
$logfilename =~ s/\/{2,}/\//g; # remove duplicate slashes
if (-e $logfilename) {
$rolldatestr = sprintf("%02d%02d%02d", sub {($_[5] % 100, $_[4]+1, $_[3])}->(localtime));
$rollfilenumber = 0;
$rollfilename = "$dirname$chdelim" . $logname . ".$rolldatestr" . '000.log';
while (-e $rollfilename) {
$rollfilenumber++;
$rollfilename = "$dirname$chdelim" . $logname . ".$rolldatestr" . sprintf("%03d", $rollfilenumber) . '.log';
}
$rollfilename =~ s/\/{2,}/\//g; # remove duplicate slashes
`/bin/mv "$logfilename" "$rollfilename"`;
#unlink($dirname);
}
$confirmMessage = $messages{'ErrorLogResetConf'};
}
sub SaveBroadcasterSettings {
my $restartBroadcaster = 0;
my $changedNetworkSetting = 0;
my %messages = %$messageHash;
if (!$broadcasterConn) {
RestartBroadcaster();
if (!$broadcasterConn) {
$filename = 'start_broadcaster.html';
return false;
}
}
if (($broadcasterConn->state != 0) && ($theAction eq 'SaveBroadcasterSettings')) {
$restartBroadcaster = 1;
$broadcasterConn->stopBroadcast;
}
if ($query->{'qtbCurrentAudioPreset'} ne $query->{'qtbCurrentAudioPreset_shadow'}) {
$changedNetworkSetting = 1;
&broadcasterlib::SetCurrentPresetForType($broadcasterConn, 0, $query->{'qtbCurrentAudioPreset'});
}
if ($query->{'qtbCurrentVideoPreset'} ne $query->{'qtbCurrentVideoPreset_shadow'}) {
$changedNetworkSetting = 1;
&broadcasterlib::SetCurrentPresetForType($broadcasterConn, 1, $query->{'qtbCurrentVideoPreset'});
}
if ($query->{'qtbAudioStreamEnabled'} ne $query->{'qtbAudioStreamEnabled_shadow'}) {
&broadcasterlib::SetStreamEnabledForType($broadcasterConn, 0, $query->{'qtbAudioStreamEnabled'});
}
if ($query->{'qtbVideoStreamEnabled'} ne $query->{'qtbVideoStreamEnabled_shadow'}) {
&broadcasterlib::SetStreamEnabledForType($broadcasterConn, 1, $query->{'qtbVideoStreamEnabled'});
}
if ($query->{'qtbRecordingPath'} ne $query->{'qtbRecordingPath_shadow'}) {
&broadcasterlib::SetRecordingPath($broadcasterConn, $query->{'qtbRecordingPath'});
}
if ($query->{'qtbNetworkPresetSDPFilename'} ne $query->{'qtbNetworkPresetSDPFilename_shadow'}) {
$changedNetworkSetting = 1;
&broadcasterlib::SetNetworkFilepath($query->{'qtbNetworkPresetSDPFilename'});
}
if ($query->{'qtbBufferDelay'} ne $query->{'qtbBufferDelay_shadow'}) {
$changedNetworkSetting = 1;
&broadcasterlib::SetBufferDelay($query->{'qtbBufferDelay'});
}
if ($changedNetworkSetting == 1) {
&broadcasterlib::RereadSettingsFile($broadcasterConn);
}
if (($restartBroadcaster) && ($theAction eq 'SaveBroadcasterSettings')) {
StartStopBroadcast();
}
if ($confirmMessage ne $messages{'QTBErrBroadcastSettings'}) {
$confirmMessage = $messages{'QTBConfSaved'};
}
}
sub StartStopBroadcast {
if ($theAction eq 'StartStopBroadcast') {
SaveBroadcasterSettings();
}
my %messages = %$messageHash;
my $messageName = '';
if ($broadcasterConn) {
$messageName = &broadcasterlib::StartStopBroadcast($broadcasterConn);
}
$confirmMessage = $messages{$messageName};
if ($messageName eq '') { # couldn't start broadcast
$confirmMessage = $messages{'QTBErrBroadcastSettings'};
}
if ($messageName eq 'QTBConfStarted') {
my $value = '/modules/admin/server/qtssSvrDefaultDNSName';
my $data = '';
my $status = adminprotolib::EchoData($data, $messHash, $authheader, $qtssip, $qtssport, $value, $value);
&broadcasterlib::WriteRefMovie($data);
my $cycles = 0;
my $continue = 1;
my $state;
while ($continue == 1) {
sleep(1);
$state = &broadcasterlib::GetBroadcasterStateID($broadcasterConn);
$cycles = $cycles + 1;
if (($cycles > 7) || ($state == 3)) {
$continue = 0;
}
}
if ($state != 3) {
$confirmMessage = $messages{'QTBErrBroadcastSettings'};
}
}
}
sub RestartBroadcaster {
eval("require 'broadcaster_lib.pl';");
&broadcasterlib::KillServer(1);
sleep(1);
ConnectToBroadcaster(1);
}
# this routine performs an action, if there is any
sub PerformAction {
my $messHash = adminprotolib::GetMessageHash();
my %messages = %$messHash;
if ($theAction eq 'refreshmessages') {
# refresh the message hashes from the correct files.
&streamingadminserver::LoadMessageHashes();
}
elsif ($theAction eq 'login') {
$cookie = 'qtsspassword='.encodeBase64($query->{'qtssusername'}.':'.$query->{'qtsspassword'}).'; path=/';
return true;
}
elsif ($theAction eq 'logout') {
$cookie = 'qtsspassword=; path=/';
return true;
}
elsif ($theAction eq 'StartStopServer') {
StartStopServer();
}
elsif ($theAction eq 'restartadminserver') {
restart_streamingadminserver();
return true;
}
elsif ($theAction eq 'setrefresh') {
if (getCookie('pageRefreshInterval') ne $query->{'pageRefreshInterval'}) {
$cookie = 'pageRefreshInterval='.$query->{'pageRefreshInterval'}.'; path=/';
}
else {
$cookie = 'displayCount='.$query->{'displayCount'}.'; path=/';
}
return true;
}
elsif ($theAction eq 'setconnusersort') {
$cookie = 'connUserSort='.$query->{'connUserSort'};
}
elsif ($theAction eq 'setrelaystatsort') {
$cookie = 'relayStatSort='.$query->{'relayStatSort'};
}
elsif ($theAction eq 'SaveGeneralSettings') {
SaveGeneralSettings();
}
elsif ($theAction eq 'ChangePassword') {
ChangePassword();
}
elsif ($theAction eq 'ConfirmPassChanged') {
$confirmMessage = $messages{'ChPassSavedText'};
}
elsif ($theAction eq 'ChangeMP3Password') {
ChangeMP3Password();
}
elsif ($theAction eq 'ChangeBroadcastPassword') {
ChangeBroadcastPassword();
}
elsif ($theAction eq 'SaveLogSettings') {
SaveLogSettings();
}
elsif ($theAction eq 'SavePortSettings') {
SavePortSettings();
}
elsif ($theAction eq 'StartPlaylist') {
StartPlaylist();
}
elsif ($theAction eq 'StopPlaylist') {
StopPlaylist();
}
elsif ($theAction eq 'ShowPlaylistLog') {
ShowPlaylistLog();
}
elsif ($theAction eq 'GetPlaylist') {
GetPlaylist();
}
elsif ($theAction eq 'CreatePlaylist') {
CreatePlaylist();
}
elsif ($theAction eq 'NewMP3Playlist') {
$isMP3 = 1;
NewPlaylist();
}
elsif ($theAction eq 'NewMoviePlaylist') {
$isMP3 = 0;
NewPlaylist();
}
elsif ($theAction eq 'RefreshPlaylistDir') {
RefreshPlaylistDir();
}
elsif ($theAction eq 'DeletePlaylist') {
DeletePlaylist();
}
elsif ($theAction eq 'getValsForRelay') {
getValsForRelay();
}
elsif ($theAction eq 'getNewRelay') {
getNewRelay();
}
elsif ($theAction eq 'getRelayDestData') {
getRelayDestData();
}
elsif ($theAction eq 'SetRelayDestData') {
SetRelayDestData();
}
elsif ($theAction eq 'AddRelayDestination') {
AddRelayDestination();
}
elsif ($theAction eq 'DeleteRelayDest') {
DeleteRelayDest();
}
elsif ($theAction eq 'SaveRelay') {
SaveRelay();
}
elsif ($theAction eq 'DeleteRelay') {
DeleteRelay();
$confirmMessage = $messages{'RelayDeleteText'};
}
elsif ($theAction eq 'RunAssistant') {
RunAssistant();
if (-e "index.html") {
unlink("index.html");
}
}
elsif ($theAction eq 'AssistSetPassword') {
my $setupAssistantPasswordSuccess = AssistSetPassword();
if (($setupAssistantPasswordSuccess == 1) && (-e "index.html")) {
unlink("index.html");
}
}
elsif ($theAction eq 'ResetErrorLog') {
ResetErrorLog();
}
elsif ($theAction eq 'SaveBroadcasterSettings') {
SaveBroadcasterSettings();
}
elsif ($theAction eq 'StartStopBroadcast') {
StartStopBroadcast();
}
elsif ($theAction eq 'StartBroadcaster') {
eval("require 'broadcaster_lib.pl';");
ConnectToBroadcaster(1);
sleep(3);
}
elsif ($theAction eq 'RestartBroadcaster') {
RestartBroadcaster();
}
elsif ($theAction eq 'QuitBroadcaster') {
eval("require 'broadcaster_lib.pl';");
ConnectToBroadcaster(0);
if (!(!$broadcasterConn || !$$broadcasterConn)) {
&broadcasterlib::QuitBroadcaster($broadcasterConn);
}
my %messages = %$messageHash;
$confirmMessage = $messages{'QTBConfQuit'};
}
elsif ($theAction eq '') {
return true;
}
else {
die("Action not found!");
}
}
# post method environment variable
$cl = $ENV{"CONTENT_LENGTH"};
if ($ENV{"REQUEST_METHOD"} eq "POST")
{
# put the data into a variable
read(STDIN, $qs, $cl);
$query = &adminprotolib::ParseQueryString($qs);
}
elsif ($ENV{"REQUEST_METHOD"} eq "GET")
{
$qs = $ENV{"QUERY_STRING"};
$query = &adminprotolib::ParseQueryString($qs);
}
# get the filename
$filename = $query->{'filename'};
if (($filename =~ /[^A-Za-z0-9_\-\.\/]/) or ($filename =~ /\.{2,}/) or ($filename =~ /\/{2,}/)) {
die "Can't access HTML file!";
}
$auth = $query->{'qtsspassword'};
$username = $query->{'qtssusername'};
$cookie = $query->{'cookie'};
$confirmMessage = '';
$chdelim = &playlistlib::GetFileDelimChar();
$serverRoot = $ENV{"SERVER_ROOT"};
# fix for 3148849
# if the filename starts with /, remove the slash
$filename =~ s/^\///;
# fix for 3064725
# if the setup assistant is being called and the index file no longer exists,
# clear $filename so we get the frameset instead
if (($filename =~ m/setup_assistant2/) && (!(-e "$serverRoot/index.html")))
{
$filename = '';
}
# new auth code
if ($auth eq '') {
#if ($cookies{'qtsspassword'}) {
# $auth = $cookies{'qtsspassword'}->value;
#}
# can't use CGI library; parsing by hand
if (getCookie('qtsspassword')) {
$auth = getCookie('qtsspassword');
}
}
else {
$auth = encodeBase64("$username:$auth");
}
$authheader = "Authorization: Basic $auth\r\n";
$theAction = $query->{'action'};
$wasAuth = 1;
# fake a found tag to force authentication before performing an action
if (($theAction ne '') && !($nonAuthenticatedActions =~ m/\|$theAction\|/o)) {
foundTag(' name="qtssSvrDefaultDNSName"', '', '/');
if ($wasAuth <= 0) {
undef($query);
undef($qs);
return 0;
}
}
# run the action if there is one
PerformAction();
# hack for QT Broadcaster library on Mac OS X Only
if ($filename eq 'broadcaster_settings.html') {
if (!(-e '/Applications/QuickTime Broadcaster.app')) {
my %messages = %$messageHash;
$confirmMessage = $messages{'QTBErrNotInstalledText'};
$filename = 'welcome.html';
}
else {
my $result = ConnectToBroadcaster(0);
if ($result == 0) { # couldn't connect to broadcaster
$filename = 'start_broadcaster.html';
}
elsif ($result == (-1)) {
$filename = 'restart_broadcaster.html';
}
}
}
if ($confirmMessage ne '') { # if we're confirming a save, then do a redirect from the post operation.
if ($confirmMessage eq 'redirect') {
$confirmMessage = '';
}
else {
$confirmMessage =~ s/\s/%20/g;
$confirmMessage =~ s/&/%26/g;
}
&cgilib::PrintRedirectHeader($ENV{"SERVER_SOFTWARE"}, "/parse_xml.cgi?filename=$filename&confirmMessage=$confirmMessage");
return 0;
}
else {
$confirmMessage = $query->{'confirmMessage'};
chdir($ENV{"SERVER_ROOT"});
# default here
if (($filename eq '') or (($filename eq 'login.html') and ($query->{'action'} eq 'login'))) {
$filename = "frameset.html";
}
if ($templatefile eq '') {
$templatefile = "template.html";
}
#prevent source code revelation
if (!($filename =~ m/\.html$/)) {
die "Can't access HTML file '$filename'!";
}
#prevent windows ports from being opened
#aux, con, prn, com*, lpt?, nul
$foundFilename = 0;
opendir(FILEDIR, $ENV{"SERVER_ROOT"}) or die "Can't access HTML file '$filename'!";
while (defined($subpath = readdir(FILEDIR))) {
$foundFilename = 1 if $subpath eq $filename;
}
die "Can't access HTML file '$filename'!" if $foundFilename == 0;
$text = '';
$templatetext = '';
if (!(-e "$filename")) {
die "Can't access HTML file '$filename'!";
}
open(HTMLFILE, $filename) or die "Can't open HTML file '$filename'!";
# read the entire file into
while ($line = <HTMLFILE>) {
$text .= $line;
}
# we're done with the file; now close it
close(HTMLFILE);
# if the template contains the <bodytext/> tag, replace it with the body text from the file
if ($templatetext =~ /<bodytext\/>/gix) {
$templatetext =~ s/<bodytext\/>/$text/gix;
$text = $templatetext;
}
# parse the tags in the file's text
$text = parseTags($text);
if ($wasAuth <= 0) {
undef($query);
undef($qs);
return 0;
}
# used to be makeSecureRoot()
if ($^O ne "MSWin32") {
chroot($ENV{"SERVER_ROOT"});
die "Can't open HTML file '$filename!'" if (!(-e $ENV{"SERVER_ROOT"}.'/'.$filename));
}
if (($^O eq "MSWin32") && &adminprotolib::CheckIfForbidden($ENV{"SERVER_ROOT"}, $filename)) {
die "Can't open HTML file '$filename'!";
}
open(HTMLFILE, $filename) or die "Can't open HTML file '$filename'!";
close(HTMLFILE);
# give them a new cookie unless we have a better plan for them
if ($cookie eq '') {
$cookie = 'qtsspassword='.getCookie('qtsspassword').'; path=/';
}
# CGI programs must print their own HTTP response headers
&cgilib::PrintOKTextHeader($servername, $cookie);
#print the replaced HTML
print $text;
}
# done!
undef($query);
undef($qs);
return 0;