M = $MessageController; else $M = new MessageController(new TransmissionController); $this->Preferences = $Preferences; } private function Error($ErrorString) { $this->LastError = $ErrorString; return false; } public function GetError() { return $this->LastError; } /* public GetInitialSettings() * Get the initial settings for the web client (up/down speed etc) * * @return array $Result */ public function GetInitialSettings() { $Result = array(); $AutoStart = $this->M->GetAutoStart(); $Result['auto_start'] = $AutoStart[1]; $DownloadLocation = $this->M->GetDefaultDirectory(); $Result['download_location'] = $DownloadLocation[1]; $Port = $this->M->GetPort(); $Result['port'] = $Port[1]; $Encryption = $this->M->GetEncryption(); $Result['encryption'] = $Encryption[1]; $Result = array_merge($Result, $this->Preferences->GetAllPreferences()); // Down/Up rate is a bit fiddly - remember the last up/down speed // if it's not set by transmission $DownloadRate = $this->M->GetDownloadLimit(); if (isset($DownloadRate[1]) && intval($DownloadRate[1]) >= 0) { $Result['download_rate'] = $DownloadRate[1]; $Result['limit_download'] = true; } $UploadRate = $this->M->GetUploadLimit(); if (isset($UploadRate[1]) && intval($UploadRate[1]) >= 0) { $Result['upload_rate'] = $UploadRate[1]; $Result['limit_upload'] = true; } if (is_null($Result['download_rate'])) { $Result['download_rate'] = 0; $Result['limit_download'] = false; } if (is_null($Result['upload_rate'])) { $Result['upload_rate'] = 0; $Result['limit_upload'] = false; } return json_encode($Result); } /* public savePrefs() * save the POSTed preferences for the web client (up/down speed etc) * */ public function savePrefs() { $Prefs = $_POST; // Make sure the download directory exists if (! is_dir($Prefs['download_location'])) { return $this->Error("The download directory doesn't exist."); } // The checkbox-based prefs won't be passed if they're not selected if (! array_key_exists('auto_start', $Prefs)) { $Prefs['auto_start'] = false; } if (! array_key_exists('limit_download', $Prefs)) { $Prefs['limit_download'] = false; } if (! array_key_exists('limit_upload', $Prefs)) { $Prefs['limit_upload'] = false; } foreach ($Prefs as $Key=>$Value) { // Checkboxes pass selected state as 'on' if ($Value == 'on') { $Prefs[$Key] = true; } // Make sure 'rate' prefs are stored as ints if (strpos($Key, 'rate') !== false) { $Prefs[$Key] = intval($Value); } } // Set any daemon-specific settings $this->M->SetAutoStart(intval($Prefs['auto_start'])); unset($Prefs['auto_start']); $this->M->SetPort(intval($Prefs['port'])); unset($Prefs['port']); $this->M->SetDefaultDirectory($Prefs['download_location']); unset($Prefs['download_location']); $Encryption = ($Prefs['encryption'] == 1) ? EncryptionRequired : EncryptionPreferred; $this->M->SetEncryption($Encryption); unset($Prefs['encryption']); foreach ($Prefs as $Key=>$Value) { $this->Preferences->SetPreference($Key, $Value); } if ($Prefs['limit_download']) { $this->M->SetDownloadLimit($Prefs['download_rate']); } else { $this->M->SetDownloadLimit(-1); } if ($Prefs['limit_upload']) { $this->M->SetUploadLimit($Prefs['upload_rate']); } else { $this->M->SetUploadLimit(-1); } return true; } /* public TorrentSort((array) $Torrents, [(string) $SortMethod, [(int) $SortOrder]]) * Sorts a two-dimensional array * Ex. TorrentSort($TorrentsInArray, 'name', SORT_DESC) * * Valid sort options are SORT_ASC and SORT_DESC * Do not attempt to sort using an array as the method. (EG. 'trackers' or 'files') */ public function TorrentSort(&$Torrents, $SortMethod = 'name', $SortOrder = SORT_ASC) { if (count($Torrents) > 0) { $SortCriteria = array(); foreach ($Torrents as $TorrentID => $TorrentInfo) { if ($SortMethod == SortByTracker && isset($TorrentInfo[$SortMethod]['address'])) { $SortCriteria[$TorrentID] = strtolower($TorrentInfo[$SortMethod]['address']); } else { $SortCriteria[$TorrentID] = strtolower($TorrentInfo[$SortMethod]); } // Need to convert the criteria to lower case if it's a string to sort case-insensitively if (is_string($SortCriteria[$TorrentID])) { $SortCriteria[$TorrentID] = strtolower($SortCriteria[$TorrentID]); } } $SortType = SORT_STRING; if ($SortMethod == SortByCompleted) { $SortType = SORT_NUMERIC; } array_multisort($SortCriteria, $SortOrder, $SortType, $Torrents); } } /* public MergeArraysById((array) $Array1, (array) $Array2) * Merges two arrays by id ($Array1[0]['id']) * Used to merge two arrays of torrents into one. */ public function MergeArraysById($Array1, $Array2) { foreach ($Array1 as $Key => $Value) $NewArray1[$Value['id']] = $Array1[$Key]; foreach ($Array2 as $Key => $Value) $NewArray2[$Value['id']] = $Array2[$Key]; asort($NewArray1, SORT_ASC); asort($NewArray2, SORT_ASC); foreach ($NewArray1 as $Key => $Value) { unset($NewArray2[$Key]['id']); $NewArray[$Key] = array_merge_recursive($NewArray1[$Key], $NewArray2[$Key]); } return $NewArray; } /* public function setDownloadRate([(integer) $Rate]) * Set the maximum download rate for the daemon * Ex. setDownloadRate(5) * * @access public * @param integer $Rate Maximum download rate * @return void */ public function setDownloadRate($Rate = -1) { $this->M->SetDownloadLimit(intval($Rate)); if ($Rate == -1) { $this->Preferences->SetPreference('limit_download', false); } else { $this->Preferences->SetPreference('download_rate', intval($Rate)); } } /* public function setUploadRate([(integer) $Rate]) * Set the maximum upload rate for the daemon * Ex. setUploadRate(5) * * @access public * @param integer $Rate Maximum upload rate * @return void */ public function setUploadRate($Rate = -1) { $this->M->SetUploadLimit(intval($Rate)); if ($Rate == -1) { $this->Preferences->SetPreference('limit_upload', false); } else { $this->Preferences->SetPreference('upload_rate', intval($Rate)); } } /* public function AddTorrentByUpload((string) $FormName, [(string) $Directory]) * Upload a torrent to the daemon * * @access public * @param string $FormName Name of the upload form * @param string $Directory Directory to download to * @return void */ public function AddTorrentByUpload($FormName, $Directory = null) { if (! $Directory) { $Response = $this->M->GetDefaultDirectory(); $Directory = $Response[1]; } if (!is_uploaded_file($_FILES[$FormName]['tmp_name'])) return $this->Error('No file uploaded'); else if (!is_dir($Directory)) return $this->Error("The download directory doesn't exist. Please check your preferences."); else { $parts = pathinfo($_FILES[$FormName]['name']); if ($parts['extension'] != 'torrent') { return $this->Error('Uploaded file was not a .torrent file'); } else { $result = $this->M->AddFileDetailed(file_get_contents($_FILES[$FormName]['tmp_name']), $Directory); // Daemon and Transmission.app return different results after adding torrents if (isset($result[1][0]['id'])) { $result[0] = 'succeeded'; } return $result; } } } /* public function AddTorrentByURL((string) $URL, [(string) $Directory]) * Upload a torrent to the daemon by specifying a URL * * @access public * @param string $URL URL where the .torrent file is * @param string $Directory Directory to download to * @return void */ public function AddTorrentByURL($URL, $Directory = null) { if (!$Directory) { $Response = $this->M->GetDefaultDirectory(); $Directory = $Response[1]; } $result = $this->M->AddFileDetailed(file_get_contents($URL), $Directory); // Daemon and Transmission.app return different results after adding torrents if (isset($result[1][0]['id'])) { $result[0] = 'succeeded'; } return $result; } /* public function removeTorrents([(string) $JsonArray], [(array)$InfoFields], [(array)$status_fields]) * Removes a list of torrents, and returns an JSON array of torrent ids for the interface to remove * Ex. removeTorrents([1,2,3]) * * @access public * @param string $JsonArray Array of torrent IDs to remove * @return string $Result Array of torrent IDs for the interface to remove */ public function removeTorrents($JsonArray = "[]") { $TorrentIdList = json_decode($JsonArray); if (count($TorrentIdList) == 0) { $this->M->RemoveAllTorrents(); } else { $this->M->RemoveTorrents($TorrentIdList); } return $JsonArray; } /* public function resumeTorrents([(string) $JsonArray]) * Starts a list of torrents, and returns an JSON array of torrent data * Ex. resumeTorrents([1,2,3]) * * @access public * @param string $JsonArray Array of torrent IDs to start * @return void */ public function resumeTorrents($JsonArray = "[]") { $TorrentIdList = json_decode($JsonArray); if (count($TorrentIdList) == 0) { $this->M->StartAllTorrents(); } else { $this->M->StartTorrents($TorrentIdList); } } /* public function pauseTorrents([(string) $JsonArray]) * Pauses a list of torrents, and returns an JSON array of torrent data * Ex. pauseTorrents([1,2,3]) * * @access public * @param string $JsonArray Array of torrent IDs to pause * @return void */ public function pauseTorrents($JsonArray = "[]") { $TorrentIdList = json_decode($JsonArray); if (count($TorrentIdList) == 0) { $this->M->StopAllTorrents(); } else { $this->M->StopTorrents($TorrentIdList); } } /* public function getTorrentData([(array)$InfoFields], [(array)$status_fields], [(array)$IdList]) * Returns a JSON array of torrent data for the specified torrent-ids * Ex. getTorrentData(array(1,2,3)) * * @access public * @param array $InfoFields Array of torrent info fields to return * @param array $status_fields Array of torrent status fields to return * @param array $IdList Array of torrent IDs to get data about * @return string $Result JSON array of torrent data */ public function getTorrentData($InfoFields = array(), $status_fields = array(), $IdList = array()) { $TorrentListData = array(); $Torrent_status_data = array(); // If no ids are specified, get a list of all torrent IDs if (count($IdList) == 0) { $TempIdList = $this->M->GetInfoAll('id'); $TempIdList = $TempIdList[1]; $IdList = array(); foreach ($TempIdList as $Row) { $IdList[] = (int) $Row['id']; } } $Result = array(); foreach ($IdList as $Id) { $TorrentListData = $this->M->GetInfo($Id, $InfoFields); $Torrent_status_data = $this->M->GetStatus($Id, $status_fields); $Torrent_data = $this->mergeTorrentData($TorrentListData, $Torrent_status_data); array_push($Result, $Torrent_data[0]); } return json_encode($Result); } /* public function filterTorrents([(array)$InfoFields], [(array)$StatusFields], [(string)$FilterType], [(string)$sortMethod], [(string)$sortDirection], [(string)$Search]) * Returns a JSON array of torrent data for the specified filter type * Ex. filterTorrents(FilterSeeding) * * @access public * @param array $InfoFields Array of torrent info fields to return * @param array $StatusFields Array of torrent status fields to return * @param array $FilterType Type of torrents to return (FilterAll, FilterDownloading, FilterSeeding, FilterPaused) * @param string $sortMethod Method to sort the torrents (name, progress etc) * @param string $sortDirection Direction to sort the torrents (SortAscending or SortDescending) * @param string $Search Only return torrents whose name contains the search string * @return string $Result JSON array of torrent data */ public function filterTorrents( $InfoFields = array(), $StatusFields = array(), $FilterType = FilterAll, $sortMethod = SortByQueueOrder, $sortDirection = SortAscending, $Search = '') { // First, need to get the IDs of all the torrents that match this type // Need to look through all the torrents & figure out which ones we want // Is there an easier way to do this? $TempTorrentList = $this->mergeTorrentData( $this->M->GetInfoAll('id'), $this->M->GetStatusAll('state', 'download-speed', 'upload-speed') ); $IdList = array(); $TotalDownloadRate = 0; $TotalUploadRate = 0; foreach ($TempTorrentList as $Row) { $TotalDownloadRate += $Row['download_speed']; $TotalUploadRate += $Row['upload_speed']; if ($FilterType == $Row['state'] || $FilterType == FilterAll) { $IdList[] = (int) $Row['id']; } // Add the torrent ID if we have a match if ($includeTorrent == true) { $IdList[] = (int) $Row['id']; } } $Result = array(); foreach ($IdList as $Id) { $TorrentInfoData = $this->M->GetInfo($Id, $InfoFields); $TorrentStatusData = $this->M->GetStatus($Id, $StatusFields); $TorrentData = $this->mergeTorrentData($TorrentInfoData, $TorrentStatusData); // Set 'completed' as a percentage $TorrentData[0]['percent_completed'] = round($TorrentData[0]['completed'] / $TorrentData[0]['size'] * 100, 2); array_push($Result, $TorrentData[0]); } // Remember the current filter type $_SESSION['filterType'] = $FilterType; if ($sortMethod == SortByQueueOrder && $sortDirection == SortDescending) $Result = array_reverse($Result); else if ($sortMethod != SortByQueueOrder && $sortDirection == SortDescending) $this->TorrentSort($Result, $sortMethod, $SortOrder = SORT_DESC); else if ($sortMethod != SortByQueueOrder && $sortDirection == SortAscending) $this->TorrentSort($Result, $sortMethod, $SortOrder = SORT_ASC); // If the search string isn't empty, filter out any torrents // whose names don't include the string if ($Search != '') { foreach ($Result as $Key=>$Value) { if (stripos($Result[$Key]['name'], $Search) === false ) { unset($Result[$Key]); } } $Result = array_values($Result); } // Figure out the disk space remaining $Response = $this->M->GetDefaultDirectory(); $TotalSpace = disk_total_space($Response[1]); $FreeSpaceBytes = disk_free_space($Response[1]); $FreeSpacePercent = round($FreeSpaceBytes * 100 / $TotalSpace, 1); // Include total down and up rates in the result $Result = array( 'free_space_bytes' => $FreeSpaceBytes, 'free_space_percent' => $FreeSpacePercent, 'total_download_rate' => $TotalDownloadRate, 'total_upload_rate' => $TotalUploadRate, 'torrent_list' => $Result ); // Store these settings for the future $this->Preferences->SetPreference('filter', $FilterType); $this->Preferences->SetPreference('sort_method', $sortMethod); $this->Preferences->SetPreference('sort_direction', $sortDirection); return json_encode($Result); } /* private function mergeTorrentData((array) $TorrentListData, (array) $Torrent_status_data) * Merge the contents of the torrent data and status arrays by torrent-id into a single array * Ex. getTorrentData(array(1,2,3)) * * @access private * @param array $TorrentListData Array of basic torrent data * @param array $Torrent_status_data Array of torrent status data * @return array $Result merged torrent data */ private function mergeTorrentData($TorrentListData, $Torrent_status_data) { $Result = array(); foreach ($TorrentListData[1] as $Torrent) : $Result[$Torrent['id']] = array(); foreach ($Torrent as $Key => $Value) : $Key = str_replace('-', '_', $Key); $Result[$Torrent['id']][$Key] = $Value; endforeach; endforeach; foreach ($Torrent_status_data[1] as $Torrent) : foreach ($Torrent as $Key => $Value) : $Key = str_replace('-', '_', $Key); $Result[$Torrent['id']][$Key] = $Value; endforeach; endforeach; // Not interested in the keys anymore - only needed them for mapping return array_values($Result); } } ?>