* * @author Double Bastion LLC * * @license GNU AGPL version 3 or any later version * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE * License as published by the Free Software Foundation; either * version 3 of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU AFFERO GENERAL PUBLIC LICENSE for more details. * * You should have received a copy of the GNU Affero General Public * License along with this program. If not, see . * */ declare(strict_types=1); namespace OCA\PaxFax\Controller; use OCP\AppFramework\ApiController; use OCP\IRequest; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; use OCP\IUserSession; use OCP\AppFramework\Controller; use OCP\Files\IAppData; use OCA\PaxFax\Service\PaxfaxService; use OCP\AppFramework\App; use OCP\Files\NotPermittedException; use OCP\Files\Folder; use OC\Files\Filesystem; use OC\Files\View; use \ReflectionClass; use OCP\Notification; use OCP\Notification\INotification; use OCP\Notification\IManager; use OCP\Notification\IAction; use \DateTime; use Phaxio; use Phaxio\OperationResult; use Phaxio\Error\AuthenticationException; use Phaxio\Error\NotFoundException; use Phaxio\Error\InvalidRequestException; use Phaxio\Error\RateLimitException; use Phaxio\Error\APIConnectionException; use Phaxio\Error\GeneralException; class AuthorApiController extends ApiController { private $service; private $userId; private $folder; private $filesystem; private $view; private $userSession; public function __construct($appName, IRequest $request, IUserSession $userSession, PaxfaxService $service, Folder $folder, Filesystem $filesystem, $userId, View $view) { parent::__construct( $appName, $request, 'PUT, POST, GET, DELETE, PATCH', 'Authorization, Content-Type, Accept', 1728000); $this->service = $service; $this->userId = $userId; $this->folder = $folder; $this->filesystem = $filesystem; $this->view = $view; $this->userSession = $userSession; } /** * @NoAdminRequired */ public function object_to_array($obj) { if(is_object($obj)) $obj = (array)$this->dismount($obj); if(is_array($obj)) { $new = array(); foreach($obj as $key => $val) { $new[$key] = $this->object_to_array($val); } } else $new = $obj; return $new; } /** * @NoAdminRequired */ public function dismount($object) { $reflectionClass = new ReflectionClass(get_class($object)); $array = array(); foreach ($reflectionClass->getProperties() as $property) { $property->setAccessible(true); $array[$property->getName()] = $property->getValue($object); $property->setAccessible(false); } return $array; } /** * @NoAdminRequired */ public function isValidCallbackRequest($token, $url = null, $postParameters = null, $uploadedFiles = null, $signature = null) { if (!$url) { $url = $_SERVER['REQUEST_SCHEME'] . "://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; } if (!$postParameters) { $postParameters = $_REQUEST; } if (!$uploadedFiles) { $uploadedFiles = $_FILES; } if (!$signature) { $signature = $_SERVER['HTTP_X_PHAXIO_SIGNATURE']; } // Sort the array by keys ksort($postParameters); // Append the data array to the url string, with no delimiters foreach ($postParameters as $key => $value) { $url .= $key . $value; } foreach ($uploadedFiles as $key => $value) { $url .= $key . sha1_file($value['tmp_name']); } $hmac = hash_hmac("sha1", $url, $token); return $signature == $hmac; } /** * @NoAdminRequired * @NoCSRFRequired */ public function receivefaxphaxio() { $phaxiosignature = $_SERVER['HTTP_X_PHAXIO_SIGNATURE']; $thisapicred = $this->service->getapicredentials($this->userId); $phaxiowhtoken = $thisapicred[2]; $phaxiorecURL = $thisapicred[3]; // Verify Phaxio's signature $signverify = $this->isValidCallbackRequest($phaxiowhtoken, $phaxiorecURL, null, null, $phaxiosignature); if ($signverify) { $fileContent = file_get_contents($_FILES['file']['tmp_name']); $fileNameinit = $_FILES['file']['name']; $fldate = date("Y-m-d_H-i-s_").gettimeofday()["usec"]; $gmtind = "UTC " . date('P'); $flmsdateinit = date("Y-m-d H:i:s"); $flmsdate = $flmsdateinit . " " . $gmtind; $fileNamesec = array_reverse(explode(".", $fileNameinit)); $filenameext = $fileNamesec[0]; array_shift($fileNamesec); $fileName = implode("", $fileNamesec); $faxid = str_replace("Fax-", "", $fileName); $apiMode = 'live'; $apiKeys[$apiMode] = $thisapicred[0]; $apiSecrets[$apiMode] = $thisapicred[1]; $apiHost = 'https://api.phaxio.com/v2.1/'; $phaxio = new Phaxio($apiKeys[$apiMode], $apiSecrets[$apiMode], $apiHost); try { $phaxioresultreq = $phaxio->doRequest("GET", 'faxes/' . $faxid); $fromnmbrtoarr = $this->object_to_array($phaxioresultreq); $phaxiofromraw = $fromnmbrtoarr['data']['from_number']; $phaxiotoraw = $fromnmbrtoarr['data']['to_number']; $phaxiofromnumber = str_replace("+", "", $phaxiofromraw); $phaxiotonumber = str_replace("+", "", $phaxiotoraw); $errortype = 'there are no errors'; } catch (InvalidRequestException $e) { $phaxiofromnumber = 'null'; $errortype = 'invalid request error'; } catch (AuthenticationException $e) { $phaxiofromnumber = 'null'; $errortype = 'authentication error'; } catch (APIConnectionException $e) { $phaxiofromnumber = 'null'; $errortype = 'API connection error'; } catch (RateLimitException $e) { $phaxiofromnumber = 'null'; $errortype = 'rate limit error'; } catch (NotFoundException $e) { $phaxiofromnumber = 'null'; $errortype = 'not found error'; } catch (GeneralException $e) { $phaxiofromnumber = 'null'; $errortype = 'undefined error'; } if ($this->folder->nodeExists('Pax_Fax/faxes_received') == false) { $this->folder->newFolder('Pax_Fax/faxes_received'); } if ($this->folder->nodeExists('Pax_Fax/faxes_received_failed') == false) { $this->folder->newFolder('Pax_Fax/faxes_received_failed'); } $targetfile = "/Pax_Fax/faxes_received/" . $fileName . "_" . $phaxiofromnumber . "_" . $phaxiotonumber . "_" . $fldate . "." . $filenameext; $target = $this->folder->newFile($targetfile); $target->putContent($fileContent); // Move failed received faxes to the 'faxes_received_failed' folder if ($filenameext == '') { $newtargetfl = "/Pax_Fax/faxes_received_failed/" . $fileName . "_" . $phaxiofromnumber . "_" . $phaxiotonumber . "_" . $fldate . "." . $filenameext; $targetact = $this->folder->newFile($newtargetfl); $targetact->putContent($fileContent); $failedfl = "/Pax_Fax/faxes_received/" . $fileName . "_" . $phaxiofromnumber . "_" . $phaxiotonumber . "_" . $fldate . "." . $filenameext; $removefailed = $this->filesystem->unlink($failedfl); } // Send notifications $nameofhost = exec("hostname"); $getnextnotify = $thisapicred[4]; $useremailaddr = $thisapicred[5]; if ($filenameext != '') { $targetflname = $targetfile; $targettrim = "/Pax_Fax/faxes_received/"; $validfaxparam = "fax"; $setsubject = "New fax received"; } else { $targetflname = $newtargetfl; $targettrim = "/Pax_Fax/faxes_received_failed/"; $validfaxparam = "failed fax"; $setsubject = "New failed fax received"; } if ($useremailaddr != '') { $subject = $setsubject; $message = "Hello!

You have received a new ".$validfaxparam." on ".$flmsdate." .
The new ".$validfaxparam." file is '".$targetflname."' .

____________

Yours,
Pax Fax
A fax application for Nextcloud
Host: '".$nameofhost."'
"; $messagefin = chunk_split(base64_encode($message)); $headers = "MIME-Version: 1.0" . "\r\n"; $headers .= "Content-type: text/html; charset=UTF-8" . "\r\n"; $headers .= "Content-Transfer-Encoding: base64" . "\r\n"; // Set the email sender $headers .= "From: " . $useremailaddr . "\r\n"; $headers .= "Reply-To: " . $useremailaddr . "\r\n"; mail($useremailaddr, $subject, $messagefin, $headers); } if ($getnextnotify != 0 ) { $notify = exec("php ./occ notification:generate ".$this->userId." 'Pax Fax has received a new fax !' -l 'The new fax can be found in the \"".$targettrim."\" folder.'"); } } else { return "access denied"; } } }