Browse code

added appinfo/info.xml appinfo/signature.json appinfo/routes.php CHANGELOG.txt templates/navigation/index.php templates/settings.php css/style.css js/settings.js js/sendfax.js lib/Controller/AuthorApiController.php lib/Controller/PaxfaxController.php lib/Service/PaxfaxService.php img/pax_fax_received_fax.png img/pax_fax_send_uploaded_file_as_fax.png l10n/en_GB.js l10n/en_US.js l10n/en_GB.json l10n/en_US.json lib/Migration/Version119Date20250425082914.php

DoubleBastionAdmin authored on 25/04/2025 06:06:16
Showing 19 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,81 @@
1
+======= CHANGELOG =======
2
+
3
+Versions:
4
+
5
+== 1.0.0 - 2022-1-27 ==
6
+* Initial release.
7
+
8
+== 1.0.1 - 2022-3-31 ==
9
+* Changed presentation text.
10
+
11
+== 1.0.2 - 2022-4-11 ==
12
+* Respect custom 'datadirectory'.
13
+* Fixed received/sent faxes list not shown in the right hand pane when clicking the 'Received Faxes/Sent Faxes' button, while using Apache as a web server.
14
+* Fixed error when uploading pdf files, while using Apache as a web server.
15
+
16
+== 1.0.3 - 2022-4-14 ==
17
+* Changed the way the app gets the timezone.
18
+
19
+== 1.0.4 - 2022-4-29 ==
20
+* Specified how usernames containing an @ can be included in the callback URL, on the Settings page.
21
+* Adjusted pdf files paths, so that uploaded pdf files can be previewed when Nextcloud is served on a subdomain or on a subdirectory, by Nginx or by Apache. 
22
+
23
+== 1.0.5 - 2022-5-10 ==
24
+* Changed syntax of SQL queries and of encryption function.
25
+* Modified file paths to match changes in Nextcloud 24.
26
+* Text change on Settings page.
27
+
28
+== 1.0.6 - 2022-9-3 ==
29
+* Solved issue with viewing images picked from Nextcloud.
30
+* Small text changes on navigation pane.
31
+* Minor CSS modifications.
32
+
33
+== 1.0.7 - 2022-9-22 ==
34
+* Changed presentation text and text on Settings page.
35
+
36
+== 1.0.8 - 2022-10-27 ==
37
+* Changed CSS settings to match the modifications introduced in Nextcloud 25.
38
+
39
+== 1.0.9 - 2022-12-3 ==
40
+* Added support for dark themes.
41
+
42
+== 1.1.0 - 2023-3-22 ==
43
+* Fixed error when removing files in the 'temp_files' directory.
44
+* Renounced disabling the buttons 'Received Faxes', 'Sent Faxes', 'Failed Received Faxes' and 'Failed Sent Faxes' after successfull fax sending.
45
+
46
+== 1.1.1 - 2023-5-31 ==
47
+* Made app available for Nextcloud 26.
48
+
49
+== 1.1.2 - 2023-10-30 ==
50
+* Marked the app as compatible with Nextcloud 27.
51
+* Changed app presentation text.
52
+
53
+== 1.1.3 - 2023-11-2 ==
54
+* Changed how the app sends notifications for incoming faxes.
55
+
56
+== 1.1.4 - 2024-1-11 ==
57
+* Added the 'fonts' directory and stored the 'Open Sans' and 'Inter' fonts inside it.
58
+* Made small CSS changes.
59
+* Marked the app as compatible with Nextcloud 28.
60
+
61
+== 1.1.5 - 2024-1-12 ==
62
+* Fixed not being able to see the upper bar with the close button when viewing pdf files.
63
+* Added more screenshots to presentation page.
64
+
65
+== 1.1.6 - 2024-05-27 ==
66
+* Changed 'notnull' to false for 4 columns.
67
+* Made small text changes on the settings page.
68
+* Marked the app as compatible with Nextcloud 29.
69
+
70
+== 1.1.7 - 2024-10-10 ==
71
+* Fixed log warning related to path of notification icon.
72
+* Made small CSS changes.
73
+* Marked the app as compatible with Nextcloud 30.
74
+
75
+== 1.1.8 - 2025-03-10 ==
76
+* Modified how current user is obtained.
77
+* Verified compatibility with Nextcloud 31 and marked the app as compatible.
78
+
79
+== 1.1.9 - 2025-04-26 ==
80
+* Added support for Sinch's fax API.
81
+* Made minor text changes to information popups.
0 82
new file mode 100644
... ...
@@ -0,0 +1,83 @@
1
+<?xml version="1.0"?>
2
+<info xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
3
+      xsi:noNamespaceSchemaLocation="https://apps.nextcloud.com/schema/apps/info.xsd">
4
+    <id>pax_fax</id>
5
+    <name>Pax Fax</name>
6
+    <summary>A fax sending application</summary>
7
+    <description><![CDATA[
8
+This application allows sending and receiving faxes in Nextcloud. A Phaxio account and a real fax number acquired from Phaxio are needed. 
9
+Complete instructions on how to configure and use this application are detailed in the 'Admin documentation' linked on this page.
10
+          
11
+### Features:
12
+
13
+* 🚀 Multiple documents can be sent in one fax call (up to 20 separate files with a cumulative size of up to 20 MB).
14
+
15
+* 📠 A fax can be sent to multiple fax numbers at once (up to 15 different fax numbers).
16
+
17
+* 📄 Users can send as fax any document in any of the following formats: pdf, doc, docx, odt, jpeg/jpg, png, tiff/tif, txt, html.
18
+
19
+* 📰 All incoming faxes are received as pdf documents and stored in a Nextcloud folder.
20
+
21
+* 📧 Users receive notifications and (optionally) emails when new faxes arrive.
22
+
23
+* 🔍 All the sent and received faxes are stored in specific Nextcloud folders, so that they can be searched by caller/callee phone number or date.
24
+
25
+* 💻 When they want to send a fax, users can upload files from their computer or choose them directly from Nextcloud.
26
+
27
+* 🔏 Incoming fax requests are checked for authenticity and integrity by verifying Phaxio's signature.
28
+
29
+* 💵 Current Phaxio balance can be always checked by pressing a button on the left panel.
30
+
31
+* 💰 The only ongoing cost is $2 per month for a fax number located in USA or Canada, in a city chosen by the user. No contracts.
32
+
33
+* 💸 Straightforward pricing: $0.07 per sent/received page for faxes to/from USA and Canada and $0.1 per sent/received page for faxes to/from other countries.
34
+
35
+We have no affiliation with Phaxio.
36
+
37
+### Documentation
38
+
39
+* [Admin documentation](https://www.doublebastion.com/install-nextcloud/#install-pax-fax)
40
+
41
+### Donations
42
+
43
+* 🎁 [Donate](https://www.doublebastion.com/donations/)
44
+
45
+    ]]></description>
46
+    <version>1.1.9</version>
47
+    <licence>AGPL</licence>
48
+    <author homepage="https://www.doublebastion.com">Double Bastion LLC</author>
49
+    <namespace>PaxFax</namespace>
50
+	<documentation>
51
+		<admin>https://www.doublebastion.com/install-nextcloud/#install-pax-fax</admin>
52
+	</documentation>
53
+    <category>office</category>
54
+    <category>organization</category>
55
+
56
+    <website>https://www.doublebastion.com/pax-fax/</website>
57
+    <bugs>https://git.doublebastion.com/pax-fax/issues/develop</bugs>
58
+    <repository>https://git.doublebastion.com/pax-fax/develop/</repository>
59
+
60
+    <screenshot>https://git.doublebastion.com/pax-fax/raw/develop/img/pax_fax_received_fax.png</screenshot>
61
+    <screenshot>https://git.doublebastion.com/pax-fax/raw/develop/img/pax_fax_send_uploaded_file_as_fax.png</screenshot>
62
+    <screenshot>https://git.doublebastion.com/pax-fax/raw/develop/img/pax_fax_files_from_pc_and_nextcloud.png</screenshot>
63
+    <screenshot>https://git.doublebastion.com/pax-fax/raw/develop/img/pax_fax_received_faxes.png</screenshot>
64
+    <screenshot>https://git.doublebastion.com/pax-fax/raw/develop/img/pax_fax_sent_faxes.png</screenshot>
65
+                
66
+    <dependencies>
67
+            <nextcloud min-version="26" max-version="31" />
68
+    </dependencies>
69
+
70
+    <navigations>
71
+        <navigation>
72
+            <name>Pax Fax</name>
73
+            <route>pax_fax.page.index</route>
74
+            <order>103</order>
75
+            <icon>pax_fax.svg</icon>
76
+        </navigation>
77
+    </navigations>
78
+
79
+    <settings>
80
+            <personal>OCA\PaxFax\Settings\Personal</personal>
81
+            <personal-section>OCA\PaxFax\Settings\PersonalSection</personal-section>
82
+    </settings>
83
+</info>
0 84
new file mode 100644
... ...
@@ -0,0 +1,45 @@
1
+<?php
2
+/**
3
+ * @copyright 2021 Double Bastion LLC <www.doublebastion.com>
4
+ *
5
+ * @author Double Bastion LLC
6
+ *
7
+ * @license GNU AGPL version 3 or any later version
8
+ *
9
+ * This program is free software; you can redistribute it and/or
10
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
11
+ * License as published by the Free Software Foundation; either
12
+ * version 3 of the License, or any later version.
13
+ *
14
+ * This program is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
18
+ *
19
+ * You should have received a copy of the GNU Affero General Public
20
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
+ *
22
+ */
23
+
24
+declare(strict_types=1);
25
+
26
+return [
27
+  'routes' => [
28
+     // User views
29
+     ['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
30
+     ['name' => 'author_api#receivefaxphaxio', 'url' => '/api/recfaxphaxio', 'verb' => 'POST'],
31
+     ['name' => 'author_api#receivefaxsinch', 'url' => '/api/recfaxsinch', 'verb' => 'POST'],
32
+     ['name' => 'paxfax#getbalance', 'url' => '/user/getbalance', 'verb' => 'POST'],
33
+     ['name' => 'paxfax#getfaxnumbers', 'url' => '/user/getfaxnumbers', 'verb' => 'POST'],
34
+     ['name' => 'paxfax#cleantempdir', 'url' => '/user/cleantempdir', 'verb' => 'POST'],
35
+     ['name' => 'paxfax#uploadfile', 'url' => '/user/uploadfile', 'verb' => 'POST'],
36
+     ['name' => 'paxfax#pickfile', 'url' => '/user/pickfile', 'verb' => 'POST'],
37
+     ['name' => 'paxfax#removeupfile', 'url' => '/user/removeupfile', 'verb' => 'POST'],
38
+     ['name' => 'paxfax#getpickedfile', 'url' => '/user/getpickedfile', 'verb' => 'POST'],
39
+     ['name' => 'paxfax#sendfax', 'url' => '/user/sendfax', 'verb' => 'POST'],
40
+     ['name' => 'paxfax#sendfaxpicked', 'url' => '/user/sendfaxpicked', 'verb' => 'POST'],
41
+     // Settings
42
+     ['name' => 'paxfax#getsettings', 'url' => '/user/getsettings', 'verb' => 'GET'],
43
+     ['name' => 'paxfax#updatesettings', 'url' => '/user/updatesettings', 'verb' => 'PUT']
44
+  ]
45
+];
0 46
\ No newline at end of file
1 47
new file mode 100644
... ...
@@ -0,0 +1,156 @@
1
+{
2
+    "hashes": {
3
+        "CHANGELOG.txt": "8a1ce99f8ae7719426090da5cf88eb757168b6c96f89a91d4f88df00c459b177597ca7e71a808cc4c08ae85ddee097cbbe97235a97220bf0729c3d78ad9103f0",
4
+        "COPYING.txt": "a0a86214ea153fb07ff35ceec0848dd1703eae22de036a825efc8394e50f65e3044832f3b49cf7e45a39edc470bdf738abc36a3a78ca7df3a6e73c14eaef94a8",
5
+        "Contributors.txt": "36bb17a05cb65b7ce8faf6b601396a2ff9b2e99b159a3eac35f21107f0457fbcee645b53c97aab653eac8433e59ad774b521aaf4f4dfdf8470817e51636d1535",
6
+        "Phaxio\/composer.json": "15a73bed2e5760f4c4dd1fd60abf746cbd245830ba502884261e9a0b6202844a8a37936e60a2761c6cd94a3054ebdf0c791fb866e191797a9f08227c125f5e4c",
7
+        "Phaxio\/composer.lock": "a6366b124ebbd604e11245e4e01f2f3a6d2bb63bccb861bf2e275f7be7d84d3380447cd9b84afd9dd5da0258cdaa01cdbde0f67ca27f2494d60b9304b092d2f9",
8
+        "Phaxio\/vendor\/autoload.php": "4eeb7a390556c23bed27d39fa0e9921347ccd07a8116f373f1d9ec45e6be608ba526392b6392722fd0aca67b14c8365f45773c50d983218df51f2b221d225761",
9
+        "Phaxio\/vendor\/composer\/ClassLoader.php": "2b6fa585122ace1ba816410acbd8372cb75329917aae6363dbad48e396cca581452616e1386a2e445a8fbb0e461b988279103f4f89adf704bce7726f761abf0e",
10
+        "Phaxio\/vendor\/composer\/InstalledVersions.php": "d7273807c70dea77e8708d58a8368ac9e1cd03a952f5cca0202d469a76d13ae84e17152a52b17768e16f54b18a84963959031c32485166a46b425bb4852b8a2a",
11
+        "Phaxio\/vendor\/composer\/LICENSE": "f3bb64009f41a425df5a9bbab53490f0eb9b74fa8d6aaa2f57efb928edc4ffff330260666edeaa04a91fed708c3663371cf01b284f3a08d6698aaef7a23f355a",
12
+        "Phaxio\/vendor\/composer\/autoload_classmap.php": "38cb0fcac43c6563d0320769be34f7020cecc2d172100930fb5f77043fafae1e1d7467bf681996316e41bb5e5d71a159a02f2b88fa5e067a1fa7883f1f734c79",
13
+        "Phaxio\/vendor\/composer\/autoload_namespaces.php": "e94d2ac452dac5c0a46d259cb9c142ce02d424db8ecd680e16eb604636cbe7b1cff5ce75406b8c99d762952343abfde8a29c3611994c77fb15ad3c9a4d3737f8",
14
+        "Phaxio\/vendor\/composer\/autoload_psr4.php": "1d78c03bc79c82476a9b806cba84ce9067f3dd1a2565f5616f6bcdb0c2eae4ccee33e7267f78a636c9e02904253c024cef43ec01d789918294586d2a1b4654fb",
15
+        "Phaxio\/vendor\/composer\/autoload_real.php": "8e0c72be16830e95bdac7c33043d1ad5144a294dbc28d078563274f379d81e957b2edc400382abd517adc74c0d295ecb606701e4240f55a7303686f424f5432c",
16
+        "Phaxio\/vendor\/composer\/autoload_static.php": "c1abaf9518c87901439bbdba91b10c144ab4fa5263fa35bafba3d56143febc7d045fb281f8fea746e82279c74fe4b22e323a6857cd9fc1ec688e70212546845a",
17
+        "Phaxio\/vendor\/composer\/installed.json": "4cb36f28c497f8d506b8570c0894262a37e98c4327737ed67a963b1ecfa561625a10bf7322e9b0fab7e2401182cc6864e529458ac5d421d8658610479c73cb5e",
18
+        "Phaxio\/vendor\/composer\/installed.php": "2dc2f106f98921818677d17f135455d02ad3946f06dbf85cbecbbef387adbc0d4ffaa53b0fa18697130c53977cccb5a745e69ba3e539fc2ace74997430283a7d",
19
+        "Phaxio\/vendor\/composer\/platform_check.php": "03262b35b0226cd690c4e88d4ac19edfa911b51cd3b49589f6a7d19100a566ee3848d5afedafc68f4dbdf0c1580e98be4bb929195e9e23906fc14d542dc921a1",
20
+        "Phaxio\/vendor\/phaxio\/phaxio\/CHANGELOG": "2eff47994cc1ef1ff374ab0e6d63c6504518b2731149c200ed7aa0aa5ea13fef070a7408741426c1c384a298061bc4c53c3dd91ef8eb6c5e4f62894aee1a3206",
21
+        "Phaxio\/vendor\/phaxio\/phaxio\/LICENSE": "a2a7604f0909b0e4b282508198c8e525d239a18995574b54569abd07ba784e872af3757b2a0802e1a8430fcbfe8260eee8f508f3821f29b0fe95ccc7e44874a2",
22
+        "Phaxio\/vendor\/phaxio\/phaxio\/composer.json": "37a15063347f6997ccebacc48942110158f8fd682ac5eb5c58465e3562a9cad346228dec018841d28be3d6afd282f5dce978a22d778f77b75dda05e1cf6a4213",
23
+        "Phaxio\/vendor\/phaxio\/phaxio\/examples\/autoload.php": "fccd9008107c490da7808c70d27ea04f13ee3de4bde8291a69c3283ebf7b5efc0d0a440aaad0d68ebeadfe37241f924040c977dd0bc93a16b894638211bad1dd",
24
+        "Phaxio\/vendor\/phaxio\/phaxio\/examples\/cancelFax.php": "590564fdaaef85e7b72b49c31ddc0a5cd9ae70a5c452f1ce4b08f56bec1e19ae9f8c826fe179dd0c68127f96333ddab1faa3d652879e35d27ac5e4b422586c07",
25
+        "Phaxio\/vendor\/phaxio\/phaxio\/examples\/createPhaxCode.php": "8fd8fe39a97abc99afae8edc9363319bee3ef07841b91f0bc6f738d283a24b2e8e56f109ecd0b4d567e5da694abd4deae14008c1d247dd8690de7ad54e48238e",
26
+        "Phaxio\/vendor\/phaxio\/phaxio\/examples\/deleteFax.php": "0f14c0147950102848ed065c3ca3f12bb56fad382a35e42f77f0acf67ed491050054bbc43f3ee49a96895d3081156ddbdc7640f3f7d9a0fc7848d13bf4921107",
27
+        "Phaxio\/vendor\/phaxio\/phaxio\/examples\/downloadFaxDocument.php": "ee26536919405a2e5f4303c69cbaaa66d08eb946143f17dabc8636881b88cb08abdb56812d826424e756efa247dc1c6aeb585ad9f7bfaa21547d0827f4d2e934",
28
+        "Phaxio\/vendor\/phaxio\/phaxio\/examples\/downloadFaxThumbnail.php": "b581ab76492911decadad4357e6d1cba800394dea1dd0be3ebe925b43b41efc0005ec66707f52ec8a21bcba46f9be0626ff8d08e2686da35e690ebd13302b4db",
29
+        "Phaxio\/vendor\/phaxio\/phaxio\/examples\/files\/content.pdf": "515cdf6ba8271b7a17bd44e9458e28aa288cd9aee64db2daf721568d0eab1249d47243bfa6b2cf39563e848afa1f246453288682d16ddfd4a0a89c981424dbdc",
30
+        "Phaxio\/vendor\/phaxio\/phaxio\/examples\/files\/coverPage.html": "8c14d034bd830269ab9df374f6bff8261b4641d121e4c5806c0e923f744e5b0eab82504924e474f04b9218b166edddb5ad1dc42524c64a018e21e9c968f8160a",
31
+        "Phaxio\/vendor\/phaxio\/phaxio\/examples\/listFaxes.php": "4bd4e16ae654cd39df0f7b405537af034a48c4acee9107dec5fc7f5bb982c2b9cfd6ea030912f0190132664c80fad629bfebb1229d7650200d0ca096a5aabdfe",
32
+        "Phaxio\/vendor\/phaxio\/phaxio\/examples\/phaxio_config.php.temp": "1efc886fce5ea24e9a650a35c497d45b8bae47bc035c6ce4f58aa2abd78ba46585c0401d8e4cc34614d3521b234d12d539536bc9bfe78a9e980f97f92ff898f9",
33
+        "Phaxio\/vendor\/phaxio\/phaxio\/examples\/sendContentUrls.php": "f65f864142f8f856d504ddc89f37a570cb3f229563fdeb2a7a56d628c7f4d316c930cd0e4f944cea3c73c0349aba51340f9cf02a174fcdcb7dcf4823ecd4d3c7",
34
+        "Phaxio\/vendor\/phaxio\/phaxio\/examples\/sendFiles.php": "ae986282c3c75b8e0162bbe95bd08100ce4ec10af67cd536b763e674d9c21a8168948a5f2b1fc3efeb9fd9d9daf46645ffbf179e1e3166ff0060c4ee39edd593",
35
+        "Phaxio\/vendor\/phaxio\/phaxio\/examples\/sendFilesWithBatching.php": "5e4915fe1fb7fb1c916c776a962aff398ea8c0d3bb753fb0b6edd00ceea8374c8cdc6a528c1e36ee61368d072f8ef549c2ffc62ccff6057088b768d764fe5984",
36
+        "Phaxio\/vendor\/phaxio\/phaxio\/examples\/sendText.php": "914a594bdd09c08727c9f155945060212f6c03ecf920a9ffe3eeed9ed5ff35547e541a3bd18b242ef47ae356f2c1e55f74b8d790ca077950a07881ae926fa46e",
37
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio.php": "e13f967f4b54f99de59d91fe0dbcf8c653a388825fa1f84f76b391a839941586d38d215f63005fe4307a2a3658afaece45088c002de83f962bb1d936476e9b13",
38
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/AbstractResource.php": "48f68360a03312162d9aae7195345ba848216700f9a7d89f08d681d500d27af715af7d569aaab23b2426867519244d2cbec50fa3db7c8eee897bfd9e43aa30a8",
39
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/AbstractResourceCollection.php": "0365a3e8c6194b51633199d9123aa0789e2279f5b29455c1ae5feb0c01a7731d053ef5252d91f6aa62ac1a4726fa3b906ffffabf9e715f30f9aaa34780367aaa",
40
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/AbstractResources.php": "b22c82110e2f60cdf92c7546f1ec8e8039cb9f4b92298087290c9113698166e9ef7d25b9a2645809e0f2aceb3994e45f4c8904b1a2ca03cf00c05be8504df6bd",
41
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/Account.php": "aea5b414544a9c3c7797146c15c4f419d732225de824113ece7a089f26bbc99426f11e980fa7214e4a3065b8efcd1e32ac1d29ea82ebb1eff445e9d27ff6aac0",
42
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/Account\/Status.php": "678e00b88f00ce03ce1cdfacd7ff23608baa09f5298bdda06f834d73257b89ba60ced77df88c2604fcc828b5432f2bb7c13e0d5418674b76a5152a59138d8e35",
43
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/Error.php": "db0e1a32af83054c31662c26b30bef0ce125d0269a3b762ee231af524df152698814fd479db55833f5a7e580a83f6e823130b4b4e81e6635cbcfca796c8154c1",
44
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/Error\/APIConnectionException.php": "39411737aa1d7c4e8ac656908db977500fb3a5bc9a429e5367341525d010bb48c2785ec9eec0b7d84a244d21182cf0e0f635125a7aef96006a2222cb066ac353",
45
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/Error\/AuthenticationException.php": "50dc9337d0e0339547d74d49fb608cb9434ec645b16a283f2feef6959de9ebcd0bd0134c113188c8ee4fb06e21a981ed4274670eb0adc51634b1de8c4f3be8ad",
46
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/Error\/GeneralException.php": "d6d1d96f8ef2d89eff98814befa51b3f0f5a24a44611414c9bbeaf3046633f8a3b752d33b002738ddd5bbde167a1478f897a127e8ec90e710446ca53bf6a2af0",
47
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/Error\/InvalidRequestException.php": "64988a6943b848b3f74614c27a16c109af76e4cca9df497ee7066b4ccac0719e2665460337b1e03dcc9ebc7d469f0f670c45b680bdf327c8a3ffaecf4e872846",
48
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/Error\/NotFoundException.php": "cdbe663b94bd2fdef124570af93509a8080312b0ba13e8ac1664744d40a19c9701c35813da6b10f619c6ccd449ba863c012ef2613b24993e59ecb460dd901cf7",
49
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/Error\/RateLimitException.php": "583aebaa33f59f697795034ea4053919e7203218a6984516ad8ffca8a5eb85a7804a30414b33595016b48ca6b83b1926f5b3eefb4bf8bca5fd88ecf173f0e0d1",
50
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/Fax.php": "754cc2e5f039acfd3e6ee98311fb12519d83079bb8acfb21338a0ea175df1b53ae863a709c14e43ae1ef39eddc51bfcaaa577eb284d33da787e511c3abb56df0",
51
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/Fax\/File.php": "650cf3c1e6aabd535c13c09de0525d73e695f813f0c267008b7722e7a594b5a25f2156bcf6d9fc0828dc0869fa250c138f55256d8aee6a10d83569f33228ed5e",
52
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/FaxCollection.php": "cd04652b9ff7b19af3d53436ca45cb82db41b611df18473b52cc6eb6f5051ad8db34fe751cec891ab315032f6dd109fff6c430baef95aba11cfae10fc073d2ce",
53
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/Faxes.php": "2e1c9c7c78e80fd6efbd49820002c423560bc2fc32d15799b70e26b754a9e659ef61aa707846724c999e1f98ac82366cf57ea49b0ea101a6d825b5bcc80ca278",
54
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/OperationResult.php": "3e85b6a921303cd1e03bc67a79203446e59f76714eed5b468ced130a33fe4e37d6198ef07059fc1f1b8784115ff2084d67e0c3a44b2d7c9433158873c67d7cd9",
55
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/PhaxCode.php": "3999628fee6f6f8488e49b8a03a587186a78c20f0ea1a07a5f60455de9dcc8fee644aab86b1942dfeef3b5510de3fa6c71bdf8ee4f2724ddd60309bc09e07fc6",
56
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/PhaxCodes.php": "b4d3e68f7c69646cc7e740496173504c8d5ba5956ca43e556c4da1b472500c2937f8ae81fdf8598a7c96899f8e9e9570236cf290547b3a604b0873495a39c4af",
57
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/PhaxioPublic.php": "9dcb4a790708f552289c28e12de86a5be8af96c1383e079ca626aaba2dc0ae0ac1930c2cc32547d328c69867476746caa7a0c1e9af4b162cee8ea98637720749",
58
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/PhaxioPublic\/AreaCode.php": "e40391514dc3ac86040436625c8cc977177269d878f97f1f7a26f441b75899fc0ac5f124e82563be63998b5009261287a709630bd5feb7f58d1ca0aff4e799c8",
59
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/PhaxioPublic\/AreaCodeCollection.php": "36ef6b3a17eaf0bbb45cafd7bc63a387b028c55759e9650c597ed9ad4d98a6788a5c4f2c59055dacaa7ba5cd958f1d8e0811b53962c3b9ad51e96b26ca85e418",
60
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/PhaxioPublic\/AreaCodes.php": "59b42f33330ad1856d9ecc01588abdcf34080e770f32134cbbf207144d10e1b65c1182df7e39c11f6ba9381fe845715eefd6891cbe29ffc06a8ce2e4e20a3987",
61
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/PhaxioPublic\/Countries.php": "c3214a5af911c09a2be6de5446c02c6b262082a0cfca057e9a135dbd29631f00a75bfea3bb9181bea1dbe45a7238afd05510275822857031726002ba7d9f2118",
62
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/PhaxioPublic\/Country.php": "df81c4fd6eaf3d3fd82b090e481cef2c19e34cf532c16753ec909b36c38ac2e87efda4133d8322a512cd0a31d53421fdd2009e6f04be0119a31a90c30c690db5",
63
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/PhaxioPublic\/CountryCollection.php": "5457c89d54da2c2f6ff8ae907e8c7e21e7fa8197e05c6209d7924e2ac02e422002c6d92e434b45cefe79630532d2c80f1ddd7f4508c0867db637288bc32833c6",
64
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/PhoneNumber.php": "e8d578db0d72ff22b472c2ecbd58f6b90c06a581392dcb0281b8116dfda57d7fe43d33a212b79d6185276b69ec6c3dadc231603eedb62ded7bd695177baa7b50",
65
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/PhoneNumberCollection.php": "17e29c72a0a23bf39ab4aca4e77836f78a1a9b570cbece8837e479e2039f8bbf433fe9137c7f9f39e0de930f8eea3eccaf202e6e60cda6ca8fab25e5738af264",
66
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/PhoneNumbers.php": "0a196164d5abb4598c5f3e4eaf092e999aa2e6d097fa4d93c284757ce5c616d949f07e5a6e9a93f632f838551c5979d6517802243014131f2a6bd20bd64c0246",
67
+        "Phaxio\/vendor\/phaxio\/phaxio\/lib\/Phaxio\/StringUpload.php": "a8e15f97d3562d17375989d34ee31569ae2b7a684632bf64f209e61cac7198ec91cc6668e7be51e1d3cf6110a66e881b20e47d6eac0dd2dc6ba8404f04cd0423",
68
+        "README.md": "74f886b5e9f438413f0f891cea6b6b31d1c14386e87662b644cbabe274dea36beeb134bb52026d56a291e3ecf978611750c8d1824e875bb7e584c51347b58025",
69
+        "appinfo\/info.xml": "bd5bbfce55d66b4979891e9dfa27f2f9e821bf0937c42248db02f9fdd585e03667af15ee7c8c46246ad55f83c5161f608b009a2762e5556ca3c411f294fbdc96",
70
+        "appinfo\/routes.php": "072c53bcda93163053495caa94a90f19d19328cf7a6288579cbd4c05e1d1fc320854bed9378f6771fc96d4debd7b1a91615340365ba39639b5b7667dba67bc8c",
71
+        "css\/style.css": "ef65735f9ee7ab2200512a26f859557ee621d8a1acd897d6c7bd6d5eb24188d9fde2cf479d4ad232440b82518fd134bd87b1563e6e943479249e3cc5023fb6f9",
72
+        "fonts\/Apache_License_v2.0_Open_Sans.txt": "fdae7ed259455ca9fa45939e7f25cbb4de29831cda16d9151de25a5f6e9d9be43b053f4fd3b896026239fca77abce04f543d591c501ecf4ce18c854bc0a51660",
73
+        "fonts\/Inter-Bold.woff": "f34ed611dc0ba6e7c0bf7242bad7c02e09f208bfbdd21d6649ebf9b41bc06696d8856707851944786c80c718df455e619caab170c70bfe97ba2043d651d4532e",
74
+        "fonts\/Inter-Bold.woff2": "736b4aaf8a2de0c17fbd5396a338577227326f078ee0646072d851d328b58a8058989af8735ac073f935b05f291d9310797d95c963e5e3ff0ea61a87f21c9da5",
75
+        "fonts\/Inter-BoldItalic.woff": "619e398d37249fae96ba0deb06fcf5dab215ba888740024287e2c8f1278b33273124cd5b9ea8f7525a17657566b72a1661b688ca670bc068ca6ddf466b7e7ffe",
76
+        "fonts\/Inter-BoldItalic.woff2": "a24bdb558a9b26fbe7631d6cf90b8db8f5f0164c3c814a2971fb7d45e807b0856454893bbd0d5bd0d9f060689f2be5f5bb1b69e4bdea0293d1122e13ad28e96f",
77
+        "fonts\/Inter-ExtraBold.woff": "d527e43747abed5a13d49a70c8db7ef39aab35ab0accfe1e3f6e037f685e08d2e5f7552b40c75d4faecc0e7e1227e97c563af093afefb57f2b6be9c783a85b0e",
78
+        "fonts\/Inter-ExtraBold.woff2": "20a22b0255b2bdc8f30ca7d59f20b3e2dfcbeaa39f035ccbeff40b57ad77d616dee1c41eebe30e1fab53fbb7ab4cc9f842cd13539ef34a680f6dd43441a3f2f6",
79
+        "fonts\/Inter-ExtraBoldItalic.woff": "6fc1da8183d8b131d670ff5a89593967e4666436b37fcf08c4d99d8532654558f281bb8c20c92be8c5e3d6b34e05c7aad182f4c9a413f8bb1c11ef600b3c524b",
80
+        "fonts\/Inter-ExtraBoldItalic.woff2": "3a8c4a113a4308ac9a57e7ad75060e0f08a1dd8638c29c1190f86929363b755ed2de66e4c11d3164a0a1fb1e6e35865bf786a295d3e0ad561c4a94cc8cbec6db",
81
+        "fonts\/Inter-Italic.woff": "72defeb5040f6375683dba41d4ce43654fdbae4f64aea88b01feb023b3e894c278c8a8c7e5583b6d83d980495ca0d5afa5ec7e1bfcc731be08d3dbe1b8b3f348",
82
+        "fonts\/Inter-Italic.woff2": "b128da83c81fe4a28026dc0a2a75c7920f37d4e04d6d6bde4e60b3a9527dbff04ff0ebc8b300874db9bd90036a41a52f4c9d82eb2f78fb8e99a35bb04defa1c2",
83
+        "fonts\/Inter-Medium.woff": "1f7c25aeb1ed534a106254fdba6bf59dfa03542f813489dca31fe067e2a22ab9549babb48af4cd465ab3ef0ef2f4b0f46532efcc8aae8942ad2cf98d0a5a4a3f",
84
+        "fonts\/Inter-Medium.woff2": "ce94d1a0cea81d42546ebc0247403b02c6fae24d3afba618cf658436734557a8b2b8ebed54319a9f66b233bd224da3685f848470866de63a144c8c28070491d4",
85
+        "fonts\/Inter-MediumItalic.woff": "7b7bef9c7a7717c6d52d619059e5ec258b537f538ada38325c2c7bfa4968ff53109bc9ee17a57819ef37d0a145a973f4a7c8e4d8d09e71d3faa4d0fe14cbf487",
86
+        "fonts\/Inter-MediumItalic.woff2": "4a2c5dc8c2ece82489e63b16cd8b1536b8f5502cf8f93307b0c71c6d54594a28ec2a80b8e58dfbbcc1d38a51aa8dd6d6fa025aed2cdc1429a462745a2bf2d414",
87
+        "fonts\/Inter-Regular.woff": "e37409956d19653617af32af2f99f4038c815a3664f2dcb2fef5e6a1a7345c78aaac3badc2ae499b1423514076ad676ab4bd5d936ef9d159899a6f668d991e4c",
88
+        "fonts\/Inter-Regular.woff2": "731924aedf31d6ef8fcd57a3b74182331ec7ba743d64033d8912d350ba98fd5b1942decaa4268f4dc925be2ed711c71a77200b2497bec10cae499b452fb27138",
89
+        "fonts\/Inter-SemiBold.woff": "684602b1f45bf7a9ca5ea6b1aca2cc2046e07ac79eb63b920099463f25866f50cca77ca253f16078d3a6e781ca23b964a69c87389621fa101d5cfffdb292d132",
90
+        "fonts\/Inter-SemiBold.woff2": "12b7680eccc54f56f800ac3ea4eff0490f515911d0fc83f99f62fa0f72d848155c8a7186918301a372d0fd0238d8093109c7b9b3c05168058e3cb47b1f7216ae",
91
+        "fonts\/Inter-SemiBoldItalic.woff": "9623d9c91148b651b7d4a642751e4f9eaeda68b6f4c33355d0173e303252039b3bcd301556a1d8451ffbd36d7996c1e8fc5ca1276884636cf57468e38c9e442a",
92
+        "fonts\/Inter-SemiBoldItalic.woff2": "97b7d8ab268ebcbc00876bd69ca9cc7cf2ae9ba5a6a30c13e3412e41a88f1f5ed758a6d9abbab3a14359943a003b14307cbc379bb11505c014b002322fd53c6e",
93
+        "fonts\/SIL_Open_Font_License_v1.1_Inter.txt": "073e141d4e45a3adfd2cb569db6a4fd217b1721dd6aeab8159e36940b984df5ebdc345deb0eb6be65367f943e516a12dff41eb1238a322d248ca3478c50ef9b6",
94
+        "fonts\/opensans-bold.woff": "d094832745611e047ffa87fdb21bac41befabdb07aecade483d4dc5a5b97bad00f1d4a5dca2a615789cd494791f0ab4209be537eb4b1bc7cbee7c42eb5e201dc",
95
+        "fonts\/opensans-bold.woff2": "096abb618c9ce1a534f0198aeea53c6d1138000f98b883131ab49ee48b80b483af635f0196ac40a1c1bde679f63b3c3b907b8f9b0102a752862d623dd22393a5",
96
+        "fonts\/opensans-bolditalic.woff": "c80f105a10d37c812f5d1b29445cd21cbc95594f71d9c5fc1b3aeeb9985c5465ba017654f1453baefdc56cc27aa325b586d77323012073eb713ab8f88f08dab4",
97
+        "fonts\/opensans-bolditalic.woff2": "38b99ebf320264d74a456fe590fc610580b003bc77a39d97ff42dec41353a8f908d6f680b4777cdb34ed544d9b4ed20dce8c418317de1d721e25ab670f49fc1d",
98
+        "fonts\/opensans-extrabold.woff": "6636a395ba345853ada2237b8e1f81c52e54bfb65559cbcb8de143cac00232f20cf34c764c9c4d4b80e82dae79cba3064ebdf22999cce8839df2d5709ee64092",
99
+        "fonts\/opensans-extrabold.woff2": "758c90eb07c6db7e78cb703ea285f82b443ca2cfab792328a3f8c14acc1f932ae79ec2987b8b94bf19b3cc16fae31c76f3164c9437a2591283fb1592e40ec33d",
100
+        "fonts\/opensans-extrabolditalic.woff": "ab1966f1ab3bb436e489c2d6ee562cf22d05b6b8c9bbca17e903518311aa45659efc329255e08ab597e2b8effe3bda602a7fb56b7d0c1d872b69337537d49dff",
101
+        "fonts\/opensans-extrabolditalic.woff2": "2132d6309969f868521f2d788b991bc9bcf3239f1768db9a2b90faf8838c35efea85225b24db256f54c86d0a7915ecd50a7f5348e6ab040e0f172ba7510598cd",
102
+        "fonts\/opensans-italic.woff": "a9751e7ac7a3c3d9f739d1fe00730a545b68e4a6473beafee8edf583f175b34fd5e0b60a14ec3707c8691fdbebea17e191c51707f50a21281e76be46f55a1140",
103
+        "fonts\/opensans-italic.woff2": "7a80c01d34562e2fe248a71078ffa9413c04c9c320d27acb0bce96cc295101eb9e80a25e97dab3e67c184c40937862be820581441aa4100bd512a26ef2d523cf",
104
+        "fonts\/opensans-light.woff": "cca2c5d207e0935c1848e22965972cb6feea39aa93b1b546051cfabe5ab16e909934d007a7ccd174eda1e7671d838f477890dedcb93d68ba722eda39a16d0bb8",
105
+        "fonts\/opensans-light.woff2": "cdc332de1b13eb0f05cc9dd1ebc905fa5ce948eab71e2fdb1bc538ad54a0de980bf83352090becd650af9c101ec9a6898d2e4798e4fb777e41c20fae85fd568b",
106
+        "fonts\/opensans-lightitalic.woff": "26e7759869088d8abba380f0bb22bbb9fdf0a985c0999519390cbd85099e3f48864d866f4639a8ff1992e7c81c755b0bbf66f525d4d38a929067886e9b54eb88",
107
+        "fonts\/opensans-lightitalic.woff2": "b7f80b69abeca9d0369f5d46da192e98a6329cf1f948c897fb7130e0d815f73e293c37f0e6d0047273fe3f13a19e648d1bd06cfa2fac2142ec38ac244e7f0940",
108
+        "fonts\/opensans-regular.woff": "3a526ba177f8f16ad95941c185411f350fab7e5202b9f56ea9c5f972c62912781d66da10e278e065cc6748a4bc9ab9182d68b27eaf380131c602195148e4b8b4",
109
+        "fonts\/opensans-regular.woff2": "66b3e915b891f7b37b441ee18e40f01274fe19f2515470760e503f428fc1c524ccfbe832191978c2c5f6bc4b7ef46937e4f77f5457b6efbf878c97c054cb45f2",
110
+        "fonts\/opensans-semibold.woff": "173f703ab767d0fcff014dac2fa3dcac787ffd0eb39f0c532b6679935c0105daacfa6a32bca97de13e420e10194b701ad2487bfd35d28807563ebf0b16d0ca35",
111
+        "fonts\/opensans-semibold.woff2": "75068ba76befc2356fe83b198bf6da70e177e53cc3128af09d0d9f69dfe538013f2828b2363c6f533fcaca4d4b2a5ec5159b5eb6f288504ac73d33ac5d1d2c4d",
112
+        "fonts\/opensans-semibolditalic.woff": "9e1e965095991d4a12a0658fa22a116b043ce20fd5f73bb9655d870ae49c46170cec52827510be323332b535002eb96445f79c3d1e4dd0550ff622fda0465f1d",
113
+        "fonts\/opensans-semibolditalic.woff2": "d7e43f05802e26f4cb80ab6a492b01c398c5b41168c7f61356ca3ffc5f4fccabae5ba332956f0aecad69ccabb6b7526efbc0395552cc5d68e47bec00bc660ad7",
114
+        "img\/app-dark.svg": "1cd5df59a2886ada493eedba1ec62dcef815210416cdc1a6bb35aaa3fcaee59f5cd5a756e082557ba95eddd5abcba37236b5fc815cfffd9dea2843614071a673",
115
+        "img\/app.svg": "db540b202b0b9e49e0ed2453d99eb23b8eb37c293fcf52de280844e3d3c224ed067cc7bd80db755d851a78fca13fd2721e7bf16727f755de17442fd894b75791",
116
+        "img\/nextcloud_logo.svg": "4e0d3f0c371d668d83d443e5b1f69f0eedcc759092601d8fe8710dd97b16fd53aa3f9667bba7f305dc3aacfbc14e29b09b78da8b7bf6f41dcb83f5b16473991e",
117
+        "img\/nextcloud_logo_bright.svg": "aeab941556e29f9537508171583bb3309372866122c150c887c21d6a567c5aa06d2653db67c7151b064d4e2fa25f1fc63df21c786ede02ca5f40f12e5c1bad26",
118
+        "img\/pax_fax.svg": "db540b202b0b9e49e0ed2453d99eb23b8eb37c293fcf52de280844e3d3c224ed067cc7bd80db755d851a78fca13fd2721e7bf16727f755de17442fd894b75791",
119
+        "img\/pax_fax_choose_file_from_nextcloud.png": "92d30d5c20d0f03acd9430f4e2c1a3694e346941dc9ec1400fb8a2697b750ddc611d226a55c31d5d3001c1bce2199edfcd823cc2634bb6d050ad0ce4fadaf993",
120
+        "img\/pax_fax_dark.svg": "1cd5df59a2886ada493eedba1ec62dcef815210416cdc1a6bb35aaa3fcaee59f5cd5a756e082557ba95eddd5abcba37236b5fc815cfffd9dea2843614071a673",
121
+        "img\/pax_fax_files_from_pc_and_nextcloud.png": "610c382b47f8ca41898098642538c1ede712a0462442a0eb937110b81befe71833de0a4e74c7f6e798888b51a9b7718108b910c145b7d4bc8096145f835ac556",
122
+        "img\/pax_fax_grey.svg": "fc36143f41b406b237a36e98b5834320bfff94c992a5633508834a8f2db79f679e5b83573d727774f7db6ac5c2eb01fb09b3d42ff1c16fb891f75e9d8a890c17",
123
+        "img\/pax_fax_logo.png": "3c901669e9f2e76f7bb3f2479209f0ff51c24c940d1d5ec163a375464b696c61872bc482dd523560919179cc0af3825d254dd89506220317c9930030896790df",
124
+        "img\/pax_fax_received_fax.png": "87c741f189a9be2dac419a2a37147aa8f3baec70df440f2aa1dbfa5f86fa79a8c12326ba02b0d47a470521705e1d4e2243965d82812a25e4f045f21c83138819",
125
+        "img\/pax_fax_received_faxes.png": "ae747393bbbce84696c45aad0d30eb50903dd455f4cb7ba128fd8c5f22aa8d099b2fcc32a2ce58d34ca8bafa5ddd3824e94df68464b36c3d4b6ce56fa85915fe",
126
+        "img\/pax_fax_send_uploaded_file_as_fax.png": "55b993e9ad2800750295353d265dea3b0bfb30fe1faffc078a631e8d96da5c56f0bf6254abdd144d4baf429d7d3b1595831cd46ac36efa1308e76ee3afc6e71e",
127
+        "img\/pax_fax_sent_faxes.png": "d2630afa4992268e9891c66805fb44b21a3c7fbe431f7cc4582ae28b0355821696e8e50304b0165b5208b05a0b7c460f8d2d572d98ec53c3bd99ba08feb17a4e",
128
+        "img\/refresh_logo.svg": "a95a19645bbde5e2146a3ec669950bc6029bfc6104886552eaeb4746733657ecbe4f9199e676ee2e9852ef0c5adb612d93e300e3fa9713fc611e1f8e7c1d5183",
129
+        "js\/sendfax.js": "911f5bbc4381c97b71d80903ca779472bbbc2ae3863c0bb62d685bba51a3ee0de7f6f05c629c01b9387d3235d8835b28262fc79ce1691fcd3e1afd164a2d4584",
130
+        "js\/settings.js": "a905d6d8518b9a5d738c9c582cebf22c1e9bf32961dd5b295ec6be57ebaf5db3743b483fbbcec4ea675384655ae50fff931b2a694f90e7d10ab8bfd967348110",
131
+        "js\/tiff.min.js": "c35f67b587aab62db7a3de662779a7b3264d70f5f856142cae88eadd1b477e474977f2b8c5ab31c16be002cb7ca9b52282e6de533b6fd79a02e6d33815919cb4",
132
+        "js\/webodf.min.js": "655acab6a9773314aa741a7477121885c593bf3ecf2bc67adf8f870c81d0604ebf5fc558dc2a6072da0a70397c0d995ce15c5969b2190bcd2b687693772a3281",
133
+        "l10n\/en_GB.js": "009361152e9a063f23d4bc0bc6c98daa5dee895a3c799f872b917759a16c2c7ba23b7d71a1ee3a11e630f2e9c96335fb25623825bb4aebccffd6407cd1858538",
134
+        "l10n\/en_GB.json": "56a759416a6e93562fed8ea448330d5e102c1a543259a05b7cd0db96a85d28d356e4ad341d24d20a34955821351e4d3b8ac96423d9a96e273d5d20be087ac896",
135
+        "l10n\/en_US.js": "009361152e9a063f23d4bc0bc6c98daa5dee895a3c799f872b917759a16c2c7ba23b7d71a1ee3a11e630f2e9c96335fb25623825bb4aebccffd6407cd1858538",
136
+        "l10n\/en_US.json": "56a759416a6e93562fed8ea448330d5e102c1a543259a05b7cd0db96a85d28d356e4ad341d24d20a34955821351e4d3b8ac96423d9a96e273d5d20be087ac896",
137
+        "lib\/AppConfig.php": "c8acb61a0d2a4411a468578e4d10dbf1491c259fdfc6f40bfb29b5fae9b2d9dfb3564c72b9c679b5427f37dd51932d17ce6924c4e49daf58c390b6d2076c15b3",
138
+        "lib\/AppInfo\/Application.php": "8cc6ca32c87308f27d2fe6e1cdc48200750c50df595f13a942b406c1ac70583b367a4f594bc404a6c0cb50a75fccc29648d60303ac2a5273494406cab20a4966",
139
+        "lib\/Controller\/AuthorApiController.php": "46bacf8cc575a31dc4757d7c0a340bf450a3f4fe94c88ea995edccbbff7df4285e8e2d35a673b906a81fc2538a85b5bd47d8745c5cb8c2561ca9340b273682ad",
140
+        "lib\/Controller\/PageController.php": "c2abb6d62f7118e4c4ff73252c3ac4290e46e252a65248dae12c5a721a1aadeda189835d8efb9c8da7b22b3d8221e928a640bd93e4c5408a2db453517b78cb0d",
141
+        "lib\/Controller\/PaxfaxController.php": "85f899a6a25835d9392f0a84d79694fbbaab1bb679a01b3586a225bb488b02cc162a9d8968c6fc23378bf4f3a0d0b267485bfacadccccc3e4e656358659bfb63",
142
+        "lib\/Migration\/Version100Date20211106170854.php": "d1f5538dc19c89a6b8a1521af701f0682be89f773ac63b7615b3d7af8fa183f03f176f1ba38d5c55c3912e23b815b2cf3d85078b0c4445af64380906f67e2601",
143
+        "lib\/Migration\/Version116Date20240527235146.php": "16810cf56cbbc0acdc7826d2d69fd7a0c589cc9c50802003ee1d55e0fa4ec302b6b60ea8a2b39f2173ffd6aa14d7f8c529c216caf9019abf6e03c6202ff2249a",
144
+        "lib\/Migration\/Version119Date20250425082914.php": "5bc943247693d7bdc2720bb979d5de74d475d143283f00a0afb2d626508b5b59a94444f3045f52e4a524c270b3fbf753aacbf65456cf3ba7b5a9d9c9707cfd07",
145
+        "lib\/Notification\/Notifier.php": "1654df78822651bd3b9e57fa95857e4f37ba80011a259dd9b3f25ab7913c168f4fe90ce3536f8904e051335c983c2951f89bf4e01549b8da0ce6800f952a7822",
146
+        "lib\/Service\/PaxfaxService.php": "8dae81f332ac7a96994658cf75f6531aa6522e92facb7e0c6b40394ee8b200053beffb6282f2c171a740438e4e75fddcf0452e7f35f56e9061fd3afae28f4c08",
147
+        "lib\/Settings\/Personal.php": "8242e941926433f948a32c6bad02faeba1d64374f4a7efbac64d1600177507ecd66b85df98194312d7f0062a34536e5f21293ac43b6402899146359ff7bb3d65",
148
+        "lib\/Settings\/PersonalSection.php": "f928a8b1df3bd8b482cab7a61cd32cb039ec6b8744f1902bc741c0ca85d0c3473d939df0a1fc91c2bead6b94546a10fa59136e491b142680814bd99ffb05d12b",
149
+        "templates\/content\/index.php": "7f88b793a60d7e3baeb18a22e8f6f6980fe981952871fb4efc1f9d56b4b2fcfc4ac5ef32e03ff227b0c6229cfcfa3a42a12d48c6871d5400a8b4fd68e3d18615",
150
+        "templates\/index.php": "ea041904c7847c95b9e75d60e0328b51a5eb55bd2c45352127d5490f8ee04af5af9b740cd8b71009841c53c1a1ac8de44be01f4744d7273b688d11fa5dd56498",
151
+        "templates\/navigation\/index.php": "fb50ed188a58b39142923f8628975b96c432b0364ff7b1a6a5d192ca7c36b5ea05bb244d710343a420af9e6dd505849dfcf58e37010df091f576d0bc0cceeb81",
152
+        "templates\/settings.php": "277f2de095a8bfa9f269e0f5c3c5b8face71370a7dc57955caf984b461403d8d8ca31c7bbec72eeee9fe98aa95da8ec2139b3d1a80674a57d125570b06024cc0"
153
+    },
154
+    "signature": "lI6x3uWExa8VoUYe+9jtfn0MsnVby6PSfHLNKBiDgRdgBVgsF\/5C+4gtcipJENDafeiAe\/XZkUtfyic4Y9iQwugPKI6reQnSTg98l9p4lg0net1Q2Bh91+i3TM2gweruNGjo34iNeYEDoF+qp5xbpRbGtrV\/ru8hA2ZIrt793BurOLfkjjEPLWHhl6vKZFyVkPl2S7JMY0y9azQxKJNxRuZLMFQWfy7YXabLckzGMF3etGRXbz9z+hmXX2ORKqK3gAby42w3romWZP+i6YxVCiOtWBawePneXbm8TUu9mwN7jF1k4LcBAgsQNXTB+WlyS9iYKcPdpdLqIiQQhhIIsjEx\/lrZbQZ583UgdACYTKAjpAxJzPzrawZuZyPX\/iHlhBVus75ts5GsJdspIGuETLD1myzd5TwA4TY2tDGT6+S\/pGHzOenubIEZnkXMvFDQj+b6bqX53CLaLT2Cue+zEr8xHf6aUqTWpNP0++B55uuqBdI1kErNeKCi9r42O7xjbAFfxme\/k7imIw0CqNZyByVd8xgXYch1+liPH6WSBTWzKlRxG+isvjAYLsV6SWphtT9KX3CI2jhbvCW9JJ14Kb57dOFPwXjVsMX08pCoUTfuSVBWjNV4tb1E52k5uNm6g\/pWb7NZtmGfL+DkNtjwyCABMSHzwBHiQOeYVYj0YCI=",
155
+    "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEAjCCAuoCAhG6MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\r\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\r\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\r\ndXRob3JpdHkwHhcNMjIwMjI1MTU0NTUwWhcNMzIwNjAyMTU0NTUwWjASMRAwDgYD\r\nVQQDDAdwYXhfZmF4MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsa4b\r\nARkaBatWm4JNKsst3BNjt1X4Clo0Vynelj+VfcMK9G2dB02HGZiQhBfi5cvLMDD4\r\nJEw9jPPf+pxxBY87gwloEQxRW4WmI3LLCPNVSF7GfvONwdjsoJebCPnH6AYHbUlG\r\nQ8\/6wlgCiCklMiCWW0pGFQaDis+4KIkmoFS4elRxOzb+oLCsJRHmLIcV1ZipRanE\r\nP5Y1u953glpjMChZEW6\/p4AEB4xi6b+GaQ+8cBZ5+7WvT54l5iKHY6Tl6fwOuBjl\r\nCc+8FC+hIKk7bTSXfbuwpgzZ7RNgH0BYD\/aryxK\/MHAqeGQKM\/pwvH9SN8LMLZVg\r\nXG+25FiBPuiST\/3l42sY1HD+Gh1KIw83zWD\/kVsU8tKIf0t0uS3ntwx3xjH0ojo9\r\n85Pu4XexopIPi4YxNFtphd\/+cJegbSLKa1LL2CqhnPSXHD8GYjZ16qdy6AxEyEki\r\nOQssSlTOsQ2RmvRqDPwqrbIZrVeiN3Mt4qEontOzci4ggjhBWqhjkcRId4XlGveu\r\nAbWP9O8aXzrElLLeSuDzl6uAcrtwgFvYjoxbRH66hcwv\/+RBOK58CI\/0ShGJZyVh\r\n\/9oDKwyYfHT1OTbRKlvm+TfV6Vmbuol0xFinUv4GoykBO67JJcERTSTGGDqMP2OL\r\n97lkR1b7sy9WKrWw1iljbwyzEEASKKleJtp8HC0CAwEAATANBgkqhkiG9w0BAQsF\r\nAAOCAQEAK+uuoq2F0N4nYdHpRRi5pP8hu540jEpHsLB8o\/3GT++Tdj9jeMdfDWos\r\nskB2e+Vi3OgiCWq51gQ9pq0YSQLZJzXBtX9Zd7gvnmIWJZqjbEkMsky+zMM2mweA\r\nl4+coZvXuqxNN6aY+oAKuf66ZWviUld1WEOz0+2vLrhs9qDCYFKDl7vXol6hz4gf\r\nX5d5crNAu1QboE8FEMxqfDrAMeJzL6SAG4UUaF9duB\/6xUm9d7vBKDCPMzZAV\/ob\r\n+8wxt7K4VoOuCo1KEpp\/+ZRrEr5ZbGGsNw41jrtfBsrMtbbIoRtyIh9Xfme2KzYM\r\ncm9HZiMNDokH8MlzOPOGwkP31w4FHQ==\r\n-----END CERTIFICATE-----"
156
+}
0 157
\ No newline at end of file
1 158
new file mode 100644
... ...
@@ -0,0 +1,1004 @@
1
+/**
2
+ * @copyright 2021 Double Bastion LLC <www.doublebastion.com>
3
+ *
4
+ * @author Double Bastion LLC
5
+ *
6
+ * @license GNU AGPL version 3 or any later version
7
+ *
8
+ * This program is free software; you can redistribute it and/or
9
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
10
+ * License as published by the Free Software Foundation; either
11
+ * version 3 of the License, or any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
17
+ *
18
+ * You should have received a copy of the GNU Affero General Public
19
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+@font-face {
24
+    font-family: 'Open Sans';
25
+    src: url('../fonts/opensans-light.woff2') format('woff2'),
26
+         url('../fonts/opensans-light.woff') format('woff');
27
+    font-weight: 300;
28
+    font-style: normal;
29
+}
30
+@font-face {
31
+    font-family: 'Open Sans';
32
+    src: url('../fonts/opensans-lightitalic.woff2') format('woff2'),
33
+         url('../fonts/opensans-lightitalic.woff') format('woff');
34
+    font-weight: 300;
35
+    font-style: italic;
36
+}
37
+@font-face {
38
+    font-family: 'Open Sans';
39
+    src: url('../fonts/opensans-regular.woff2') format('woff2'),
40
+         url('../fonts/opensans-regular.woff') format('woff');
41
+    font-weight: 400;
42
+    font-style: normal;
43
+}
44
+@font-face {
45
+    font-family: 'Open Sans';
46
+    src: url('../fonts/opensans-italic.woff2') format('woff2'),
47
+         url('../fonts/opensans-italic.woff') format('woff');
48
+    font-weight: 400;
49
+    font-style: italic;
50
+}
51
+@font-face {
52
+    font-family: 'Open Sans';
53
+    src: url('../fonts/opensans-semibold.woff2') format('woff2'),
54
+         url('../fonts/opensans-semibold.woff') format('woff');
55
+    font-weight: 600;
56
+    font-style: normal;
57
+}
58
+@font-face {
59
+    font-family: 'Open Sans';
60
+    src: url('../fonts/opensans-semibolditalic.woff2') format('woff2'),
61
+         url('../fonts/opensans-semibolditalic.woff') format('woff');
62
+    font-weight: 600;
63
+    font-style: italic;
64
+}
65
+@font-face {
66
+    font-family: 'Open Sans';
67
+    src: url('../fonts/opensans-bold.woff2') format('woff2'),
68
+         url('../fonts/opensans-bold.woff') format('woff');
69
+    font-weight: 700;
70
+    font-style: normal;
71
+}
72
+@font-face {
73
+    font-family: 'Open Sans';
74
+    src: url('../fonts/opensans-bolditalic.woff2') format('woff2'),
75
+         url('../fonts/opensans-bolditalic.woff') format('woff');
76
+    font-weight: 700;
77
+    font-style: italic;
78
+}
79
+@font-face {
80
+    font-family: 'Open Sans';
81
+    src: url('../fonts/opensans-extrabold.woff2') format('woff2'),
82
+         url('../fonts/opensans-extrabold.woff') format('woff');
83
+    font-weight: 800;
84
+    font-style: normal;
85
+}
86
+@font-face {
87
+    font-family: 'Open Sans';
88
+    src: url('../fonts/opensans-extrabolditalic.woff2') format('woff2'),
89
+         url('../fonts/opensans-extrabolditalic.woff') format('woff');
90
+    font-weight: 800;
91
+    font-style: italic;
92
+}
93
+
94
+@font-face {
95
+    font-family: 'Inter';
96
+    src: url('../fonts/Inter-Regular.woff2') format('woff2'),
97
+         url('../fonts/Inter-Regular.woff') format('woff');
98
+    font-weight: 400;
99
+    font-style: normal;
100
+}
101
+@font-face {
102
+    font-family: 'Inter';
103
+    src: url('../fonts/Inter-Italic.woff2') format('woff2'),
104
+         url('../fonts/Inter-Italic.woff') format('woff');
105
+    font-weight: 400;
106
+    font-style: italic;
107
+}
108
+@font-face {
109
+    font-family: 'Inter';
110
+    src: url('../fonts/Inter-Medium.woff2') format('woff2'),
111
+         url('../fonts/Inter-Medium.woff') format('woff');
112
+    font-weight: 500;
113
+    font-style: normal;
114
+}
115
+@font-face {
116
+    font-family: 'Inter';
117
+    src: url('../fonts/Inter-MediumItalic.woff2') format('woff2'),
118
+         url('../fonts/Inter-MediumItalic.woff') format('woff');
119
+    font-weight: 500;
120
+    font-style: italic;
121
+}
122
+@font-face {
123
+    font-family: 'Inter';
124
+    src: url('../fonts/Inter-SemiBold.woff2') format('woff2'),
125
+         url('../fonts/Inter-SemiBold.woff') format('woff');
126
+    font-weight: 600;
127
+    font-style: normal;
128
+}
129
+@font-face {
130
+    font-family: 'Inter';
131
+    src: url('../fonts/Inter-SemiBoldItalic.woff2') format('woff2'),
132
+         url('../fonts/Inter-SemiBoldItalic.woff') format('woff');
133
+    font-weight: 600;
134
+    font-style: italic;
135
+}
136
+@font-face {
137
+    font-family: 'Inter';
138
+    src: url('../fonts/Inter-Bold.woff2') format('woff2'),
139
+         url('../fonts/Inter-Bold.woff') format('woff');
140
+    font-weight: 700;
141
+    font-style: normal;
142
+}
143
+@font-face {
144
+    font-family: 'Inter';
145
+    src: url('../fonts/Inter-BoldItalic.woff2') format('woff2'),
146
+         url('../fonts/Inter-BoldItalic.woff') format('woff');
147
+    font-weight: 700;
148
+    font-style: italic;
149
+}
150
+@font-face {
151
+    font-family: 'Inter';
152
+    src: url('../fonts/Inter-ExtraBold.woff2') format('woff2'),
153
+         url('../fonts/Inter-ExtraBold.woff') format('woff');
154
+    font-weight: 800;
155
+    font-style: normal;
156
+}
157
+@font-face {
158
+    font-family: 'Inter';
159
+    src: url('../fonts/Inter-ExtraBoldItalic.woff2') format('woff2'),
160
+         url('../fonts/Inter-ExtraBoldItalic.woff') format('woff');
161
+    font-weight: 800;
162
+    font-style: italic;
163
+}
164
+
165
+#app {
166
+  position: relative;
167
+  display: flex;
168
+  min-height: 100%;
169
+  min-width: 100%;
170
+}
171
+
172
+#app-content {
173
+  position: relative;
174
+  z-index: 1000;
175
+  flex-basis: 100vw;
176
+  min-width: 0;
177
+  min-height: 100%;
178
+  margin: 0 !important;
179
+  overflow-y: scroll;
180
+}
181
+
182
+#app-content #app-content-wrapper {
183
+  height: 108% !important;
184
+}
185
+
186
+#pax_fax_vbar {
187
+  padding: 18px;
188
+  font-family: 'Open Sans';
189
+  color: #6d6c6c;
190
+}
191
+
192
+#currentbaldiv {
193
+  display: block;
194
+  position: relative;
195
+  height: 30px;
196
+  margin: 0 0 8px 0;
197
+  padding: 3px 0 3px 14px;
198
+  font-size: 15px;
199
+  font-weight: 700;
200
+  color: #ffffff;
201
+  background-color: #3f9dd1;
202
+  border-radius: 20px;
203
+}
204
+
205
+#currentbalance {
206
+  display: inline;
207
+  position: relative;
208
+  padding-left: 10px;
209
+}
210
+
211
+#faxnumbersdiv {
212
+  display: block;
213
+  position: relative;
214
+  font-size: 15px;
215
+  font-weight: 700;
216
+  height: 30px;
217
+  margin: 0px 0px 20px 0px;
218
+  background: #3f9dd1;
219
+  border-radius: 20px;
220
+}
221
+
222
+#currentfaxnmbrs {
223
+  display: inline-block;
224
+  position: absolute;
225
+  height: 22px !important;
226
+  width: 55%;
227
+  font-size: 14px;
228
+  font-weight: 600;
229
+  text-align: center;
230
+  padding: 0 0 2px 0;
231
+  color: #565656;
232
+  margin: 1px 0 0 4px;
233
+  -moz-box-sizing: border-box;
234
+  -webkit-box-sizing: border-box;
235
+  box-sizing: border-box;
236
+  background: #fcfcfc;
237
+  border-radius: 20px;
238
+}
239
+
240
+.pflabels {
241
+  font-size: 15px;
242
+  font-weight: 700;
243
+}
244
+
245
+.pfheader {
246
+  display: block;
247
+  position: relative;
248
+  margin: 0px 0px 7px 0px;
249
+  font-size: 15px;
250
+  font-weight: 700;
251
+}
252
+
253
+.faxnbformat {
254
+  display: block;
255
+  position: relative;
256
+  margin: 0px 0px 4px 0px;
257
+  font-size: 15px;
258
+  font-weight: 700;
259
+}
260
+
261
+.pax_fax_box {
262
+  display: block;
263
+  box-sizing: content-box;
264
+  margin: 8px 0px !important;
265
+  width: 70%;
266
+}
267
+.indtext {
268
+  display: inline-block;
269
+  padding-left: 10px;
270
+}
271
+
272
+#pf_upload_msg, #pf_choose_msg, #pf_submit_msg {
273
+  display: block;
274
+  margin: 8px 0px 8px 0px;
275
+  text-align: center;
276
+  font-size: 15px;
277
+  font-weight: 700;
278
+  color: #181918;
279
+  background-color: #a5e5b3;
280
+  border-radius: 14px;
281
+}
282
+
283
+#paxfax_save_msg {
284
+  display: inline;
285
+  color: #181918;
286
+  background-color: #a5e5b3;
287
+  font-weight: 700;
288
+  max-width: 70px;
289
+  text-align: center;
290
+  margin-top: 7px;
291
+}
292
+
293
+#pf_submit_msg {
294
+  padding-left: 5px;
295
+  padding-right: 5px;
296
+}
297
+
298
+#pickedfilename {
299
+  font-size: 13px;
300
+}
301
+
302
+#faxtodiv {
303
+  display: block;
304
+  position: relative;
305
+}
306
+
307
+#faxto {
308
+  display: block;
309
+  width: 97%;
310
+  max-height: 22px;
311
+  margin: 3px 0px 20px 0px;
312
+  padding: 0 13px 0 13px;
313
+  color: #565656;
314
+  font-family: 'Open Sans';
315
+  font-size: 15px;
316
+  font-weight: 700;
317
+  border-radius: 20px;
318
+}
319
+
320
+.up-bttn-wrapper {
321
+  display: block;
322
+  position: relative;
323
+  overflow: hidden;
324
+  padding-top: 20px;
325
+  padding-bottom: 30px;
326
+}
327
+
328
+#submitfax {
329
+  display: block;
330
+  color: white;
331
+  font-family: 'Open Sans';
332
+  font-weight: 700;
333
+  font-size: 15px;
334
+  background-color: #3f9dd1;
335
+  padding: 5px 16px 6px 16px;
336
+  border-radius: 20px;
337
+}
338
+
339
+#submitfax:hover {
340
+  background-color: #398dbb;
341
+}
342
+
343
+#submitfax:active {
344
+  background-color: #3179a1;
345
+}
346
+
347
+.uploadfiledv {
348
+  position: relative;
349
+  display: inline-block;
350
+  margin: 4px 0px 22px 0px;
351
+}
352
+
353
+#faxfoldersview {
354
+  display: inline-block;
355
+  position: relative;
356
+  width: 100%;
357
+  height: 100%;
358
+  // margin-top: -50px;
359
+  background-color: #f4f9ff;
360
+}
361
+
362
+#viewerContainer {
363
+  display: block;
364
+  position: relative;
365
+  width: 100%;
366
+  height: 100%;
367
+}
368
+
369
+#viewer {
370
+  display: block;
371
+  position: relative;
372
+  min-width: 100%;
373
+  min-height: 100%;
374
+}
375
+
376
+#faxdocpreview {
377
+  display: block;
378
+  position: relative;
379
+  min-width: 100%;
380
+  min-height: 100%;
381
+  background-color: #f4f9ff;
382
+}
383
+
384
+#docPreviewFaxImg {
385
+  display: block;
386
+  position: relative;
387
+  background-image: url('../img/pax_fax_grey.svg');
388
+  background-repeat: no-repeat;
389
+  background-position: center;
390
+  width: 100%;
391
+  height: 100%;
392
+}
393
+
394
+#outerContainer {
395
+  display: block;
396
+  position: relative;
397
+  width: 100%;
398
+  height: 100%;
399
+}
400
+
401
+#mainContainer {
402
+  display: block;
403
+  position: relative;
404
+  width: 100%;
405
+  height: 100%;
406
+}
407
+
408
+#uploadedjpg, #uploadedpng {
409
+  width: auto !important;
410
+  height: auto !important;
411
+}
412
+
413
+.cllridcls {
414
+  position: relative;
415
+  display: inline;
416
+  font-size: 17px;
417
+  color: #000000;
418
+  z-index: 3;
419
+}
420
+
421
+.fortooltipinit {
422
+  position: relative;
423
+  display: inline-block;
424
+  float: right;
425
+  font-size: 15px;
426
+  color: #000000;
427
+  z-index: 3;
428
+}
429
+
430
+.fortooltipinit #infosetid {
431
+  display: block;
432
+  position: relative;
433
+  margin: 0 9px 0 0;
434
+  color: #000000;
435
+  font-size: 19px;
436
+  font-weight: 700;
437
+  font-family: 'Open Sans';
438
+  font-style: italic;
439
+}
440
+
441
+.fortooltip {
442
+  position: relative;
443
+  display: inline-block;
444
+  font-size: 15px;
445
+  color: #000000;
446
+  z-index: 2;
447
+}
448
+
449
+.fortooltip #infonumber {
450
+  color: #000000;
451
+  font-size: 19px;
452
+  font-weight: 700;
453
+  font-family: 'Open Sans';
454
+  font-style: italic;
455
+  padding: 0px 0px 3px 3px;
456
+}
457
+
458
+.fortooltipsec {
459
+  position: relative;
460
+  display: inline-block;
461
+  font-size: 15px;
462
+  color: #000000;
463
+  padding: 0px 0px 4px 0px;
464
+  z-index: 1;
465
+}
466
+
467
+.fortooltipsec #infoformat {
468
+  color: #000000;
469
+  font-size: 19px;
470
+  font-weight: 700;
471
+  font-family: 'Open Sans';
472
+  font-style: italic;
473
+  padding: 0px 0px 3px 3px;
474
+}
475
+
476
+.fortooltipinit .calleridtooltip {
477
+  display: block;
478
+  position: absolute;
479
+  visibility: hidden;
480
+  width: 264px;
481
+  background-color: #fafafa;
482
+  font-size: 14px;
483
+  font-weight: 700;
484
+  color: #595959;
485
+  text-align: left;
486
+  border-radius: 5px;
487
+  padding: 5px 10px;
488
+  margin: -4px 0px 0px -214px;
489
+  box-shadow: 0 0 23px rgba(0, 0, 0, 0.23);
490
+  -webkit-box-shadow: 0 0 23px rgba(0, 0, 0, 0.23);
491
+  -moz-box-shadow: 0 0 23px rgba(0, 0, 0, 0.23);
492
+}
493
+
494
+.fortooltipinit:hover .calleridtooltip {
495
+  visibility: visible;
496
+}
497
+
498
+.fortooltip .fortooltiptext {
499
+  display: block;
500
+  position: absolute;
501
+  visibility: hidden;
502
+  width: 256px;
503
+  background-color: #fafafa;
504
+  font-size: 14px;
505
+  font-weight: 700;
506
+  color: #595959;
507
+  text-align: left;
508
+  border-radius: 5px;
509
+  padding: 5px 10px;
510
+  margin: -11px 0 0 -4px;
511
+  box-shadow: 0 0 23px rgba(0, 0, 0, 0.23);
512
+  -webkit-box-shadow: 0 0 23px rgba(0, 0, 0, 0.23);
513
+  -moz-box-shadow: 0 0 23px rgba(0, 0, 0, 0.23);
514
+}
515
+
516
+.fortooltip:hover .fortooltiptext {
517
+  visibility: visible;
518
+}
519
+
520
+.fortooltipsec .fortooltiptextsec {
521
+  display: block;
522
+  position: absolute;
523
+  visibility: hidden;
524
+  width: 256px;
525
+  background-color: #fafafa;
526
+  font-size: 14px;
527
+  font-weight: 700;
528
+  color: #595959;
529
+  text-align: left;
530
+  border-radius: 5px;
531
+  padding: 5px 10px;
532
+  margin: -10px 0 0 -4px;
533
+  box-shadow: 0 0 23px rgba(0, 0, 0, 0.23);
534
+  -webkit-box-shadow: 0 0 23px rgba(0, 0, 0, 0.23);
535
+  -moz-box-shadow: 0 0 23px rgba(0, 0, 0, 0.23);
536
+}
537
+
538
+.fortooltipsec:hover .fortooltiptextsec {
539
+  visibility: visible;
540
+}
541
+
542
+.fileupload {
543
+  display: none;
544
+}
545
+
546
+div > label {
547
+  position: relative;
548
+}
549
+
550
+.uploadflbt {
551
+  width: 411px;
552
+}
553
+
554
+label span {
555
+  display: inline-block;
556
+  min-width: 110px;
557
+  padding: 0px 0px 8px 0px;
558
+}
559
+
560
+.uploadflbt .icon-upload {
561
+  display: inline;
562
+}
563
+
564
+.pfprompt {
565
+  font-size: 17px;
566
+  font-weight: 700;
567
+  color: #6d6c6c;
568
+}
569
+
570
+.fileuploadstl,.filesfromnc {
571
+  display: block;
572
+  font-size: 17px;
573
+  font-weight: 700;
574
+  color: #000000;
575
+}
576
+
577
+#filestotsize {
578
+  display: none;
579
+  position: relative;
580
+  height:auto;
581
+  margin: 0px 0px 16px 0px;
582
+  font-family: 'Open Sans';
583
+  color: #18bf6e;
584
+  font-size: 14px;
585
+  font-weight: 700;
586
+}
587
+
588
+#filessizetext {
589
+  display: inline;
590
+  position: relative;
591
+  padding-left: 10px;
592
+}
593
+
594
+#fileuploadednm .indivflcls {
595
+  display: inline-block;
596
+  position: relative;
597
+  height:auto;
598
+  max-width: 90%;
599
+  overflow: visible;
600
+  white-space: normal;
601
+  word-break: break-all;
602
+  text-overflow: ellipsis;
603
+  font-size: 15px;
604
+  color: #0e6ba0;
605
+}
606
+
607
+.indivflcls:hover {
608
+  cursor: pointer;
609
+  text-decoration: underline;
610
+}
611
+
612
+.indupfldl {
613
+  position: relative;
614
+  display: inline-block;
615
+  float: right;
616
+  cursor: pointer;
617
+  width: 20px;
618
+  color: #0e6ba0;
619
+  text-align: center;
620
+  font-size: 15px;
621
+}
622
+
623
+#fileuploadednm .indupfldl:hover {
624
+  background-color: #e8f6ff;
625
+  cursor: pointer;
626
+}
627
+
628
+#filespickednc .indivflpckd {
629
+  display: inline-block;
630
+  position: relative;
631
+  height:auto;
632
+  max-width: 90%;
633
+  overflow: visible;
634
+  white-space: normal;
635
+  word-break: break-all;
636
+  text-overflow: ellipsis;
637
+  font-size: 15px;
638
+  color: #0e6ba0;
639
+}
640
+
641
+.indivflpckd:hover {
642
+  cursor: pointer;
643
+  text-decoration: underline;
644
+}
645
+
646
+.indpckfldl {
647
+  position: relative;
648
+  display: inline-block;
649
+  float: right;
650
+  cursor: pointer;
651
+  width: 20px;
652
+  color: #0e6ba0;
653
+  font-size: 15px;
654
+  text-align: center;
655
+}
656
+
657
+#filespickednc .indpckfldl:hover {
658
+  background-color: #e8f6ff;
659
+  cursor: pointer;
660
+}
661
+
662
+select, button, .button, input:not([type="range"]), textarea, div[contenteditable="true"], .pager li a {
663
+  margin: 0px 0px 0px 0px;
664
+}
665
+
666
+#dirbuttons {
667
+  margin-top: 28px;
668
+}
669
+
670
+button, .button, input[type="button"], input[type="submit"], input[type="reset"] {
671
+  padding: 6px 20px;
672
+  width: auto;
673
+  min-height: 22px;
674
+  cursor: pointer;
675
+  box-sizing: border-box;
676
+  background-color: var(--color-background-dark);
677
+}
678
+
679
+select {
680
+  width: 130px;
681
+  min-height: 28px;
682
+  box-sizing: border-box;
683
+  padding-right: 0px !important;
684
+}
685
+
686
+#uploadfileforfax {
687
+  margin-left: 19px;
688
+  padding: 2px 20px;
689
+  border-radius: 20px;
690
+  background-color: #ededed;
691
+}
692
+
693
+#uploadfileforfax:hover {
694
+  background-color: #e6e6e6;
695
+}
696
+
697
+#uploadfileforfax:active {
698
+  background-color: #d8d8d8;
699
+}
700
+
701
+#pickFromNext, #uploadFile {
702
+  display: inline-block;
703
+  position: relative;
704
+  font-size: 15px;
705
+  font-weight: 700;
706
+  color: #6d6c6c;
707
+}
708
+
709
+#choosefilen {
710
+  display: inline;
711
+  position: relative;
712
+  margin: 0px 0px 20px 16px;
713
+  padding-top: 15px;
714
+  background-image: url('../img/nextcloud_logo.svg');
715
+  background-repeat: no-repeat;
716
+  background-size: 110% 125%;
717
+  background-position: center center;
718
+  min-width: 66px;
719
+  min-height: 30px;
720
+  cursor:pointer;
721
+  border-radius: 20px;
722
+}
723
+
724
+#choosefilen:active {
725
+  background-image: url('../img/nextcloud_logo_bright.svg');
726
+  background-repeat: no-repeat;
727
+  background-size: 110% 125%;
728
+  background-position: center center;
729
+  min-width: 66px;
730
+  min-height: 30px;
731
+}
732
+
733
+#checkbalance {
734
+  display: block;
735
+  position: relative;
736
+  min-width: 24px;
737
+  min-height: 24px;
738
+  float: right;
739
+  padding-left: 0;
740
+  margin-top: 0.3px;
741
+  margin-right: 4px;
742
+  background-image: url('../img/refresh_logo.svg');
743
+  background-repeat: no-repeat;
744
+  background-size: 110% 110%;
745
+  background-position: center center;
746
+  cursor: pointer;
747
+  background-color: #FFFFFF;
748
+  border-radius: 20px;
749
+}
750
+
751
+#selectcalleridbttn {
752
+  display: block;
753
+  position: relative;
754
+  min-width: 24px;
755
+  min-height: 24px;
756
+  float: right;
757
+  padding-left: 0;
758
+  margin-top: 2.8px;
759
+  margin-right: 4px;
760
+  background-image: url('../img/refresh_logo.svg');
761
+  background-repeat: no-repeat;
762
+  background-size: 110% 110%;
763
+  background-position: center center;
764
+  cursor: pointer;
765
+  background-color: #ffffff;
766
+  border-radius: 20px;
767
+}
768
+
769
+#faxnumbersdiv #pickid {
770
+  display: inline-block;
771
+  position: relative;
772
+  font-family: 'Open Sans';
773
+  font-size: 15px;
774
+  font-weight: 700;
775
+  margin: 2.7px 3px 3px 14px;
776
+  color: #ffffff;
777
+}
778
+
779
+#get_notification {
780
+  display: block;
781
+  margin-bottom: 8px;
782
+}
783
+
784
+#get_notification:hover {
785
+  cursor: pointer;
786
+}
787
+
788
+.pax_fax_boxspec {
789
+  display: inline-block;
790
+  box-sizing: content-box;
791
+  margin: 8px 0px !important;
792
+  width: 70%;
793
+  font-size: 14px !important;
794
+}
795
+
796
+.setlabeltext {
797
+  font-size: 15px;
798
+}
799
+
800
+#countryCallCode {
801
+  color: #1b60ba;
802
+}
803
+
804
+#countryCallCode:hover {
805
+  color: #0D3B78;
806
+}
807
+
808
+.openfaxfolder {
809
+  display: block;
810
+  position: relative;
811
+  margin: 10px 0px 10px 0px !important;
812
+  padding: 7px 0px 7px 0px;
813
+  width: 100% !important;
814
+  color: #FFFFFF !important;
815
+  font-family: 'Open Sans' !important;
816
+  font-size: 15px !important;
817
+  border-radius: 20px !important;
818
+  background-color: #CB99C5 !important;
819
+}
820
+
821
+.openfaxfolder:hover {
822
+  border: 2px;
823
+  background-color: #c18bba !important;
824
+}
825
+
826
+.openfaxfolder:active {
827
+  background-color: #b777af !important;
828
+  border: 2px;
829
+  color: #FFFFFF !important;
830
+  border-color: #b777af;
831
+}
832
+
833
+.openfaxfolder:focus {
834
+  background-color: #a3669b !important;
835
+  border: 2px;
836
+  border-color: #a3669b;
837
+}
838
+
839
+.indgenflcls, .indgenpckfls {
840
+  display: block;
841
+  margin: 0px 6px 14px 6px;
842
+}
843
+
844
+#pax_fax_adm {
845
+  font-family: 'Inter';
846
+}
847
+
848
+#settings-dscr {
849
+  padding-top: 3px;
850
+  font-weight: 500;
851
+}
852
+
853
+#save_fax_settings {
854
+  display: inline-block;
855
+  font-family: 'Open Sans';
856
+  padding: 6px 14px;
857
+  border-radius: 20px;
858
+  color: #ffffff !important;
859
+  background-color: #1e89c2 !important;
860
+}
861
+
862
+#save_fax_settings:hover {
863
+  background-color: #0369a0  !important;
864
+}
865
+
866
+#save_fax_settings:active {
867
+  background-color: #025480  !important;
868
+}
869
+
870
+/*Changes for dark themes*/
871
+[data-theme-dark] .fortooltipinit #infosetid,
872
+[data-theme-dark-highcontrast] .fortooltipinit #infosetid {
873
+  display: block;
874
+  position: relative;
875
+  margin: 0 9px 0 0;
876
+  color: #fafafa;
877
+  font-size: 19px;
878
+  font-weight: 700;
879
+  font-family: 'Open Sans';
880
+  font-style: italic;
881
+}
882
+
883
+[data-theme-dark] .fortooltip #infonumber,
884
+[data-theme-dark-highcontrast] .fortooltip #infonumber {
885
+  color: #fafafa;
886
+  font-size: 19px;
887
+  font-weight: 700;
888
+  font-family: 'Open Sans';
889
+  font-style: italic;
890
+  padding: 0px 0px 3px 3px;
891
+}
892
+
893
+[data-theme-dark] .fortooltipsec #infoformat,
894
+[data-theme-dark-highcontrast] .fortooltipsec #infoformat {
895
+  color: #fafafa;
896
+  font-size: 19px;
897
+  font-weight: 700;
898
+  font-family: 'Open Sans';
899
+  font-style: italic;
900
+  padding: 0px 0px 3px 3px;
901
+}
902
+
903
+[data-theme-dark] .faxnbformat a,
904
+[data-theme-dark-highcontrast] .faxnbformat a {
905
+  color: #cedfff !important;
906
+}
907
+
908
+[data-theme-dark] .faxnbformat font,
909
+[data-theme-dark-highcontrast] .faxnbformat font {
910
+  color: #f7547a !important;
911
+}
912
+
913
+[data-theme-dark] #faxto,
914
+[data-theme-dark-highcontrast] #faxto {
915
+  display: block;
916
+  width: 97%;
917
+  max-height: 22px;
918
+  margin: 3px 0px 20px 0px;
919
+  padding: 1px 13px 0px 13px;
920
+  color: #fafafa;
921
+  font-size: 15px;
922
+  font-weight: 700;
923
+  border-radius: 20px;
924
+}
925
+
926
+[data-theme-dark] .pfheader,
927
+[data-theme-dark-highcontrast] .pfheader {
928
+  display: block;
929
+  position: relative;
930
+  margin: 0px 0px 7px 0px;
931
+  color: #fafafa;
932
+  font-size: 15px;
933
+  font-weight: 700;
934
+}
935
+
936
+[data-theme-dark] #uploadFile,
937
+[data-theme-dark] #pickFromNext,
938
+[data-theme-dark-highcontrast] #uploadFile,
939
+[data-theme-dark-highcontrast] #pickFromNext {
940
+  display: inline-block;
941
+  position: relative;
942
+  font-size: 15px;
943
+  font-weight: 700;
944
+  color: #fafafa;
945
+}
946
+
947
+[data-theme-dark] #uploadfileforfax,
948
+[data-theme-dark-highcontrast] #uploadfileforfax {
949
+  margin-left: 19px;
950
+  background-color: #898989;
951
+  padding: 2px 20px;
952
+  border-radius: 20px;
953
+}
954
+
955
+[data-theme-dark] #fileuploadednm .indivflcls,
956
+[data-theme-dark-highcontrast] #fileuploadednm .indivflcls {
957
+  display: inline-block;
958
+  position: relative;
959
+  height: auto;
960
+  max-width: 90%;
961
+  overflow: visible;
962
+  white-space: normal;
963
+  word-break: break-all;
964
+  text-overflow: ellipsis;
965
+  font-size: 15px;
966
+  color: #c2e9ff;
967
+}
968
+
969
+[data-theme-dark] .indupfldl,
970
+[data-theme-dark-highcontrast] .indupfldl {
971
+  position: relative;
972
+  display: inline-block;
973
+  float: right;
974
+  cursor: pointer;
975
+  width: 20px;
976
+  color: #c2e9ff;
977
+  text-align: center;
978
+  font-size: 15px;
979
+}
980
+
981
+[data-theme-dark] #filespickednc .indivflpckd,
982
+[data-theme-dark-highcontrast] #filespickednc .indivflpckd {
983
+  display: inline-block;
984
+  position: relative;
985
+  height: auto;
986
+  max-width: 90%;
987
+  overflow: visible;
988
+  white-space: normal;
989
+  word-break: break-all;
990
+  text-overflow: ellipsis;
991
+  font-size: 15px;
992
+  color: #c2e9ff;
993
+}
994
+
995
+[data-theme-dark] .indpckfldl,
996
+[data-theme-dark-highcontrast] .indpckfldl {
997
+  position: relative;
998
+  display: inline-block;
999
+  float: right;
1000
+  cursor: pointer;
1001
+  width: 20px;
1002
+  color: #c2e9ff;
1003
+  text-align: center;
1004
+}
0 1005
new file mode 100644
1 1006
Binary files /dev/null and b/img/pax_fax_received_fax.png differ
2 1007
new file mode 100644
3 1008
Binary files /dev/null and b/img/pax_fax_send_uploaded_file_as_fax.png differ
4 1009
new file mode 100644
... ...
@@ -0,0 +1,818 @@
1
+/**
2
+ * @copyright 2021 Double Bastion LLC <www.doublebastion.com>
3
+ *
4
+ * @author Double Bastion LLC
5
+ *
6
+ * @license GNU AGPL version 3 or any later version
7
+ *
8
+ * This program is free software; you can redistribute it and/or
9
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
10
+ * License as published by the Free Software Foundation; either
11
+ * version 3 of the License, or any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
17
+ *
18
+ * You should have received a copy of the GNU Affero General Public
19
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+$(document).ready(function() {
24
+
25
+  var readtxtfile = [];
26
+  var readhtmlfile = [];
27
+  var readjpg = [];
28
+  var readpng = [];
29
+
30
+  // Adjust the path, so that the uploaded pdf files can be previewed while Nextcloud is served on a subdomain or on a subdirectory, by Nginx or by Apache
31
+  var locHref = window.location.href;
32
+  var pathSplit = locHref.split('/');
33
+  var firstPathEl = '';
34
+  if (pathSplit.length == 7) { firstPathEl = '/' + pathSplit[3]; }
35
+
36
+  // Check the available balance
37
+  $("#checkbalance").on("click", function(event) {
38
+
39
+     $('#checkbalance').addClass('icon-loading');
40
+
41
+     var getbalanceUrl = OC.generateUrl("/apps/pax_fax/user/getbalance");
42
+
43
+     $.ajax({
44
+          url: getbalanceUrl,
45
+          type: "POST",
46
+          cache: false,
47
+          processData: false,
48
+          contentType: false,
49
+          success: function(faxbalance) {
50
+
51
+                     if (faxbalance != "n/a") {
52
+                         var balanceindlrs = faxbalance / 100;
53
+                         var balanceproc = "$ " + balanceindlrs.toFixed(2);
54
+                         $('#currentbalance').text(balanceproc);
55
+                     } else { 
56
+                         $('#currentbalance').text("n/a"); 
57
+                     }
58
+
59
+                     $('#checkbalance').removeClass('icon-loading');
60
+          }
61
+     });
62
+  });
63
+
64
+  // Select the Caller ID
65
+  $("#selectcalleridbttn").on("click", function(event) {
66
+
67
+     $('#selectcalleridbttn').addClass('icon-loading');
68
+
69
+     var getfaxnumbersUrl = OC.generateUrl("/apps/pax_fax/user/getfaxnumbers");
70
+     var selectednmbr = null;
71
+
72
+     $.ajax({
73
+          url: getfaxnumbersUrl,
74
+          type: "POST",
75
+          cache: false,
76
+          processData: false,
77
+          contentType: false,
78
+          success: function(faxnmbrs) {
79
+
80
+                    $('#currentfaxnmbrs').empty();
81
+                    $('#currentfaxnmbrs').append("<option value='' selected='selected' disabled class='optselectfxnb'>Choose an ID</option>");
82
+                    if (faxnmbrs.provider == "phaxio") {
83
+                        $('#currentfaxnmbrs').append("<option value='' class='optselectfxnb'>Blank Caller ID</option>");
84
+                    }
85
+
86
+                    $.each(faxnmbrs.nblist, function(key, indfxnmb) {
87
+                           $('#currentfaxnmbrs').append("<option value='"+indfxnmb+"' class='optselectfxnb'>"+indfxnmb+"</option>");
88
+                    });
89
+
90
+                    $('#selectcalleridbttn').removeClass('icon-loading');
91
+          }
92
+     });
93
+  });
94
+
95
+  // Clean the Pax_Fax/temp_files directory
96
+  var cleanflUrl = OC.generateUrl("/apps/pax_fax/user/cleantempdir");
97
+
98
+  $.ajax({
99
+          url: cleanflUrl,
100
+          type: "POST",
101
+          cache: false,
102
+          processData: false,
103
+          contentType: false
104
+  });
105
+
106
+  var n = 1;
107
+  var uploadedtofax = [];
108
+
109
+  // Upload files to be faxed
110
+  $("#uploadfileforfax").change(function(e){
111
+
112
+     OC.msg.startAction("#pf_upload_msg", t("pax_fax", "Uploading ..."));
113
+     $('#faxdocpreview').addClass('icon-loading');
114
+     $('#filestotsize').show();
115
+
116
+     var baseUrl = OC.generateUrl("/apps/pax_fax/user/uploadfile");
117
+
118
+     var formData = new FormData();
119
+     formData.append('uploadfileforfax', $('#uploadfileforfax')[0].files[0]);
120
+
121
+     var currentflsize = $('#uploadfileforfax')[0].files[0].size;
122
+
123
+     var fileup = $('#uploadfileforfax').val();
124
+     var fileuptrim = fileup.split('\\').pop();
125
+
126
+     if ($.inArray(fileuptrim, uploadedtofax) != -1) {
127
+         var duplicatescheck = 1;
128
+     } else var duplicatescheck = 0;
129
+
130
+     var extension = fileup.replace(/^.*\./, '');
131
+
132
+     if (extension == fileup) {
133
+         extension = "";
134
+     } else {
135
+         extension = extension.toLowerCase();
136
+     }
137
+
138
+     var validExtensions = ["pdf", "doc", "docx", "tif", "tiff", "jpg", "jpeg", "odt", "txt", "html", "png"];
139
+
140
+     if ($.inArray(extension, validExtensions) != -1) {
141
+
142
+       if (duplicatescheck == 0) {
143
+
144
+         if (currentflsize < 20971520) {
145
+
146
+            if (n < 21) {
147
+
148
+               uploadedtofax.push(fileuptrim);
149
+
150
+               $.ajax({
151
+                 url: baseUrl,
152
+                 type: "POST",
153
+                 data: formData,
154
+                 cache: false,
155
+                 processData: false,
156
+                 contentType: false,
157
+                 success: function(totalflsize) {
158
+
159
+                   $('#filessizetext').text(totalflsize);
160
+
161
+                   // Check if the total file size is over 20 MB
162
+                   var rectotfilesz = parseFloat(totalflsize.replace(" MB", ""));
163
+
164
+                   if (rectotfilesz > 20.00) {
165
+                       $('#filestotsize').css('color', '#ba3555');
166
+                       alert("Error ! You can't send files having a total size of more than 20 MB in one fax call ! Please consider removing files so that the total files size would drop to or below 20 MB");
167
+                       $('#submitfax').attr("disabled", true);
168
+                   } else {
169
+                       $('#submitfax').attr("disabled", false);
170
+                       $('#filestotsize').css('color', '#1eb16a');
171
+                     }
172
+
173
+
174
+                   $('#fileuploadednm').append("<div class='indgenflcls'><div id='"+n+"indfilediv' class='indivflcls'>" + n + ") " + fileuptrim + "</div><div class='indupfldl'>X</div></div>");
175
+                   n++;
176
+
177
+                   // Preview the file when you click on its name
178
+                   $("div:visible[id*='indfilediv']").each(function() {
179
+                        $(this).on("click", function(eventclck) {
180
+                           var faxfilenameinit = $(this).text();
181
+                           var faxfilenamesec = faxfilenameinit.substring(faxfilenameinit.indexOf(" ") + 1);
182
+                           var faxfilename = faxfilenamesec.replace("X","");
183
+                           var baseUrl = firstPathEl+"/remote.php/webdav/Pax_Fax/temp_files/"+faxfilename;
184
+                           var extenlst = faxfilename.replace(/^.*\./, '');
185
+
186
+                           if (extenlst == faxfilename) {
187
+                               extenlst = "";
188
+                           } else {
189
+                               extenlst = extenlst.toLowerCase();
190
+                           }
191
+
192
+                           if (extenlst == 'pdf') {
193
+                                  var viewerclick = OC.generateUrl('/apps/files_pdfviewer/?file={file}', {file: baseUrl});
194
+                                  var $iframe = $('<iframe id="docclickview" style="width:100%;height:100%;display:block;position:absolute;top:0;left:0;z-index:1041;" src="' + viewerclick + '" sandbox="allow-scripts allow-same-origin allow-popups allow-modals"></iframe>');
195
+                                  $("#faxdocpreview").empty();
196
+                                  $("#faxdocpreview").append($iframe);
197
+                           } else if (extenlst == 'txt') {
198
+                                  $("#faxdocpreview").empty();
199
+                                  $("#faxdocpreview").append(readtxtfile[faxfilename]);
200
+                           } else if (extenlst == 'html') {
201
+                                  $("#faxdocpreview").empty();
202
+                                  $("#faxdocpreview").append(readhtmlfile[faxfilename]);
203
+                           } else if (extenlst == 'jpg' || extenlst == 'jpeg') {
204
+                                  $("#faxdocpreview").empty();
205
+                                  $("#faxdocpreview").append('<img style="width:100%;height:100%" id="uploadedjpg" src="#" />');
206
+                                  $("#uploadedjpg").attr('src', readjpg[faxfilename]);
207
+                           } else if (extenlst == 'png') {
208
+                                  $("#faxdocpreview").empty();
209
+                                  $("#faxdocpreview").append('<img style="width:100%;height:100%" id="uploadedpng" src="#" />');
210
+                                  $("#uploadedpng").attr('src', readpng[faxfilename]);
211
+                           } else if (extenlst == 'odt') {
212
+                                  $("#faxdocpreview").empty();
213
+                                  function odfInit() {
214
+                                     var odfelement = document.getElementById("faxdocpreview");
215
+                                     odfcanvas = new odf.OdfCanvas(odfelement);
216
+                                     odfcanvas.load(baseUrl);
217
+                                  }
218
+                                  window.setTimeout(odfInit, 0);
219
+                           } else if (extenlst == 'tif' || extenlst == 'tiff') {
220
+                                  var tiffile = '/remote.php/webdav/Pax_Fax/temp_files/'+faxfilename;
221
+                                  var xhr = new XMLHttpRequest();
222
+                                  xhr.responseType = 'arraybuffer';
223
+                                  xhr.open('GET', tiffile);
224
+                                  xhr.onload = function (evnt) {
225
+                                      var tiff = new Tiff({buffer: xhr.response});
226
+                                      var tifcanvas = tiff.toCanvas();
227
+                                      $("#faxdocpreview").empty();
228
+                                      $("#faxdocpreview").append(tifcanvas);
229
+                                  };
230
+                                  xhr.send();
231
+                           }
232
+
233
+                           $("#faxdocpreview").show();
234
+                           $("#faxfoldersview").hide();
235
+                        });
236
+                   });
237
+
238
+                   // Remove uploaded files
239
+                   $('[class*="indupfldl"]').last().click(function() {
240
+
241
+                           var baseUrl = OC.generateUrl("/apps/pax_fax/user/removeupfile");
242
+
243
+                           var removedfilenameinit = $(this).closest('[class*="indgenflcls"]').find('[class*="indivflcls"]').text();
244
+
245
+                           var removedfilesplit = removedfilenameinit.split(") ");
246
+                           var removedflnb = parseInt(removedfilesplit[0]);
247
+
248
+                           $(this).closest('[class*="indgenflcls"]').find('[class*="indivflcls"]').hide();
249
+                           $(this).hide();
250
+
251
+                           var removedfilename = removedfilenameinit.substring(removedfilenameinit.indexOf(" ") + 1);
252
+
253
+                           uploadedtofax = $.grep(uploadedtofax, function(value) {
254
+                                           return value != removedfilename;
255
+                           });
256
+
257
+                           $.ajax({
258
+                                   url: baseUrl,
259
+                                   type: "POST",
260
+                                   data: { removedfilename: removedfilename },
261
+                                   success: function(totalflsize) {
262
+
263
+                                      $('#filessizetext').text(totalflsize);
264
+
265
+                                      // Check file size
266
+                                      var rectotfilesz = parseFloat(totalflsize.replace(" MB", ""));
267
+
268
+                                      if (rectotfilesz > 20.00) {
269
+                                          $('#filestotsize').css('color', '#ba3555');
270
+                                             alert("Error ! You can't send files having a total size of more than 20 MB in one fax call ! Please consider removing files so that the total files size would drop to or below 20 MB");
271
+                                          $('#submitfax').attr("disabled", true);
272
+                                      } else {
273
+                                          $('#submitfax').attr("disabled", false);
274
+                                          $('#filestotsize').css('color', '#1eb16a');
275
+                                        }
276
+
277
+                                      // Rewrite order numbers for files that follow
278
+                                      --n;
279
+                                      $("div:visible[id*='indfilediv']").each(function() {
280
+
281
+                                          var getdivtext =  $(this).text();
282
+                                          var splitdivtext = getdivtext.split(") ");
283
+                                          var currentnbvalue = parseInt(splitdivtext[0]);
284
+                                          var newnbvalue = currentnbvalue - 1;
285
+
286
+                                          if (currentnbvalue > removedflnb) {
287
+                                              var replacedstr = newnbvalue + ") " + splitdivtext[1];
288
+                                              $(this).text(replacedstr);
289
+                                          }
290
+                                      });
291
+
292
+                                      $("div:visible[id*='indflpicked']").each(function() {
293
+
294
+                                          var getdivtext =  $(this).text();
295
+                                          var splitdivtext = getdivtext.split(") ");
296
+                                          var currentnbvalue = parseInt(splitdivtext[0]);
297
+                                          var newnbvalue = currentnbvalue - 1;
298
+
299
+                                          if (currentnbvalue > removedflnb) {
300
+                                              var replacedstr = newnbvalue + ") " + splitdivtext[1];
301
+                                              $(this).text(replacedstr);
302
+                                          }
303
+                                      });
304
+
305
+                                   },
306
+                                   error: function() {
307
+                                          alert('Error !');
308
+                                   }
309
+                           });
310
+
311
+                           $('#faxdocpreview').removeClass('icon-loading');
312
+                           $("#faxdocpreview").empty();
313
+                   });
314
+
315
+                   // Preview the uploaded file
316
+                   var faxfilename = e.target.files[0].name;
317
+                   var baseUrl = firstPathEl+"/remote.php/webdav/Pax_Fax/temp_files/"+faxfilename;
318
+
319
+                   if (extension == 'pdf') {
320
+                              var viewer = OC.generateUrl('/apps/files_pdfviewer/?file={file}', {file: baseUrl});
321
+                              var $iframe = $('<iframe id="docviewer" style="width:100%;height:100%;display:block;position:absolute;top:0;left:0;z-index:1041;" src="' + viewer + '" sandbox="allow-scripts allow-same-origin allow-popups allow-modals"></iframe>');
322
+                              $("#faxdocpreview").empty();
323
+                              $("#faxdocpreview").append($iframe);
324
+                   } else if (extension == 'txt') {
325
+                              var reader = new FileReader();
326
+                              reader.readAsText(e.target.files[0]);
327
+                              reader.onload = function(e) {
328
+                                  readtxtfile[faxfilename] = e.target.result.replace(/(?:\r\n|\r|\n)/g, '<br>');
329
+                                  $("#faxdocpreview").empty();
330
+                                  $("#faxdocpreview").append(readtxtfile[faxfilename]);
331
+                              };
332
+                   } else if (extension == 'html') {
333
+                              var reader = new FileReader();
334
+                              reader.readAsText(e.target.files[0]);
335
+                              reader.onload = function(e) {
336
+                                  readhtmlfile[faxfilename] = e.target.result.replace(/(?:\r\n|\r|\n)/g, '<br>');
337
+                                  $("#faxdocpreview").empty();
338
+                                  $("#faxdocpreview").append(readhtmlfile[faxfilename]);
339
+                              };
340
+                   } else if (extension == 'jpg' || extension == 'jpeg') {
341
+                              $("#faxdocpreview").empty();
342
+                              $("#faxdocpreview").append('<img style="width:100%;height:100%" id="uploadedjpg" src="#" />');
343
+
344
+                              var reader = new FileReader();
345
+                              reader.onload = function (e) {
346
+                                  readjpg[faxfilename] = e.target.result;
347
+                                  $("#uploadedjpg").attr('src', readjpg[faxfilename]);
348
+                              }
349
+                              reader.readAsDataURL(e.target.files[0]);
350
+                   } else if (extension == 'png') {
351
+                              $("#faxdocpreview").empty();
352
+                              $("#faxdocpreview").append('<img style="width:100%;height:100%" id="uploadedpng" src="#" />');
353
+
354
+                              var reader = new FileReader();
355
+                              reader.onload = function (e) {
356
+                                  readpng[faxfilename] = e.target.result;
357
+                                  $("#uploadedpng").attr('src', readpng[faxfilename]);
358
+                              }
359
+                              reader.readAsDataURL(e.target.files[0]);
360
+                   } else if (extension == 'odt') {
361
+                              $("#faxdocpreview").empty();
362
+                              function odfInit() {
363
+                                 var odfelement = document.getElementById("faxdocpreview");
364
+                                 odfcanvas = new odf.OdfCanvas(odfelement);
365
+                                 odfcanvas.load(baseUrl);
366
+                              }
367
+                              window.setTimeout(odfInit, 0);
368
+                   } else if (extension == 'tif' || extension == 'tiff') {
369
+                              var tiffile = '/remote.php/webdav/Pax_Fax/temp_files/'+faxfilename;
370
+                              var xhr = new XMLHttpRequest();
371
+                              xhr.responseType = 'arraybuffer';
372
+                              xhr.open('GET', tiffile);
373
+                              xhr.onload = function (e) {
374
+                                  var tiff = new Tiff({buffer: xhr.response});
375
+                                  var tifcanvas = tiff.toCanvas();
376
+                                  $("#faxdocpreview").empty();
377
+                                  $("#faxdocpreview").append(tifcanvas);
378
+                              };
379
+                              xhr.send();
380
+                   }
381
+
382
+                   $("#faxdocpreview").show();
383
+                   $('#pf_upload_msg').hide();
384
+                   $('#faxdocpreview').removeClass('icon-loading');
385
+                   $("#faxfoldersview").hide();
386
+                 },
387
+                 error: function(data){
388
+                     alert('Error!');
389
+                 }
390
+               });
391
+
392
+            } else {
393
+                  alert("Error ! You can't send as fax more than 20 files in one fax call !");
394
+                  $('#pf_upload_msg').hide();
395
+                  $('#faxdocpreview').removeClass('icon-loading');
396
+              }
397
+         } else {
398
+              alert("Error ! You can't send files having a total size of more than 20 MB in one fax call !");
399
+              $('#pf_upload_msg').hide();
400
+              $('#faxdocpreview').removeClass('icon-loading');
401
+           }
402
+       } else {
403
+            alert("Error ! There is already a file named '"+fileuptrim+"' in the 'Pax_Fax/temp_files' folder !");
404
+            $('#pf_upload_msg').hide();
405
+            $('#faxdocpreview').removeClass('icon-loading');
406
+         }
407
+
408
+     } else {
409
+          alert('The file type is not supported ! Supported formats are: pdf, doc, docx, tiff/tif, jpeg/jpg, odt, txt, html, png.');
410
+          $('#pf_upload_msg').hide();
411
+          $('#faxdocpreview').removeClass('icon-loading');
412
+       }
413
+  });
414
+
415
+
416
+  // Pick file to fax, from Nextcloud
417
+  var faxfilename = null;
418
+
419
+  $("#choosefilen").on("click", function(evn) {
420
+
421
+                OC.dialogs.filepicker(
422
+                        t('settings', "Select a file to send as fax."),
423
+                        function (path) {
424
+
425
+                              OC.msg.startAction("#pf_choose_msg", t("pax_fax", "Please wait ..."));
426
+                              $('#faxdocpreview').addClass('icon-loading');
427
+                              $('#filestotsize').show();
428
+
429
+                              var baseUrl = OC.generateUrl("/apps/pax_fax/user/pickfile");
430
+
431
+                              faxfilename = path.split('/').pop();
432
+
433
+                              if ($.inArray(faxfilename, uploadedtofax) != -1) {
434
+                                  var duplicatescheck = 1;
435
+                              } else var duplicatescheck = 0;
436
+
437
+                              var extension = faxfilename.replace(/^.*\./, '');
438
+
439
+                              if (extension == faxfilename) {
440
+                                  extension = "";
441
+                              } else {
442
+                                  extension = extension.toLowerCase();
443
+                              }
444
+
445
+                              var validExtensions = ["pdf", "doc", "docx", "tif", "tiff", "jpg", "jpeg", "odt", "txt", "html", "png"];
446
+
447
+                              if ($.inArray(extension, validExtensions) != -1) {
448
+
449
+                                 if (duplicatescheck == 0) {
450
+
451
+                                    if (n < 21) {
452
+
453
+                                       uploadedtofax.push(faxfilename);
454
+
455
+                                       $.ajax({
456
+                                          url: baseUrl,
457
+                                          type: "POST",
458
+                                          data: { path: path },
459
+                                          success: function(totalflsize) {
460
+
461
+                                                $('#filessizetext').text(totalflsize);
462
+
463
+                                                // Check if the total file size is over 20 MB
464
+                                                var rectotfilesz = parseFloat(totalflsize.replace(" MB", ""));
465
+
466
+                                                if (rectotfilesz > 20.00) {
467
+                                                    $('#filestotsize').css('color', '#ba3555');
468
+                                                    alert("Error ! You can't send files having a total size of more than 20 MB in one fax call ! Please consider removing files so that the total files size would drop to or below 20 MB");
469
+                                                    $('#submitfax').attr("disabled", true);
470
+                                                } else {
471
+                                                    $('#submitfax').attr("disabled", false);
472
+                                                    $('#filestotsize').css('color', '#1eb16a');
473
+                                                }
474
+
475
+                                                $('#filespickednc').append("<div class='indgenpckfls'><div id='"+n+"indflpicked' class='indivflpckd'>" + n + ") " + faxfilename + "</div><div class='indpckfldl'>X</div></div>");
476
+                                                n++;
477
+
478
+                                                // Preview each file when you click on its name
479
+                                                $("div:visible[id*='indflpicked']").each(function() {
480
+                                                   $(this).on("click", function(event) {
481
+                                                      var faxfilenameinit = $(this).text();
482
+                                                      var faxfilenamesec = faxfilenameinit.substring(faxfilenameinit.indexOf(" ") + 1);
483
+                                                      var faxfilenamesp = faxfilenamesec.replace("X","");
484
+                                                      var baseUrl = firstPathEl+"/remote.php/webdav/Pax_Fax/temp_files/"+faxfilenamesp;
485
+                                                      var extenlst = faxfilenamesp.replace(/^.*\./, '');
486
+
487
+                                                      if (extenlst == faxfilenamesp) {
488
+                                                           extenlst = "";
489
+                                                      } else {
490
+                                                           extenlst = extenlst.toLowerCase();
491
+                                                      }
492
+
493
+                                                      if (extenlst == 'pdf') {
494
+                                                           var viewerclick = OC.generateUrl('/apps/files_pdfviewer/?file={file}', {file: baseUrl});
495
+                                                           var $iframe = $('<iframe id="docclickview" style="width:100%;height:100%;display:block;position:absolute;top:0;left:0;z-index:1041;" src="' + viewerclick + '" sandbox="allow-scripts allow-same-origin allow-popups allow-modals"></iframe>');
496
+                                                           $("#faxdocpreview").empty();
497
+                                                           $("#faxdocpreview").append($iframe);
498
+                                                      } else if (extenlst == 'txt') {
499
+                                                              $("#faxdocpreview").empty();
500
+                                                              $("#faxdocpreview").append(readtxtfile[faxfilenamesp]);
501
+                                                      } else if (extenlst == 'html') {
502
+                                                              $("#faxdocpreview").empty();
503
+                                                              $("#faxdocpreview").append(readhtmlfile[faxfilenamesp]);
504
+                                                      } else if (extenlst == 'jpg' || extenlst == 'jpeg') {
505
+                                                              $("#faxdocpreview").empty();
506
+                                                              $("#faxdocpreview").append('<img style="width:auto;height:auto" id="uploadedjpg" src="'+ baseUrl +'" />');
507
+                                                      } else if (extenlst == 'png') {
508
+                                                              $("#faxdocpreview").empty();
509
+                                                              $("#faxdocpreview").append('<img style="width:auto;height:auto" id="uploadedpng" src="'+ baseUrl +'" />');
510
+                                                      } else if (extenlst == 'odt') {
511
+                                                              $("#faxdocpreview").empty();
512
+                                                              function odfInit() {
513
+                                                                 var odfelement = document.getElementById("faxdocpreview");
514
+                                                                 odfcanvas = new odf.OdfCanvas(odfelement);
515
+                                                                 odfcanvas.load(baseUrl);
516
+                                                              }
517
+                                                              window.setTimeout(odfInit, 0);
518
+                                                      } else if (extenlst == 'tif' || extenlst == 'tiff') {
519
+                                                              var tiffile = '/remote.php/webdav/Pax_Fax/temp_files/'+faxfilenamesp;
520
+                                                              var xhr = new XMLHttpRequest();
521
+                                                              xhr.responseType = 'arraybuffer';
522
+                                                              xhr.open('GET', tiffile);
523
+                                                              xhr.onload = function (evnt) {
524
+                                                                  var tiff = new Tiff({buffer: xhr.response});
525
+                                                                  var tifcanvas = tiff.toCanvas();
526
+                                                                  $("#faxdocpreview").empty();
527
+                                                                  $("#faxdocpreview").append(tifcanvas);
528
+                                                              };
529
+                                                              xhr.send();
530
+                                                      }
531
+
532
+                                                      $("#faxdocpreview").show();
533
+                                                      $("#faxfoldersview").hide();
534
+                                                   });
535
+                                                });
536
+
537
+                                                // Remove picked files
538
+                                                $('[class*="indpckfldl"]').last().click(function() {
539
+
540
+                                                    var baseUrl = OC.generateUrl("/apps/pax_fax/user/removeupfile");
541
+
542
+                                                    var removedfilenameinit = $(this).closest('[class*="indgenpckfls"]').find('[class*="indivflpckd"]').text();
543
+
544
+                                                    var removedfilesplit = removedfilenameinit.split(") ");
545
+                                                    var removedflnb = parseInt(removedfilesplit[0]);
546
+
547
+                                                    $(this).closest('[class*="indgenpckfls"]').find('[class*="indivflpckd"]').hide();
548
+                                                    $(this).hide();
549
+                                                    var removedfilename = removedfilenameinit.substring(removedfilenameinit.indexOf(" ") + 1);
550
+
551
+                                                    uploadedtofax = $.grep(uploadedtofax, function(value) {
552
+                                                             return value != removedfilename;
553
+                                                    });
554
+
555
+                                                    $.ajax({
556
+                                                        url: baseUrl,
557
+                                                        type: "POST",
558
+                                                        data: { removedfilename: removedfilename },
559
+                                                        success: function(totalflsize) {
560
+
561
+                                                             $('#filessizetext').text(totalflsize);
562
+
563
+                                                             // Check file size
564
+                                                             var rectotfilesz = parseFloat(totalflsize.replace(" MB", ""));
565
+
566
+                                                             if (rectotfilesz > 20.00) {
567
+                                                                 $('#filestotsize').css('color', '#ba3555');
568
+                                                                 alert("Error ! You can't send files having a total size of more than 20 MB in one fax call ! Please consider removing files so that the total files size would drop at or below 20 MB");
569
+                                                                 $('#submitfax').attr("disabled", true);
570
+                                                             } else {
571
+                                                                 $('#submitfax').attr("disabled", false);
572
+                                                                 $('#filestotsize').css('color', '#1eb16a');
573
+                                                               }
574
+
575
+                                                             // Rewrite order numbers for files that follow
576
+                                                             --n;
577
+                                                             $("div:visible[id*='indflpicked']").each(function() {
578
+
579
+                                                                  var getdivtext =  $(this).text();
580
+                                                                  var splitdivtext = getdivtext.split(") ");
581
+                                                                  var currentnbvalue = parseInt(splitdivtext[0]);
582
+                                                                  var newnbvalue = currentnbvalue - 1;
583
+
584
+                                                                  if (currentnbvalue > removedflnb) {
585
+                                                                      var replacedstr = newnbvalue + ") " + splitdivtext[1];
586
+                                                                      $(this).text(replacedstr);
587
+                                                                  }
588
+                                                             });
589
+                                                        },
590
+                                                        error: function() {
591
+                                                             alert('Error !');
592
+                                                        }
593
+                                                    });
594
+
595
+                                                    $('#faxdocpreview').removeClass('icon-loading');
596
+                                                    $("#faxdocpreview").empty();
597
+                                                });
598
+
599
+
600
+		                                // Preview the picked file
601
+		                                var flUrl = firstPathEl+"/remote.php/webdav/Pax_Fax/temp_files/"+faxfilename;
602
+		                                var pickUrl = OC.generateUrl("/apps/pax_fax/user/getpickedfile");
603
+
604
+		                                if (extension == 'pdf') {
605
+		                                    var viewer = OC.generateUrl('/apps/files_pdfviewer/?file={file}', {file: flUrl});
606
+		                                    var $iframe = $('<iframe id="docviewer" style="width:100%;height:100%;display:block;position:absolute;top:0;left:0;z-index:1041;" src="' + viewer + '" sandbox="allow-scripts allow-same-origin allow-popups allow-modals"></iframe>');
607
+		                                    $("#faxdocpreview").empty();
608
+		                                    $("#faxdocpreview").append($iframe);
609
+		                                } else if (extension == 'txt') {
610
+						           $.get(flUrl, function(textdata) {
611
+		                                             readtxtfile[faxfilename] = textdata.replace(/(?:\r\n|\r|\n)/g, '<br>');
612
+		                                             $("#faxdocpreview").empty();
613
+		                                             $("#faxdocpreview").append(readtxtfile[faxfilename]);
614
+							   });
615
+		                                } else if (extension == 'html') {
616
+							   $.get(flUrl, function(htmldata) {
617
+		                                             readhtmlfile[faxfilename] = htmldata.replace(/(?:\r\n|\r|\n)/g, '<br>');
618
+		                                             $("#faxdocpreview").empty();
619
+		                                             $("#faxdocpreview").append(readhtmlfile[faxfilename]);
620
+							   });
621
+		                                } else if (extension == 'jpg' || extension == 'jpeg') {
622
+		                                           $("#faxdocpreview").empty();
623
+		                                           $("#faxdocpreview").append('<img style="width:auto;height:auto" id="uploadedjpg" src="'+ flUrl +'" />');
624
+		                                } else if (extension == 'png') {
625
+		                                           $("#faxdocpreview").empty();
626
+		                                           $("#faxdocpreview").append('<img style="width:auto;height:auto" id="uploadedpng" src="'+ flUrl +'" />');
627
+                                                           $("#uploadedpng").attr('src', readpng[faxfilename]);
628
+		                                } else if (extension == 'odt') {
629
+		                                       $("#faxdocpreview").empty();
630
+		                                       function odfInit() {
631
+		                                           var odfelement = document.getElementById("faxdocpreview");
632
+		                                           odfcanvas = new odf.OdfCanvas(odfelement);
633
+		                                           odfcanvas.load(flUrl);
634
+		                                       }
635
+		                                       window.setTimeout(odfInit, 0);
636
+
637
+		                                } else if (extension == 'tif' || extension == 'tiff') {
638
+		                                       var tiffile = '/remote.php/webdav/Pax_Fax/temp_files/'+faxfilename;
639
+		                                       var xhr = new XMLHttpRequest();
640
+		                                       xhr.responseType = 'arraybuffer';
641
+		                                       xhr.open('GET', tiffile);
642
+		                                       xhr.onload = function (event) {
643
+		                                           var tiff = new Tiff({buffer: xhr.response});
644
+		                                           var tifcanvas = tiff.toCanvas();
645
+		                                           $("#faxdocpreview").empty();
646
+		                                           $("#faxdocpreview").append(tifcanvas);
647
+		                                       };
648
+		                                       xhr.send();
649
+		                                }
650
+
651
+		                                $("#faxdocpreview").show();
652
+
653
+		                                $('#pf_choose_msg').hide();
654
+		                                $('#faxdocpreview').removeClass('icon-loading');
655
+		                                $("#faxfoldersview").hide();
656
+
657
+                                          },
658
+
659
+                                          error: function(data){
660
+                                             alert('Error!');
661
+                                          }
662
+
663
+                                       });
664
+
665
+                                    } else {
666
+                                        alert("Error ! You can't fax more than 20 files in one fax call !");
667
+                                        $('#pf_choose_msg').hide();
668
+                                        $('#faxdocpreview').removeClass('icon-loading');
669
+                                      }
670
+                                 } else {
671
+                                      alert("Error ! There is already a file named '"+faxfilename+"' in the 'Pax_Fax/temp_files' folder !");
672
+                                      $('#pf_choose_msg').hide();
673
+                                      $('#faxdocpreview').removeClass('icon-loading');
674
+                                   }
675
+
676
+                              } else {
677
+                                   alert('The file type is not supported ! Supported formats are: pdf, doc, docx, tiff/tif, jpeg/jpg, odt, txt, html, png.');
678
+                                   $('#pf_choose_msg').hide();
679
+                                   $('#faxdocpreview').removeClass('icon-loading');
680
+                                }
681
+
682
+                        }
683
+                );
684
+  });
685
+
686
+
687
+  // Submit the fax
688
+  $("#submitfax").on("click", function(event){
689
+
690
+     var selectedcid = $('#currentfaxnmbrs :selected').text();
691
+
692
+     var toNumberinit = $('#faxto').val();
693
+     var toNumbersec = toNumberinit.replace(/[^0-9,]/g, "");
694
+     var toNumber = toNumbersec.split(",");
695
+
696
+     for (var v = 0; v < toNumber.length; v++) {
697
+         toNumber[v] = "+" + toNumber[v];
698
+     }
699
+
700
+     OC.msg.startAction("#pf_submit_msg", t("pax_fax", "Sending fax ... Please wait !"));
701
+     $('#faxdocpreview').addClass('icon-loading');
702
+
703
+     $('#submitfax').attr("disabled", true);
704
+
705
+     var baseUrl = OC.generateUrl("/apps/pax_fax/user/sendfax");
706
+
707
+     var toNumberwc = toNumberinit.replace(/[^0-9]/g, "");
708
+
709
+     if (uploadedtofax.length != 0) {
710
+
711
+         if (toNumberwc != '') {
712
+
713
+             $.ajax({
714
+                url: baseUrl,
715
+                type: "POST",
716
+                data: {
717
+                       uploadedtofax: uploadedtofax,
718
+                       selectedcid: selectedcid,
719
+                       toNumber: toNumber
720
+                      },
721
+                success: function(phaxioresult) {
722
+
723
+                   if (phaxioresult.success == true) {
724
+                       alert("The fax has been sent successfully ! You can see the sent fax by clicking on the 'Sent Faxes' button.");
725
+                   } else {
726
+                       alert("Error ! The fax couldn't be sent because of the following error: "+ phaxioresult.errortype +" You can see the failed fax by clicking on the 'Failed Sent Faxes' button.");
727
+                   }
728
+
729
+                   $("div:visible[id*='indfilediv']").hide();
730
+                   $("div:visible[id*='indflpicked']").hide();
731
+                   $('[class*="indupfldl"]').hide();
732
+                   $('[class*="indpckfldl"]').hide();
733
+                   $('#faxdocpreview').hide();
734
+                   $('#filestotsize').hide();
735
+                   $('#pf_submit_msg').hide();
736
+                },
737
+                error: function(phaxioresult) {
738
+
739
+                   alert('Error ! Please check your settings !');
740
+
741
+                   $("div:visible[id*='indfilediv']").hide();
742
+                   $("div:visible[id*='indflpicked']").hide();
743
+                   $('[class*="indupfldl"]').hide();
744
+                   $('[class*="indpckfldl"]').hide();
745
+                   $('#pf_submit_msg').hide();
746
+                   $('#filestotsize').hide();
747
+                   $('#faxdocpreview').hide();
748
+
749
+                   location.reload(true);
750
+                }
751
+             });
752
+
753
+         } else {
754
+              $('#pf_submit_msg').hide();
755
+              $('#faxdocpreview').removeClass('icon-loading');
756
+              alert("Please enter the fax number of the recipient !");
757
+         }
758
+
759
+     } else {
760
+              $('#pf_submit_msg').hide();
761
+              $('#faxdocpreview').removeClass('icon-loading');
762
+              alert("Please upload a file or pick a file from Nextcloud to send as fax !");
763
+     }
764
+  });
765
+
766
+  $("#receivedfaxdir").on("click", function(event){
767
+     $("#faxdocpreview").hide();
768
+     $("#faxfoldersview").show();
769
+     $("#faxfoldersview").addClass("icon-loading");
770
+     $("#faxfoldersview :last-child").remove();
771
+     var fxreceived = OC.generateUrl("/apps/files/?dir=/Pax_Fax/faxes_received");
772
+     $("#faxfoldersview").append("<iframe id='embeddedView' src='" + fxreceived + "' width='100%' height='100%'></iframe>");
773
+     $("#app-content").scrollTop(50);
774
+     setTimeout(function() { $("#faxfoldersview").removeClass("icon-loading"); }, 1000);
775
+  });
776
+
777
+  $("#sentfaxdir").on("click", function(event){
778
+     $("#faxdocpreview").hide();
779
+     $("#faxfoldersview").show();
780
+     $("#faxfoldersview").addClass("icon-loading");
781
+     $("#faxfoldersview :last-child").remove();
782
+     var fxsent = OC.generateUrl("/apps/files/?dir=/Pax_Fax/faxes_sent");
783
+     $("#faxfoldersview").append("<iframe id='embeddedView' src='" + fxsent + "' width='100%' height='100%'></iframe>");
784
+     $("#app-content").scrollTop(50);
785
+     setTimeout(function() { $("#faxfoldersview").removeClass("icon-loading"); }, 1000);
786
+  });
787
+
788
+  $("#receivedfaileddir").on("click", function(event){
789
+     $("#faxdocpreview").hide();
790
+     $("#faxfoldersview").show();
791
+     $("#faxfoldersview").addClass("icon-loading");
792
+     $("#faxfoldersview :last-child").remove();
793
+     var fxrecfailed = OC.generateUrl("/apps/files/?dir=/Pax_Fax/faxes_received_failed");
794
+     $("#faxfoldersview").append("<iframe id='embeddedView' src='" + fxrecfailed + "' width='100%' height='100%'></iframe>");
795
+     $("#app-content").scrollTop(50);
796
+     setTimeout(function() { $("#faxfoldersview").removeClass("icon-loading"); }, 1000);
797
+  });
798
+
799
+  $("#sentfaileddir").on("click", function(event){
800
+     $("#faxdocpreview").hide();
801
+     $("#faxfoldersview").show();
802
+     $("#faxfoldersview").addClass("icon-loading");
803
+     $("#faxfoldersview :last-child").remove();
804
+     var fxsentfailed = OC.generateUrl("/apps/files/?dir=/Pax_Fax/faxes_received_failed");
805
+     $("#faxfoldersview").append("<iframe id='embeddedView' src='" + fxsentfailed + "' width='100%' height='100%'></iframe>");
806
+     $("#app-content").scrollTop(50);
807
+     setTimeout(function() { $("#faxfoldersview").removeClass("icon-loading"); }, 1000);
808
+  });
809
+
810
+  $(".indivflpckd").on("click", function(event){
811
+     $("#faxfoldersview").hide();
812
+  });
813
+
814
+  $(".indivflcls").on("click", function(event){
815
+     $("#faxfoldersview").hide();
816
+  });
817
+
818
+});
0 819
new file mode 100644
... ...
@@ -0,0 +1,103 @@
1
+/**
2
+ * @copyright 2021 Double Bastion LLC <www.doublebastion.com>
3
+ *
4
+ * @author Double Bastion LLC
5
+ *
6
+ * @license GNU AGPL version 3 or any later version
7
+ *
8
+ * This program is free software; you can redistribute it and/or
9
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
10
+ * License as published by the Free Software Foundation; either
11
+ * version 3 of the License, or any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
17
+ *
18
+ * You should have received a copy of the GNU Affero General Public
19
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+$(document).ready(function() {
24
+
25
+  $("#save_fax_settings").on("click", function(event) {
26
+
27
+    event.preventDefault();
28
+    OC.msg.startAction("#paxfax_save_msg", t("pax_fax", "Saved"));
29
+
30
+    var baseUrl = OC.generateUrl("/apps/pax_fax/user/updatesettings");
31
+    var getnotify = 0;
32
+
33
+    if ($("#get_notification").is(':checked')) {
34
+        getnotify = 1;
35
+    }
36
+
37
+    var emailaddressinit = $("#notification_email").val();
38
+
39
+    function validate_email($email) {
40
+        var email_reg = /^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/;
41
+        return email_reg.test($email);
42
+    }
43
+
44
+    if (validate_email(emailaddressinit)) {
45
+         var notifyemail = emailaddressinit;
46
+    } else {
47
+         var notifyemail = '';
48
+    }
49
+
50
+    var datatosave = {
51
+                      apiKey: $("#api_key").val(),
52
+                      apiSecret: $("#api_secret").val(),
53
+                      webhookToken: $("#webhook_token").val(),
54
+                      receiveUrl: $("#receive_url").val(),
55
+                      sinchProjectId: $("#sinch_project_id").val(),
56
+                      sinchKeyId: $("#sinch_key_id").val(),
57
+                      sinchKeySecret: $("#sinch_key_secret").val(),
58
+                      sinchServiceId: $("#sinch_service_id").val(),
59
+                      sinchCallbackUrl: $("#sinch_callback_url").val(),
60
+                      getNotification: getnotify,
61
+                      notificationEmail: notifyemail
62
+    };
63
+
64
+    $.ajax({
65
+       method: 'PUT',
66
+       url: baseUrl,
67
+       contentType: 'application/json',
68
+       data: JSON.stringify(datatosave),
69
+       error: function(resp){
70
+                  alert('Error ! Please check your settings !');
71
+       }
72
+    });
73
+
74
+  });
75
+
76
+  var baseUrlget = OC.generateUrl("/apps/pax_fax/user/getsettings");
77
+
78
+  $.ajax({
79
+       method: 'GET',
80
+       url: baseUrlget,
81
+       contentType: 'application/json',
82
+       success: function(settingsfromdb) {
83
+          $("#api_key").val(settingsfromdb.api_key);
84
+          $("#api_secret").val(settingsfromdb.api_secret);
85
+          $("#webhook_token").val(settingsfromdb.webhook_token);
86
+          $("#receive_url").val(settingsfromdb.receive_url);
87
+          $("#sinch_project_id").val(settingsfromdb.sinch_project_id);
88
+          $("#sinch_key_id").val(settingsfromdb.sinch_key_id);
89
+          $("#sinch_key_secret").val(settingsfromdb.sinch_key_secret);
90
+          $("#sinch_service_id").val(settingsfromdb.sinch_service_id);
91
+          $("#sinch_callback_url").val(settingsfromdb.sinch_callback_url);
92
+          $("#notification_email").val(settingsfromdb.notification_email);
93
+
94
+          if (settingsfromdb.get_notification == 1) {
95
+              $("#get_notification").attr('checked', true);
96
+          } else {
97
+              $("#get_notification").attr('checked', false);
98
+          }
99
+       }
100
+  });
101
+
102
+});
103
+
0 104
new file mode 100644
... ...
@@ -0,0 +1,17 @@
1
+OC.L10N.register(
2
+    "pax_fax",
3
+    {
4
+    "Settings" : "Settings",
5
+    "Pax Fax" : "Pax Fax",
6
+    "Enter either your Phaxio credentials or your Sinch credentials in the fields from below:" : "Enter either your Phaxio credentials or your Sinch credentials in the fields from below:",
7
+    "Phaxio API Key" : "Phaxio API Key",
8
+    "Phaxio API Secret" : "Phaxio API Secret",
9
+    "Phaxio Webhook Token" : "Phaxio Webhook Token",
10
+    "I want to see a notification in Nextcloud when a new fax is received:" : "I want to see a notification in Nextcloud when a new fax is received:",
11
+    "I want to receive a notification to the email address from below, when a new fax is received" : "I want to receive a notification to the email address from below, when a new fax is received",
12
+    "Save" : "Save",
13
+    "New fax" : "New fax",
14
+    "New fax from Pax Fax" : "New fax from Pax Fax"
15
+},
16
+"nplurals=2; plural=(n != 1);");
17
+
0 18
new file mode 100644
... ...
@@ -0,0 +1,14 @@
1
+{ "translations": {
2
+    "Settings" : "Settings",
3
+    "Pax Fax" : "Pax Fax",
4
+    "Enter either your Phaxio credentials or your Sinch credentials in the fields from below:" : "Enter either your Phaxio credentials or your Sinch credentials in the fields from below:",
5
+    "Phaxio API Key" : "Phaxio API Key",
6
+    "Phaxio API Secret" : "Phaxio API Secret",
7
+    "Phaxio Webhook Token" : "Phaxio Webhook Token",
8
+    "I want to see a notification in Nextcloud when a new fax is received:" : "I want to see a notification in Nextcloud when a new fax is received:",
9
+    "I want to receive a notification to the email address from below, when a new fax is received" : "I want to receive a notification to the email address from below, when a new fax is received",
10
+    "Save" : "Save",
11
+    "New fax" : "New fax",
12
+    "New fax from Pax Fax" : "New fax from Pax Fax"
13
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
14
+}
0 15
new file mode 100644
... ...
@@ -0,0 +1,17 @@
1
+OC.L10N.register(
2
+    "pax_fax",
3
+    {
4
+    "Settings" : "Settings",
5
+    "Pax Fax" : "Pax Fax",
6
+    "Enter either your Phaxio credentials or your Sinch credentials in the fields from below:" : "Enter either your Phaxio credentials or your Sinch credentials in the fields from below:",
7
+    "Phaxio API Key" : "Phaxio API Key",
8
+    "Phaxio API Secret" : "Phaxio API Secret",
9
+    "Phaxio Webhook Token" : "Phaxio Webhook Token",
10
+    "I want to see a notification in Nextcloud when a new fax is received:" : "I want to see a notification in Nextcloud when a new fax is received:",
11
+    "I want to receive a notification to the email address from below, when a new fax is received" : "I want to receive a notification to the email address from below, when a new fax is received",
12
+    "Save" : "Save",
13
+    "New fax" : "New fax",
14
+    "New fax from Pax Fax" : "New fax from Pax Fax"
15
+},
16
+"nplurals=2; plural=(n != 1);");
17
+
0 18
new file mode 100644
... ...
@@ -0,0 +1,14 @@
1
+{ "translations": {
2
+    "Settings" : "Settings",
3
+    "Pax Fax" : "Pax Fax",
4
+    "Enter either your Phaxio credentials or your Sinch credentials in the fields from below:" : "Enter either your Phaxio credentials or your Sinch credentials in the fields from below:",
5
+    "Phaxio API Key" : "Phaxio API Key",
6
+    "Phaxio API Secret" : "Phaxio API Secret",
7
+    "Phaxio Webhook Token" : "Phaxio Webhook Token",
8
+    "I want to see a notification in Nextcloud when a new fax is received:" : "I want to see a notification in Nextcloud when a new fax is received:",
9
+    "I want to receive a notification to the email address from below, when a new fax is received" : "I want to receive a notification to the email address from below, when a new fax is received",
10
+    "Save" : "Save",
11
+    "New fax" : "New fax",
12
+    "New fax from Pax Fax" : "New fax from Pax Fax"
13
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
14
+}
0 15
new file mode 100644
... ...
@@ -0,0 +1,404 @@
1
+<?php
2
+/**
3
+ * @copyright 2021 Double Bastion LLC <www.doublebastion.com>
4
+ *
5
+ * @author Double Bastion LLC
6
+ *
7
+ * @license GNU AGPL version 3 or any later version
8
+ *
9
+ * This program is free software; you can redistribute it and/or
10
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
11
+ * License as published by the Free Software Foundation; either
12
+ * version 3 of the License, or any later version.
13
+ *
14
+ * This program is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
18
+ *
19
+ * You should have received a copy of the GNU Affero General Public
20
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
+ *
22
+ */
23
+
24
+declare(strict_types=1);
25
+
26
+namespace OCA\PaxFax\Controller;
27
+
28
+use OCP\AppFramework\ApiController;
29
+use OCP\IRequest;
30
+use OCP\AppFramework\Http\DataResponse;
31
+use OCP\AppFramework\OCSController;
32
+use OCP\IUserSession;
33
+use OCP\AppFramework\Controller;
34
+use OCP\Files\IAppData;
35
+use OCA\PaxFax\Service\PaxfaxService;
36
+use OCP\AppFramework\App;
37
+use OCP\Files\NotPermittedException;
38
+use OCP\Files\Folder;
39
+use OC\Files\Filesystem;
40
+use \ReflectionClass;
41
+use OCP\Notification;
42
+use OCP\Notification\INotification;
43
+use OCP\Notification\IManager;
44
+use OCP\Notification\IAction;
45
+use \DateTime;
46
+
47
+use Phaxio;
48
+use Phaxio\OperationResult;
49
+use Phaxio\Error\AuthenticationException;
50
+use Phaxio\Error\NotFoundException;
51
+use Phaxio\Error\InvalidRequestException;
52
+use Phaxio\Error\RateLimitException;
53
+use Phaxio\Error\APIConnectionException;
54
+use Phaxio\Error\GeneralException;
55
+
56
+
57
+class AuthorApiController extends ApiController {
58
+
59
+    private $service;
60
+    private $userId;
61
+    private $folder;
62
+    private $filesystem;
63
+    private $userSession;
64
+    private $manager;
65
+
66
+    public function __construct($appName, IRequest $request, IUserSession $userSession, PaxfaxService $service, Folder $folder, Filesystem $filesystem, $userId, IManager $manager) {
67
+        parent::__construct(
68
+                $appName,
69
+                $request,
70
+                'PUT, POST, GET, DELETE, PATCH',
71
+                'Authorization, Content-Type, Accept',
72
+                1728000);
73
+
74
+        $this->service = $service;
75
+        $this->userId = $userId;
76
+        $this->folder = $folder;
77
+        $this->filesystem = $filesystem;
78
+        $this->userSession = $userSession;
79
+	$this->manager = $manager;
80
+    }
81
+
82
+    /**
83
+     * @NoAdminRequired
84
+     */
85
+    public function object_to_array($obj) {
86
+        if(is_object($obj)) $obj = (array)$this->dismount($obj);
87
+        if(is_array($obj)) {
88
+           $new = array();
89
+           foreach($obj as $key => $val) {
90
+               $new[$key] = $this->object_to_array($val);
91
+           }
92
+        }
93
+        else $new = $obj;
94
+        return $new;
95
+    }
96
+
97
+    /**
98
+     * @NoAdminRequired
99
+     */
100
+    public function dismount($object) {
101
+        $reflectionClass = new ReflectionClass(get_class($object));
102
+        $array = array();
103
+        foreach ($reflectionClass->getProperties() as $property) {
104
+           $property->setAccessible(true);
105
+           $array[$property->getName()] = $property->getValue($object);
106
+           $property->setAccessible(false);
107
+        }
108
+        return $array;
109
+    }
110
+
111
+    /**
112
+     * @NoAdminRequired
113
+     */
114
+    public function isValidCallbackRequest($token, $url = null, $postParameters = null, $uploadedFiles = null, $signature = null) {
115
+
116
+	if (!$url) {
117
+	    $url = $_SERVER['REQUEST_SCHEME'] . "://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
118
+	}
119
+
120
+	if (!$postParameters) {
121
+	    $postParameters = $_REQUEST;
122
+	}
123
+
124
+	if (!$uploadedFiles) {
125
+	    $uploadedFiles = $_FILES;
126
+	}
127
+
128
+	if (!$signature) {
129
+	    $signature = $_SERVER['HTTP_X_PHAXIO_SIGNATURE'];
130
+	}
131
+
132
+	// Sort the array by keys
133
+	ksort($postParameters);
134
+
135
+	// Append the data array to the url string, with no delimiters
136
+	foreach ($postParameters as $key => $value) {
137
+		 $url .= $key . $value;
138
+	}
139
+
140
+	foreach ($uploadedFiles as $key => $value) {
141
+		 $url .= $key . sha1_file($value['tmp_name']);
142
+	}
143
+
144
+	$hmac = hash_hmac("sha1", $url, $token);
145
+	return $signature == $hmac;
146
+    }
147
+
148
+    /**
149
+     * @NoAdminRequired
150
+     * @NoCSRFRequired
151
+     */
152
+    public function receivefaxphaxio() {
153
+
154
+       $phaxiosignature = $_SERVER['HTTP_X_PHAXIO_SIGNATURE'];
155
+
156
+       $thisapicred = $this->service->getapicredentials($this->userId);
157
+       $phaxiowhtoken = $thisapicred[2];
158
+       $phaxiorecURL = $thisapicred[3];
159
+
160
+       // Verify Phaxio's signature
161
+       $signverify = $this->isValidCallbackRequest($phaxiowhtoken, $phaxiorecURL, null, null, $phaxiosignature);
162
+
163
+       if ($signverify) {
164
+
165
+           $fileContent = file_get_contents($_FILES['file']['tmp_name']);
166
+           $fileNameinit = $_FILES['file']['name'];
167
+
168
+           $fldate = date("Y-m-d_H-i-s_").gettimeofday()["usec"];
169
+
170
+           $gmtind = "UTC " . date('P');
171
+           $flmsdateinit = date("Y-m-d  H:i:s");
172
+           $flmsdate = $flmsdateinit . " " . $gmtind;
173
+
174
+           $fileNamesec = array_reverse(explode(".", $fileNameinit));
175
+           $filenameext = $fileNamesec[0];
176
+           array_shift($fileNamesec);
177
+
178
+           $fileName = implode("", $fileNamesec);
179
+
180
+           $faxid = str_replace("Fax-", "", $fileName);
181
+
182
+           $apiMode = 'live';
183
+
184
+           $apiKeys[$apiMode] = $thisapicred[0];
185
+           $apiSecrets[$apiMode] = $thisapicred[1];
186
+
187
+           $apiHost = 'https://api.phaxio.com/v2.1/';
188
+
189
+           $phaxio = new Phaxio($apiKeys[$apiMode], $apiSecrets[$apiMode], $apiHost);
190
+
191
+
192
+           try {
193
+                    $phaxioresultreq = $phaxio->doRequest("GET", 'faxes/' . $faxid);
194
+
195
+                    $fromnmbrtoarr = $this->object_to_array($phaxioresultreq);
196
+
197
+                    $phaxiofromraw = $fromnmbrtoarr['data']['from_number'];
198
+                    $phaxiotoraw  = $fromnmbrtoarr['data']['to_number'];
199
+                    $phaxiofromnumber = str_replace("+", "", $phaxiofromraw);
200
+                    $phaxiotonumber = str_replace("+", "", $phaxiotoraw);
201
+                    $errortype = 'there are no errors';
202
+
203
+           } catch (InvalidRequestException $e) {
204
+                      $phaxiofromnumber = 'null';
205
+                      $errortype = 'invalid request error';
206
+           } catch (AuthenticationException $e) {
207
+                      $phaxiofromnumber = 'null';
208
+                      $errortype = 'authentication error';
209
+           } catch (APIConnectionException $e) {
210
+                      $phaxiofromnumber = 'null';
211
+                      $errortype = 'API connection error';
212
+           } catch (RateLimitException $e) {
213
+                      $phaxiofromnumber = 'null';
214
+                      $errortype = 'rate limit error';
215
+           } catch (NotFoundException $e) {
216
+                      $phaxiofromnumber = 'null';
217
+                      $errortype = 'not found error';
218
+           } catch (GeneralException $e) {
219
+                      $phaxiofromnumber = 'null';
220
+                      $errortype = 'undefined error';
221
+           }
222
+
223
+           if ($this->folder->nodeExists('Pax_Fax/faxes_received') == false) {
224
+               $this->folder->newFolder('Pax_Fax/faxes_received');
225
+           }
226
+
227
+           if ($this->folder->nodeExists('Pax_Fax/faxes_received_failed') == false) {
228
+               $this->folder->newFolder('Pax_Fax/faxes_received_failed');
229
+           }
230
+
231
+           $targetfile = "/Pax_Fax/faxes_received/" . $fileName . "_" . $phaxiofromnumber . "_" . $phaxiotonumber  . "_" . $fldate . "." . $filenameext;
232
+
233
+           $target = $this->folder->newFile($targetfile);
234
+
235
+           $target->putContent($fileContent);
236
+
237
+           // Move failed received faxes to the 'faxes_received_failed' folder
238
+           if ($filenameext == '') {
239
+
240
+               $newtargetfl =  "/Pax_Fax/faxes_received_failed/" . $fileName . "_" . $phaxiofromnumber . "_" . $phaxiotonumber . "_" . $fldate . "." . $filenameext;
241
+               $targetact = $this->folder->newFile($newtargetfl);
242
+
243
+               $targetact->putContent($fileContent);
244
+
245
+               $failedfl = "/Pax_Fax/faxes_received/" . $fileName . "_" . $phaxiofromnumber . "_" . $phaxiotonumber . "_" . $fldate . "." . $filenameext;
246
+               $removefailed = $this->filesystem->unlink($failedfl);
247
+           }
248
+
249
+           // Send notifications
250
+           $nameofhost = $_SERVER['REQUEST_SCHEME'] . "://" . $_SERVER['HTTP_HOST'];
251
+           $getnextnotify = $thisapicred[9];
252
+           $useremailaddr = $thisapicred[10];
253
+
254
+           if ($filenameext != '') {
255
+               $targetflname = $targetfile;
256
+               $targettrim = "/Pax_Fax/faxes_received/";
257
+               $validfaxparam = "fax";
258
+               $setsubject = "New fax received";
259
+           } else {
260
+               $targetflname = $newtargetfl;
261
+               $targettrim = "/Pax_Fax/faxes_received_failed/";
262
+               $validfaxparam = "failed fax";
263
+               $setsubject = "New failed fax received";
264
+           }
265
+
266
+           if ($useremailaddr != '') {
267
+
268
+               $subject = $setsubject;
269
+               $message = "Hello! <br><br> You have received a new ".$validfaxparam." on ".$flmsdate." .<br> The new ".$validfaxparam." file is '".$targetflname."' . <br><br>____________<br><br> Yours, <br> Pax Fax <br> A fax application for Nextcloud <br> Host: '".$nameofhost."' <br>";
270
+
271
+               $messagefin = chunk_split(base64_encode($message));
272
+
273
+               $headers = "MIME-Version: 1.0" . "\r\n";
274
+               $headers .= "Content-type: text/html; charset=UTF-8" . "\r\n";
275
+               $headers .= "Content-Transfer-Encoding: base64" . "\r\n";
276
+
277
+               // Set the email sender
278
+               $headers .= "From: " . $useremailaddr . "\r\n";
279
+               $headers .= "Reply-To: " . $useremailaddr . "\r\n";
280
+
281
+               mail($useremailaddr, $subject, $messagefin, $headers);
282
+           }
283
+
284
+           if ($getnextnotify != 0 ) {
285
+
286
+	       $notificationph = $this->manager->createNotification();
287
+	       $notificationph->setApp('pax_fax')
288
+			      ->setUser($this->userId)
289
+			      ->setDateTime(new \DateTime())
290
+			      ->setObject('pax_fax', '12')
291
+			      ->setSubject('New fax');
292
+	       $this->manager->notify($notificationph);
293
+          }
294
+
295
+       } else { return "access denied"; }
296
+
297
+    }
298
+
299
+    /**
300
+     * @NoAdminRequired
301
+     * @NoCSRFRequired
302
+     */
303
+    public function receivefaxsinch() {
304
+
305
+           $thisapicred = $this->service->getapicredentials($this->userId);
306
+
307
+           $fileContent = file_get_contents($_FILES['file']['tmp_name']);
308
+           $fileNameinit = $_FILES['file']['name'];
309
+
310
+           $snpostdata = json_decode($_POST["fax"], true);
311
+ 
312
+           $fldate = date("Y-m-d_H-i-s_").gettimeofday()["usec"];
313
+
314
+           $gmtind = "UTC " . date('P');
315
+           $flmsdateinit = date("Y-m-d  H:i:s");
316
+           $flmsdate = $flmsdateinit . " " . $gmtind;
317
+
318
+           $fileNamesec = array_reverse(explode(".", $fileNameinit));
319
+           $filenameext = $fileNamesec[0];
320
+           array_shift($fileNamesec);
321
+
322
+           $fileName = implode("", $fileNamesec);
323
+
324
+           $sinchfromnumber = $snpostdata["from"];
325
+           $sinchtonumber = $snpostdata["to"];
326
+
327
+           $faxid = $fileName;
328
+
329
+           if ($this->folder->nodeExists('Pax_Fax/faxes_received') == false) {
330
+               $this->folder->newFolder('Pax_Fax/faxes_received');
331
+           }
332
+
333
+           if ($this->folder->nodeExists('Pax_Fax/faxes_received_failed') == false) {
334
+               $this->folder->newFolder('Pax_Fax/faxes_received_failed');
335
+           }
336
+
337
+           $targetfile = "/Pax_Fax/faxes_received/Fax-" . $fileName . "_" . $sinchfromnumber . "_" . $sinchtonumber  . "_" . $fldate . "." . $filenameext;
338
+
339
+           $target = $this->folder->newFile($targetfile);
340
+
341
+           $target->putContent($fileContent);
342
+
343
+           // Move failed received faxes to the 'faxes_received_failed' folder
344
+           if ($filenameext == '') {
345
+
346
+               $newtargetfl =  "/Pax_Fax/faxes_received_failed/" . $fileName . "_" . $sinchfromnumber . "_" . $sinchtonumber . "_" . $fldate . "." . $filenameext;
347
+               $targetact = $this->folder->newFile($newtargetfl);
348
+
349
+               $targetact->putContent($fileContent);
350
+
351
+               $failedfl = "/Pax_Fax/faxes_received/" . $fileName . "_" . $sinchfromnumber . "_" . $sinchtonumber . "_" . $fldate . "." . $filenameext;
352
+               $removefailed = $this->filesystem->unlink($failedfl);
353
+           }
354
+
355
+           // Send notifications
356
+           $nameofhost = $_SERVER['REQUEST_SCHEME'] . "://" . $_SERVER['HTTP_HOST'];
357
+           $getnextnotify = $thisapicred[9];
358
+           $useremailaddr = $thisapicred[10];
359
+
360
+           if ($filenameext != '') {
361
+               $targetflname = $targetfile;
362
+               $targettrim = "/Pax_Fax/faxes_received/";
363
+               $validfaxparam = "fax";
364
+               $setsubject = "New fax received";
365
+           } else {
366
+               $targetflname = $newtargetfl;
367
+               $targettrim = "/Pax_Fax/faxes_received_failed/";
368
+               $validfaxparam = "failed fax";
369
+               $setsubject = "New failed fax received";
370
+           }
371
+
372
+           if ($useremailaddr != '') {
373
+
374
+               $subject = $setsubject;
375
+               $message = "Hello! <br><br> You have received a new ".$validfaxparam." on ".$flmsdate." .<br> The new ".$validfaxparam." file is '".$targetflname."' . <br><br>____________<br><br> Yours, <br> Pax Fax <br> A fax application for Nextcloud <br> Host: '".$nameofhost."' <br>";
376
+
377
+               $messagefin = chunk_split(base64_encode($message));
378
+
379
+               $headers = "MIME-Version: 1.0" . "\r\n";
380
+               $headers .= "Content-type: text/html; charset=UTF-8" . "\r\n";
381
+               $headers .= "Content-Transfer-Encoding: base64" . "\r\n";
382
+
383
+               // Set the email sender
384
+               $headers .= "From: " . $useremailaddr . "\r\n";
385
+               $headers .= "Reply-To: " . $useremailaddr . "\r\n";
386
+
387
+               mail($useremailaddr, $subject, $messagefin, $headers);
388
+           }
389
+
390
+           if ($getnextnotify != 0 ) {
391
+
392
+	       $notificationph = $this->manager->createNotification();
393
+	       $notificationph->setApp('pax_fax')
394
+			      ->setUser($this->userId)
395
+			      ->setDateTime(new \DateTime())
396
+			      ->setObject('pax_fax', '12')
397
+			      ->setSubject('New fax');
398
+	       $this->manager->notify($notificationph);
399
+          }
400
+
401
+    }
402
+
403
+}
404
+
0 405
new file mode 100644
... ...
@@ -0,0 +1,768 @@
1
+<?php
2
+/**
3
+ * @copyright 2021 Double Bastion LLC <www.doublebastion.com>
4
+ *
5
+ * @author Double Bastion LLC
6
+ *
7
+ * @license GNU AGPL version 3 or any later version
8
+ *
9
+ * This program is free software; you can redistribute it and/or
10
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
11
+ * License as published by the Free Software Foundation; either
12
+ * version 3 of the License, or any later version.
13
+ *
14
+ * This program is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
18
+ *
19
+ * You should have received a copy of the GNU Affero General Public
20
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
+ *
22
+ */
23
+
24
+declare(strict_types=1);
25
+
26
+namespace OCA\PaxFax\Controller;
27
+
28
+use OCP\IRequest;
29
+use OCP\AppFramework\Controller;
30
+use OCA\PaxFax\Service\PaxfaxService;
31
+use OCP\AppFramework\App;
32
+use OCP\Files\NotPermittedException;
33
+use OCP\Files\Folder;
34
+use OCP\IConfig;
35
+use OC\Files\Filesystem;
36
+use OC\Files\View;
37
+use OCP\IUserSession;
38
+use OC\URLGenerator;
39
+use \ReflectionClass;
40
+use \FilesystemIterator;
41
+use Psr\Log\LoggerInterface;
42
+
43
+use Phaxio;
44
+use Phaxio\OperationResult;
45
+use Phaxio\Error\AuthenticationException;
46
+use Phaxio\Error\NotFoundException;
47
+use Phaxio\Error\InvalidRequestException;
48
+use Phaxio\Error\RateLimitException;
49
+use Phaxio\Error\APIConnectionException;
50
+use Phaxio\Error\GeneralException;
51
+
52
+
53
+class PaxfaxController extends Controller {
54
+
55
+    private $service;
56
+    private $config;
57
+    private $userId;
58
+    private $folder;
59
+    private $filesystem;
60
+    private $view;
61
+    private $userSession;
62
+    private $urlGenerator;
63
+    private $logger;
64
+
65
+    public function __construct($appName, IRequest $request, PaxfaxService $service, IConfig $config, $userId, Folder $folder, Filesystem $filesystem, View $view, IUserSession $userSession, URLGenerator $urlGenerator, LoggerInterface $logger) {
66
+
67
+           parent::__construct($appName, $request);
68
+
69
+           $this->service = $service;
70
+           $this->config = $config;
71
+           $this->userId = $userId;
72
+           $this->folder = $folder;
73
+           $this->filesystem = $filesystem;
74
+           $this->view = $view;
75
+           $this->userSession = $userSession;
76
+           $this->urlGenerator = $urlGenerator;
77
+           $this->logger = $logger;
78
+    }
79
+
80
+
81
+    /**
82
+     * @NoAdminRequired
83
+     */
84
+    public function cleantempdir() {
85
+
86
+           // If the 'temp_files' folder doesn't exist create it
87
+           if ($this->folder->nodeExists('Pax_Fax/temp_files') == false) {
88
+               $this->folder->newFolder('Pax_Fax/temp_files');
89
+           }
90
+
91
+           $datadir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/';
92
+           $targetdir = $datadir . $this->userSession->getUser()->getUID() . "/files/Pax_Fax/temp_files";
93
+           $fileSystemIterator = new FilesystemIterator($targetdir);
94
+
95
+           $dirfiles = [];
96
+           foreach ($fileSystemIterator as $fileInfo){
97
+                    $dirfiles[] = $fileInfo->getFilename();
98
+           }
99
+
100
+           foreach ($dirfiles as $key => $indfile) {
101
+                    $thisuserroot = $this->view->getRoot();
102
+                    $tempfile = $thisuserroot . "/Pax_Fax/temp_files/" . $indfile;
103
+                    $removetmpfile = $this->filesystem->unlink($tempfile);
104
+           }
105
+    }
106
+
107
+
108
+    /**
109
+     * @NoAdminRequired
110
+     */
111
+    public function object_to_array($obj) {
112
+
113
+           if(is_object($obj)) $obj = (array)$this->dismount($obj);
114
+           if(is_array($obj)) {
115
+              $new = array();
116
+              foreach($obj as $key => $val) {
117
+                      $new[$key] = $this->object_to_array($val);
118
+              }
119
+           }
120
+           else $new = $obj;
121
+           return $new;
122
+    }
123
+
124
+
125
+    /**
126
+     * @NoAdminRequired
127
+     */
128
+    public function dismount($object) {
129
+           $reflectionClass = new ReflectionClass(get_class($object));
130
+           $array = array();
131
+           foreach ($reflectionClass->getProperties() as $property) {
132
+                    $property->setAccessible(true);
133
+                    $array[$property->getName()] = $property->getValue($object);
134
+                    $property->setAccessible(false);
135
+           }
136
+           return $array;
137
+    }
138
+
139
+
140
+    /**
141
+     * @NoAdminRequired
142
+     */
143
+    public function getbalance() {
144
+
145
+           $thisapicred = $this->service->getapicredentials($this->userSession->getUser()->getUID());
146
+
147
+           $sinchKeyId = $thisapicred[5];
148
+           $sinchKeySecret = $thisapicred[6];
149
+
150
+           if ($sinchKeyId && $sinchKeySecret) {
151
+
152
+               // Use Sinch
153
+               return "n/a";
154
+
155
+           } else {
156
+
157
+               // Use Phaxio
158
+               $apiMode = 'live';
159
+               $apiKeys[$apiMode] = $thisapicred[0];
160
+               $apiSecrets[$apiMode] = $thisapicred[1];
161
+
162
+               $apiHost = 'https://api.phaxio.com/v2.1/';
163
+
164
+               $phaxio = new Phaxio($apiKeys[$apiMode], $apiSecrets[$apiMode], $apiHost);
165
+
166
+               try {
167
+                    // Get Phaxio account balance
168
+                    $phaxioresulttert = $phaxio->doRequest("GET", 'account/status');
169
+
170
+                    $balancetoarr = $this->object_to_array($phaxioresulttert);
171
+
172
+                    $phaxiobalance = $balancetoarr['data']['balance'];
173
+
174
+               } catch (InvalidRequestException $e) {
175
+                    $phaxiobalance = 'unknown';
176
+                    $phaxiosuccess = 'false';
177
+                    $errortype = 'invalid request error';
178
+               } catch (AuthenticationException $e) {
179
+                    $phaxiobalance = 'unknown';
180
+                    $phaxiosuccess = 'false';
181
+                    $errortype = 'authentication error';
182
+               } catch (APIConnectionException $e) {
183
+                    $phaxiobalance = 'unknown';
184
+                    $phaxiosuccess = 'false';
185
+                    $errortype = 'API connection error';
186
+               } catch (RateLimitException $e) {
187
+                    $phaxiobalance = 'unknown';
188
+                    $phaxiosuccess = 'false';
189
+                    $errortype = 'rate limit error';
190
+               } catch (NotFoundException $e) {
191
+                    $phaxiobalance = 'unknown';
192
+                    $phaxiosuccess = 'false';
193
+                    $errortype = 'not found error';
194
+               } catch (GeneralException $e) {
195
+                    $phaxiobalance = 'unknown';
196
+                    $phaxiosuccess = 'false';
197
+                    $errortype = 'undefined error';
198
+               }
199
+
200
+               return $phaxiobalance;
201
+           }
202
+    }
203
+
204
+
205
+    /**
206
+     * @NoAdminRequired
207
+     */
208
+    public function getfaxnumbers() {
209
+
210
+           $thisapicred = $this->service->getapicredentials($this->userSession->getUser()->getUID());
211
+
212
+           $sinchKeyId = $thisapicred[5];
213
+           $sinchKeySecret = $thisapicred[6];
214
+
215
+           if ($sinchKeyId && $sinchKeySecret) {
216
+
217
+               // Use Sinch
218
+	       $sinchProjectId = $thisapicred[4];
219
+	       $sinchServiceId = $thisapicred[7];
220
+
221
+	       $nbquery = [ "pageSize" => "100", "page" => "string" ];
222
+
223
+	       $curl = curl_init();
224
+
225
+	       curl_setopt_array($curl, [
226
+		    CURLOPT_HTTPHEADER => [ "Authorization: Basic " . base64_encode("" . $sinchKeyId . ":" . $sinchKeySecret ."") ],
227
+                    CURLOPT_PORT => "",
228
+		    CURLOPT_URL => "https://fax.api.sinch.com/v3/projects/" . $sinchProjectId . "/services/" . $sinchServiceId . "/numbers?" . http_build_query($nbquery),
229
+		    CURLOPT_RETURNTRANSFER => true,
230
+		    CURLOPT_CUSTOMREQUEST => "GET",
231
+		]);
232
+
233
+		$responsesnb = curl_exec($curl);
234
+		$errorsnb = curl_error($curl);
235
+
236
+		curl_close($curl);
237
+
238
+		if ($errorsnb) { $this->logger->error('cURL Error #: '. $errorsnb . '.'); }
239
+
240
+                $sincharr = [];
241
+                $sinchnmbrs = json_decode($responsesnb, true);
242
+
243
+	        foreach ($sinchnmbrs['numbers'] as $snkey => $snvalue) {
244
+	                 if (is_array($snvalue)) {
245
+	                        foreach ($snvalue as $snkeysec => $snvaluesec) {
246
+	                               if ($snkeysec == 'phoneNumber') {
247
+	                                   $sincharr[] = $snvaluesec;
248
+	                               }
249
+	                        }
250
+	                 }
251
+	        }
252
+
253
+                $sinchnbdata = ["nblist" => $sincharr, "provider" => "sinch"];
254
+
255
+		return $sinchnbdata;
256
+
257
+           } else {
258
+
259
+                // Use Phaxio
260
+		$apiMode = 'live';
261
+		$apiKeys[$apiMode] = $thisapicred[0];
262
+		$apiSecrets[$apiMode] = $thisapicred[1];
263
+
264
+		$apiHost = 'https://api.phaxio.com/v2.1/';
265
+
266
+		$phaxio = new Phaxio($apiKeys[$apiMode], $apiSecrets[$apiMode], $apiHost);
267
+
268
+		try {
269
+	            // Get all Phaxio fax numbers
270
+	            $phaxioresultfour = $phaxio->doRequest("GET", 'phone_numbers');
271
+
272
+	            $phaxionbstoarr = $this->object_to_array($phaxioresultfour);
273
+
274
+	            $phaxioarr = [];
275
+
276
+	            foreach ($phaxionbstoarr['data'] as $phkey => $phvalue) {
277
+	                   if (is_array($phvalue)) {
278
+	                         foreach ($phvalue as $phkeysec => $phvaluesec) {
279
+	                               if ($phkeysec == 'phone_number') {
280
+	                                   $phaxioarr[] = $phvaluesec;
281
+	                               }
282
+	                         }
283
+	                   }
284
+	            }
285
+
286
+		} catch (InvalidRequestException $e) {
287
+	            $phaxiobalance = 'unknown';
288
+	            $phaxiosuccess = 'false';
289
+	            $errortype = 'invalid request error';
290
+		} catch (AuthenticationException $e) {
291
+	            $phaxiobalance = 'unknown';
292
+	            $phaxiosuccess = 'false';
293
+	            $errortype = 'authentication error';
294
+		} catch (APIConnectionException $e) {
295
+	            $phaxiobalance = 'unknown';
296
+	            $phaxiosuccess = 'false';
297
+	            $errortype = 'API connection error';
298
+		} catch (RateLimitException $e) {
299
+	            $phaxiobalance = 'unknown';
300
+	            $phaxiosuccess = 'false';
301
+	            $errortype = 'rate limit error';
302
+		} catch (NotFoundException $e) {
303
+	            $phaxiobalance = 'unknown';
304
+	            $phaxiosuccess = 'false';
305
+	            $errortype = 'not found error';
306
+		} catch (GeneralException $e) {
307
+	            $phaxiobalance = 'unknown';
308
+	            $phaxiosuccess = 'false';
309
+	            $errortype = 'undefined error';
310
+		}
311
+
312
+                $phaxionbdata = ["nblist" => $phaxioarr, "provider" => "phaxio"];
313
+
314
+		return $phaxionbdata;
315
+           }
316
+        
317
+    }
318
+
319
+
320
+    /**
321
+     * @NoAdminRequired
322
+     */
323
+    public function uploadfile($uploadfileforfax) {
324
+
325
+           $fileContent = file_get_contents($_FILES['uploadfileforfax']['tmp_name']);
326
+           $fileName = $_FILES['uploadfileforfax']['name'];
327
+           $fileSizeinit = $_FILES['uploadfileforfax']['size'];
328
+           $fileSize = $fileSizeinit / 1048576;
329
+
330
+           if ($this->folder->nodeExists('Pax_Fax/faxes_sent') == false) {
331
+               $this->folder->newFolder('Pax_Fax/faxes_sent');
332
+           }
333
+           if ($this->folder->nodeExists('Pax_Fax/faxes_received') == false) {
334
+               $this->folder->newFolder('Pax_Fax/faxes_received');
335
+           }
336
+           if ($this->folder->nodeExists('Pax_Fax/faxes_sent_failed') == false) {
337
+               $this->folder->newFolder('Pax_Fax/faxes_sent_failed');
338
+           }
339
+           if ($this->folder->nodeExists('Pax_Fax/faxes_received_failed') == false) {
340
+               $this->folder->newFolder('Pax_Fax/faxes_received_failed');
341
+           }
342
+           if ($this->folder->nodeExists('Pax_Fax/temp_files') == false) {
343
+               $this->folder->newFolder('Pax_Fax/temp_files');
344
+           }
345
+
346
+           $userroot = $this->view->getRoot();
347
+           $targetfile = $userroot . "/Pax_Fax/temp_files/" . $fileName;
348
+
349
+           $target = $this->folder->newFile($targetfile);
350
+           $target->putContent($fileContent);
351
+
352
+           // Get the cumulative files size of the uploaded files
353
+           $datadir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/';
354
+           $targetdir = $datadir . $this->userSession->getUser()->getUID() . "/files/Pax_Fax/temp_files";
355
+
356
+           $fileSystemIterator = new FilesystemIterator($targetdir);
357
+
358
+           $dirfiles = [];
359
+           foreach ($fileSystemIterator as $fileInfo){
360
+                    $dirfiles[] = $fileInfo->getFilename();
361
+           }
362
+
363
+           $totalflsizeinit = 0;
364
+           foreach ($dirfiles as $key => $indfile) {
365
+                    $fileSizeinit = $this->filesystem->filesize($userroot . "/Pax_Fax/temp_files/" . $indfile);
366
+                    $mbSize = $fileSizeinit / 1048576;
367
+                    $totalflsizeinit += $mbSize;
368
+           }
369
+
370
+           $totalflsize = number_format($totalflsizeinit, 2) . ' MB';
371
+
372
+           return $totalflsize;
373
+    }
374
+
375
+    /**
376
+     * @NoAdminRequired
377
+     */
378
+    public function pickfile($path) {
379
+
380
+           if ($this->folder->nodeExists('Pax_Fax/faxes_sent') == false) {
381
+               $this->folder->newFolder('Pax_Fax/faxes_sent');
382
+           }
383
+           if ($this->folder->nodeExists('Pax_Fax/faxes_received') == false) {
384
+               $this->folder->newFolder('Pax_Fax/faxes_received');
385
+           }
386
+           if ($this->folder->nodeExists('Pax_Fax/faxes_sent_failed') == false) {
387
+               $this->folder->newFolder('Pax_Fax/faxes_sent_failed');
388
+           }
389
+           if ($this->folder->nodeExists('Pax_Fax/faxes_received_failed') == false) {
390
+               $this->folder->newFolder('Pax_Fax/faxes_received_failed');
391
+           }
392
+           if ($this->folder->nodeExists('Pax_Fax/temp_files') == false) {
393
+               $this->folder->newFolder('Pax_Fax/temp_files');
394
+           }
395
+
396
+           $datadir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/';
397
+
398
+           $fltgt = $datadir . $this->userSession->getUser()->getUID() . "/files" . $path;
399
+
400
+           $fileContentpk = file_get_contents($fltgt);
401
+
402
+           $patharr = explode("/", $path);
403
+
404
+           $revarr = array_reverse($patharr);
405
+
406
+           $relflpath = "/Pax_Fax/temp_files/" . $revarr[0]; 
407
+
408
+           $target = $this->folder->newFile($relflpath);
409
+
410
+           $target->putContent($fileContentpk);
411
+
412
+           $targetdir = $datadir . $this->userSession->getUser()->getUID() . "/files/Pax_Fax/temp_files";
413
+
414
+           $fileSystemIterator = new FilesystemIterator($targetdir);
415
+
416
+           $dirfiles = [];
417
+           foreach ($fileSystemIterator as $fileInfo) {
418
+                    $dirfiles[] = $fileInfo->getFilename();
419
+           }
420
+
421
+           $totalflsizeinit = 0;
422
+
423
+           foreach ($dirfiles as $key => $indfile) {
424
+
425
+                    $fileSizeinit = $this->filesystem->filesize("/Pax_Fax/temp_files/" . $indfile);
426
+                    $mbSize = $fileSizeinit / 1048576;
427
+                    $totalflsizeinit += $mbSize;
428
+           }
429
+
430
+           $totalflsize = number_format($totalflsizeinit, 2) . ' MB';
431
+
432
+           return $totalflsize;
433
+    }
434
+
435
+    /**
436
+     * @NoAdminRequired
437
+     */
438
+    public function removeupfile($removedfilename) {
439
+
440
+           $tmpfl = "/" . $this->userSession->getUser()->getUID() . "/files/Pax_Fax/temp_files/" . $removedfilename;
441
+
442
+           $removefile = $this->view->unlink($tmpfl);
443
+
444
+           // Get the cumulative files size of the uploaded files
445
+           $datadir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/';
446
+           $targetdir = $datadir . $this->userSession->getUser()->getUID() . "/files/Pax_Fax/temp_files";
447
+           $fileSystemIterator = new FilesystemIterator($targetdir);
448
+
449
+           $dirfiles = [];
450
+           foreach ($fileSystemIterator as $fileInfo) {
451
+                    $dirfiles[] = $fileInfo->getFilename();
452
+           }
453
+
454
+           $totalflsizeinit = 0;
455
+
456
+           foreach ($dirfiles as $key => $indfile) {
457
+                    $fileSizeinit = $this->filesystem->filesize("/Pax_Fax/temp_files/" . $indfile);
458
+                    $mbSize = $fileSizeinit / 1048576;
459
+                    $totalflsizeinit += $mbSize;
460
+           }
461
+
462
+           $totalflsize = number_format($totalflsizeinit, 2) . ' MB';
463
+
464
+           return $totalflsize;
465
+    }
466
+
467
+    /**
468
+     * @NoAdminRequired
469
+     */
470
+    public function getpickedfile($pickedfilename) {
471
+
472
+           $thisuserroot = $this->view->getRoot();
473
+
474
+           $temppickedfile = $thisuserroot . "/Pax_Fax/temp_files/" . $pickedfilename;
475
+           $getfilecontent = $this->filesystem->file_get_contents($temppickedfile);
476
+
477
+           $namesplit = explode(".", $pickedfilename);
478
+           $extension = end($namesplit);
479
+
480
+           if ($extension == "txt" || $extension == "html") {
481
+               $getpickedfile = $getfilecontent;
482
+           } elseif ($extension == "jpg") {
483
+               $getpickedfile = 'data:image/jpeg;base64,' . base64_encode($getfilecontent);
484
+           } elseif ($extension == "png") {
485
+               $getpickedfile = 'data:image/png;base64,' . base64_encode($getfilecontent);
486
+           } else { $getpickedfile = ""; }
487
+
488
+           return $getpickedfile;
489
+    }
490
+
491
+    /**
492
+     * @NoAdminRequired
493
+     */
494
+    public function sendfax($uploadedtofax, $selectedcid, $toNumber) {
495
+
496
+           $tonumbertr = str_replace("+", "", $toNumber[0]);
497
+           $fldate = date("Y-m-d_H-i-s_").gettimeofday()["usec"];
498
+           $fromnumberdigits = str_replace("+", "", $selectedcid);
499
+
500
+           if ($selectedcid != '' && $selectedcid != 'click refresh button') { $fromnumber = $selectedcid; } else { $fromnumber = ''; }
501
+
502
+           $thisapicred = $this->service->getapicredentials($this->userSession->getUser()->getUID());
503
+
504
+           $sinchKeyId = $thisapicred[5];
505
+           $sinchKeySecret = $thisapicred[6];
506
+
507
+           if ($sinchKeyId && $sinchKeySecret) {
508
+
509
+               // Use Sinch
510
+	       $sinchProjectId = $thisapicred[4];
511
+
512
+               $countfaxfiles = count($uploadedtofax);
513
+
514
+               $openedfiles = [];
515
+               $crtuser = $this->userSession->getUser()->getUID();
516
+
517
+               foreach ($uploadedtofax as $key => $flname) {
518
+
519
+                    if ($key == 0) { $firstflname = $flname; }
520
+
521
+                    $fileNamesec = array_reverse(explode(".", $flname));
522
+                    $filenameext = $fileNamesec[0];
523
+
524
+                    array_shift($fileNamesec);
525
+
526
+                    $fileName = implode("", $fileNamesec);
527
+
528
+                    if ($countfaxfiles == 1) {
529
+
530
+                        $targetfile = "/Pax_Fax/faxes_sent/" . $fileName . "_" . $fromnumber . "_"  . $tonumbertr . "_" . $fldate . "." . $filenameext;
531
+
532
+                    } else {
533
+
534
+                         if ($this->folder->nodeExists("Pax_Fax/faxes_sent/" . $firstflname . "_et_al_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate) == false) {
535
+                             $this->folder->newFolder("Pax_Fax/faxes_sent/" . $firstflname . "_et_al_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate);
536
+                         }
537
+
538
+                         $targetfile = "/Pax_Fax/faxes_sent/" . $firstflname . "_et_al_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "/" . $fileName . "_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "." . $filenameext;
539
+                    }
540
+
541
+                    $datadir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/';
542
+
543
+                    $fltgtsnd = $datadir . $crtuser . "/files/Pax_Fax/temp_files/" . $flname;
544
+                    $fltgtsndtmp = "/Pax_Fax/temp_files/" . $flname;
545
+
546
+                    $fileContentsnd = file_get_contents($fltgtsnd);
547
+
548
+                    $target = $this->folder->newFile($targetfile);
549
+                    $target->putContent($fileContentsnd);
550
+
551
+                    $removetmpfile = $this->filesystem->unlink($fltgtsndtmp);
552
+
553
+                    if ($countfaxfiles == 1) {
554
+                        $openedfiles[] = [ "file" => base64_encode(file_get_contents($datadir . $crtuser . "/files/Pax_Fax/faxes_sent/" . $fileName . "_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "." . $filenameext)), "fileType" => $filenameext ];
555
+                    } else {
556
+                        $openedfiles[] = [ "file" => base64_encode(file_get_contents($datadir . $crtuser . "/files/Pax_Fax/faxes_sent/" . $firstflname . "_et_al_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "/" . $fileName . "_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "." . $filenameext)), "fileType" => $filenameext ];
557
+                    }
558
+               }
559
+
560
+               $toNumbersn = [];
561
+               foreach ($toNumber as $nbkey => $nbvalue) { $toNumbersn[] = "+" . $nbvalue; }
562
+               $toNumbersnfin = implode(";", $toNumbersn);
563
+
564
+	       $datatosendsn = ["to" => $toNumbersnfin, "files" => $openedfiles];
565
+
566
+	       $postedparamsn = json_encode($datatosendsn);
567
+
568
+	       $chsn = curl_init();
569
+               curl_setopt($chsn, CURLOPT_URL, "https://" . $sinchKeyId . ":" . $sinchKeySecret . "@fax.api.sinch.com/v3/projects/" . $sinchProjectId . "/faxes");
570
+	       curl_setopt($chsn, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
571
+	       curl_setopt($chsn, CURLOPT_TIMEOUT, 300);
572
+	       curl_setopt($chsn, CURLOPT_RETURNTRANSFER, 1);
573
+	       curl_setopt($chsn, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
574
+	       curl_setopt($chsn, CURLOPT_POST, 1);
575
+	       curl_setopt($chsn, CURLOPT_POSTFIELDS, $postedparamsn);
576
+	       $resultsn = curl_exec($chsn);
577
+	       $statusCodesn = curl_getinfo($chsn, CURLINFO_HTTP_CODE);
578
+	       curl_close($chsn);
579
+
580
+	       $decresultsn = json_decode($resultsn, true);
581
+
582
+	       if (in_array($statusCodesn, [400, 401, 402, 404, 422, 429, 500, 800])) {
583
+                   $sinchsuccess = false;
584
+                   $sincherrortype = "Error: " . $decresultsn['code'] . " . Message: " . $decresultsn['message'];
585
+               } else { $sinchsuccess = true; $sincherrortype = ''; }
586
+
587
+               $sinchresult = [ 'success' => $sinchsuccess, 'errortype' => $sincherrortype ];
588
+
589
+               if ($sinchsuccess != true) {
590
+
591
+                    foreach ($uploadedtofax as $key => $flname) {
592
+
593
+                        $fileNamesec = array_reverse(explode(".", $flname));
594
+                        $filenameext = $fileNamesec[0];
595
+                        array_shift($fileNamesec);
596
+
597
+                        $fileName = implode("", $fileNamesec);
598
+
599
+                        if ($countfaxfiles == 1) {
600
+                            $failedfl = "/Pax_Fax/faxes_sent/" . $fileName . "_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "." . $filenameext;
601
+                            $newtargetfl =  "/Pax_Fax/faxes_sent_failed/" . $fileName . "_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "." . $filenameext;
602
+                        } else {
603
+
604
+                            $failedfl = "/Pax_Fax/faxes_sent/" . $firstflname . "_et_al_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "/" . $fileName . "_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "." . $filenameext;
605
+                            $this->folder->newFolder("Pax_Fax/faxes_sent_failed/" . $firstflname . "_et_al_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate);
606
+                            $newtargetfl = "/Pax_Fax/faxes_sent_failed/" . $firstflname . "_et_al_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "/" . $fileName . "_" . $tonumbertr . "_" . $fldate . "." . $filenameext;
607
+                        }
608
+
609
+                        $fileContentfld = $this->filesystem->file_get_contents($failedfl);
610
+
611
+                        $targetact = $this->folder->newFile($newtargetfl);
612
+                        $targetact->putContent($fileContentfld);
613
+
614
+                        $removefailed = $this->filesystem->unlink($failedfl);
615
+                    }
616
+
617
+                }
618
+
619
+                return $sinchresult;
620
+
621
+           } else {
622
+
623
+               // Use Phaxio
624
+               if ($selectedcid != '' && $selectedcid != 'click refresh button') { $fromnumber = $fromnumberdigits; } else { $fromnumber = 'nocallerid'; }
625
+
626
+               $countfaxfiles = count($uploadedtofax);
627
+
628
+               $openedfiles = [];
629
+               $crtuser = $this->userSession->getUser()->getUID();
630
+
631
+               foreach ($uploadedtofax as $key => $flname) {
632
+
633
+                    if ($key == 0) { $firstflname = $flname; }
634
+
635
+                    $fileNamesec = array_reverse(explode(".", $flname));
636
+                    $filenameext = $fileNamesec[0];
637
+                    array_shift($fileNamesec);
638
+
639
+                    $fileName = implode("", $fileNamesec);
640
+
641
+                    if ($countfaxfiles == 1) {
642
+                        $targetfile = "/Pax_Fax/faxes_sent/" . $fileName . "_" . $fromnumber . "_"  . $tonumbertr . "_" . $fldate . "." . $filenameext;
643
+                    } else {
644
+                         if ($this->folder->nodeExists("Pax_Fax/faxes_sent/" . $firstflname . "_et_al_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate) == false) {
645
+                             $this->folder->newFolder("Pax_Fax/faxes_sent/" . $firstflname . "_et_al_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate);
646
+                         }
647
+
648
+                         $targetfile = "/Pax_Fax/faxes_sent/" . $firstflname . "_et_al_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "/" . $fileName . "_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "." . $filenameext;
649
+                    }
650
+
651
+                    $datadir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/';
652
+
653
+                    $fltgtsnd = $datadir . $crtuser . "/files/Pax_Fax/temp_files/" . $flname;
654
+                    $fltgtsndtmp = "/Pax_Fax/temp_files/" . $flname;
655
+
656
+                    $fileContentsnd = file_get_contents($fltgtsnd);
657
+
658
+                    $target = $this->folder->newFile($targetfile);
659
+                    $target->putContent($fileContentsnd);
660
+
661
+                    $removetmpfile = $this->filesystem->unlink($fltgtsndtmp);
662
+
663
+                    if ($countfaxfiles == 1) {
664
+                        $openedfiles[] = fopen($datadir . $crtuser . "/files/Pax_Fax/faxes_sent/" . $fileName . "_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "." . $filenameext, "r");
665
+                    } else {
666
+                        $openedfiles[] = fopen($datadir . $crtuser . "/files/Pax_Fax/faxes_sent/" . $firstflname . "_et_al_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "/" . $fileName . "_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "." . $filenameext, "r");
667
+                    }
668
+               }
669
+
670
+               $params = array(
671
+                           'to' => $toNumber,
672
+                           'file' => $openedfiles,
673
+                           'caller_id' => $selectedcid
674
+                         );
675
+
676
+               $apiMode = 'live';
677
+
678
+               $apiKeys[$apiMode] = $thisapicred[0];
679
+               $apiSecrets[$apiMode] = $thisapicred[1];
680
+
681
+               $apiHost = 'https://api.phaxio.com/v2.1/';
682
+
683
+               $phaxio = new Phaxio($apiKeys[$apiMode], $apiSecrets[$apiMode], $apiHost);
684
+
685
+               try {
686
+                    $phaxioresultinit = $phaxio->sendFax($params);
687
+
688
+                    $phaxioresultsec = $phaxio->doRequest("GET", 'faxes/' . urlencode((string)$phaxioresultinit['id']));
689
+
690
+                    $statustoarr = $this->object_to_array($phaxioresultsec);
691
+
692
+                    $phaxiosuccess = $statustoarr['success'];
693
+
694
+                    $errortype = 'there are no errors';
695
+
696
+               } catch (InvalidRequestException $e) {
697
+                    $phaxiosuccess = 'false';
698
+                    $errortype = 'invalid request error';
699
+               } catch (AuthenticationException $e) {
700
+                    $phaxiosuccess = 'false';
701
+                    $errortype = 'authentication error';
702
+               } catch (APIConnectionException $e) {
703
+                    $phaxiosuccess = 'false';
704
+                    $errortype = 'API connection error';
705
+               } catch (RateLimitException $e) {
706
+                    $phaxiosuccess = 'false';
707
+                    $errortype = 'rate limit error';
708
+               } catch (NotFoundException $e) {
709
+                    $phaxiosuccess = 'false';
710
+                    $errortype = 'not found error';
711
+               } catch (GeneralException $e) {
712
+                    $phaxiosuccess = 'false';
713
+                    $errortype = 'undefined error';
714
+               }
715
+
716
+               $phaxioresult = ['success' => $phaxiosuccess, 'errortype' => $errortype];
717
+
718
+               if ($phaxiosuccess != 'true') {
719
+
720
+                    foreach ($uploadedtofax as $key => $flname) {
721
+
722
+                        $fileNamesec = array_reverse(explode(".", $flname));
723
+                        $filenameext = $fileNamesec[0];
724
+                        array_shift($fileNamesec);
725
+
726
+                        $fileName = implode("", $fileNamesec);
727
+
728
+                        if ($countfaxfiles == 1) {
729
+                            $failedfl = "/Pax_Fax/faxes_sent/" . $fileName . "_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "." . $filenameext;
730
+                            $newtargetfl =  "/Pax_Fax/faxes_sent_failed/" . $fileName . "_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "." . $filenameext;
731
+                        } else {
732
+
733
+                            $failedfl = "/Pax_Fax/faxes_sent/" . $firstflname . "_et_al_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "/" . $fileName . "_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "." . $filenameext;
734
+                            $this->folder->newFolder("Pax_Fax/faxes_sent_failed/" . $firstflname . "_et_al_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate);
735
+                            $newtargetfl = "/Pax_Fax/faxes_sent_failed/" . $firstflname . "_et_al_" . $fromnumber . "_" . $tonumbertr . "_" . $fldate . "/" . $fileName . "_" . $tonumbertr . "_" . $fldate . "." . $filenameext;
736
+                        }
737
+
738
+                        $fileContentfld = $this->filesystem->file_get_contents($failedfl);
739
+
740
+                        $targetact = $this->folder->newFile($newtargetfl);
741
+                        $targetact->putContent($fileContentfld);
742
+
743
+                        $removefailed = $this->filesystem->unlink($failedfl);
744
+                    }
745
+
746
+               }
747
+
748
+               return $phaxioresult;
749
+           }
750
+    }
751
+
752
+
753
+    /**
754
+     * @NoAdminRequired
755
+     */
756
+    public function getsettings() {
757
+           return $this->service->getsettings($this->userSession->getUser()->getUID());
758
+    }
759
+
760
+
761
+    /**
762
+     * @NoAdminRequired
763
+     */
764
+    public function updatesettings($apiKey, $apiSecret, $webhookToken, $receiveUrl, $sinchProjectId, $sinchKeyId, $sinchKeySecret, $sinchServiceId, $sinchCallbackUrl, $getNotification, $notificationEmail) {
765
+           return $this->service->updatesettings($this->userSession->getUser()->getUID(), $apiKey, $apiSecret, $webhookToken, $receiveUrl, $sinchProjectId, $sinchKeyId, $sinchKeySecret, $sinchServiceId, $sinchCallbackUrl, $getNotification, $notificationEmail);
766
+    }
767
+
768
+}
0 769
new file mode 100644
... ...
@@ -0,0 +1,140 @@
1
+<?php
2
+/**
3
+ * @copyright 2021 Double Bastion LLC <www.doublebastion.com>
4
+ *
5
+ * @author Double Bastion LLC
6
+ *
7
+ * @license GNU AGPL version 3 or any later version
8
+ *
9
+ * This program is free software; you can redistribute it and/or
10
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
11
+ * License as published by the Free Software Foundation; either
12
+ * version 3 of the License, or any later version.
13
+ *
14
+ * This program is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
18
+ *
19
+ * You should have received a copy of the GNU Affero General Public
20
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
+ *
22
+ */
23
+
24
+declare(strict_types=1);
25
+
26
+namespace OCA\PaxFax\Migration;
27
+
28
+use Closure;
29
+use OCP\DB\Types;
30
+use OCP\DB\ISchemaWrapper;
31
+use OCP\Migration\IOutput;
32
+use OCP\Migration\SimpleMigrationStep;
33
+
34
+
35
+class Version119Date20250425082914 extends SimpleMigrationStep {
36
+	/**
37
+	 * @param IOutput $output
38
+	 * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
39
+	 * @param array $options
40
+	 * @return null|ISchemaWrapper
41
+	 */
42
+	public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
43
+		/** @var ISchemaWrapper $schema */
44
+		$schema = $schemaClosure();
45
+
46
+		if (!$schema->hasTable('pax_fax')) {
47
+			$table = $schema->createTable('pax_fax');
48
+			$table->addColumn('id', Types::BIGINT, [
49
+				'autoincrement' => true,
50
+				'notnull' => true,
51
+                                'length' => 11,
52
+                                'unsigned' => true,
53
+			]);
54
+			$table->addColumn('user_id', Types::STRING, [
55
+				'notnull' => true,
56
+				'length' => 64,
57
+				'default' => '',
58
+			]);
59
+			$table->addColumn('api_key', Types::STRING, [
60
+				'notnull' => false,
61
+				'length' => 1024,
62
+				'default' => '',
63
+			]);
64
+			$table->addColumn('api_secret', Types::STRING, [
65
+				'notnull' => false,
66
+				'length' => 1024,
67
+				'default' => '',
68
+			]);
69
+			$table->addColumn('webhook_token', Types::STRING, [
70
+				'notnull' => false,
71
+				'length' => 1024,
72
+				'default' => '',
73
+			]);
74
+			$table->addColumn('sinch_project_id', Types::STRING, [
75
+				'notnull' => false,
76
+				'length' => 512,
77
+			]);
78
+			$table->addColumn('sinch_key_id', Types::STRING, [
79
+				'notnull' => false,
80
+				'length' => 512,
81
+			]);
82
+			$table->addColumn('sinch_key_secret', Types::STRING, [
83
+				'notnull' => false,
84
+				'length' => 512,
85
+			]);
86
+			$table->addColumn('sinch_service_id', Types::STRING, [
87
+				'notnull' => false,
88
+				'length' => 512,
89
+			]);
90
+			$table->addColumn('sinch_callback_url', Types::STRING, [
91
+				'notnull' => false,
92
+				'length' => 512,
93
+			]);
94
+			$table->addColumn('receive_url', Types::STRING, [
95
+				'notnull' => false,
96
+				'length' => 1024,
97
+				'default' => '',
98
+			]);
99
+			$table->addColumn('get_notification', Types::SMALLINT, [
100
+				'notnull' => false,
101
+				'length' => 1,
102
+			]);
103
+			$table->addColumn('notification_email', Types::STRING, [
104
+				'notnull' => false,
105
+				'length' => 1024,
106
+				'default' => '',
107
+			]);
108
+                        $table->setPrimaryKey(['id']);
109
+                        $table->addUniqueIndex(['id']);
110
+
111
+		} else {
112
+
113
+                        $table = $schema->getTable('pax_fax');
114
+
115
+			$table->addColumn('sinch_project_id', Types::STRING, [
116
+				'notnull' => false,
117
+				'length' => 512,
118
+			]);
119
+			$table->addColumn('sinch_key_id', Types::STRING, [
120
+				'notnull' => false,
121
+				'length' => 512,
122
+			]);
123
+			$table->addColumn('sinch_key_secret', Types::STRING, [
124
+				'notnull' => false,
125
+				'length' => 512,
126
+			]);
127
+			$table->addColumn('sinch_service_id', Types::STRING, [
128
+				'notnull' => false,
129
+				'length' => 512,
130
+			]);
131
+			$table->addColumn('sinch_callback_url', Types::STRING, [
132
+				'notnull' => false,
133
+				'length' => 512,
134
+			]);
135
+
136
+                }
137
+
138
+		return $schema;
139
+	}
140
+}
0 141
new file mode 100644
... ...
@@ -0,0 +1,342 @@
1
+<?php
2
+/**
3
+ * @copyright 2021 Double Bastion LLC <www.doublebastion.com>
4
+ *
5
+ * @author Double Bastion LLC
6
+ *
7
+ * @license GNU AGPL version 3 or any later version
8
+ *
9
+ * This program is free software; you can redistribute it and/or
10
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
11
+ * License as published by the Free Software Foundation; either
12
+ * version 3 of the License, or any later version.
13
+ *
14
+ * This program is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
18
+ *
19
+ * You should have received a copy of the GNU Affero General Public
20
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
+ *
22
+ */
23
+
24
+declare(strict_types=1);
25
+
26
+namespace OCA\PaxFax\Service;
27
+
28
+use OCP\DB\QueryBuilder\IQueryBuilder;
29
+use OCP\IDBConnection;
30
+use OCP\Security\ICrypto;
31
+use OCP\AppFramework\ApiController;
32
+use OCP\IRequest;
33
+use OCP\AppFramework\Controller;
34
+use OCP\Files\IAppData;
35
+use OCP\AppFramework\App;
36
+use OCP\Files\NotPermittedException;
37
+use OCP\Files\Folder;
38
+use OC\Files\Filesystem;
39
+use \ReflectionClass;
40
+
41
+use Phaxio;
42
+use Phaxio\OperationResult;
43
+use Phaxio\Error\AuthenticationException;
44
+use Phaxio\Error\NotFoundException;
45
+use Phaxio\Error\InvalidRequestException;
46
+use Phaxio\Error\RateLimitException;
47
+use Phaxio\Error\APIConnectionException;
48
+use Phaxio\Error\GeneralException;
49
+
50
+
51
+class PaxfaxService {
52
+
53
+      private $connection;
54
+
55
+      private $crypto;
56
+
57
+      public function __construct(IDBConnection $connection, ICrypto $crypto) {
58
+
59
+              $this->connection = $connection;
60
+
61
+              $this->crypto = $crypto;
62
+      }
63
+
64
+
65
+      /**
66
+       * @NoAdminRequired
67
+       */
68
+      public function object_to_array($obj) {
69
+         if(is_object($obj)) $obj = (array)$this->dismount($obj);
70
+         if(is_array($obj)) {
71
+            $new = array();
72
+            foreach($obj as $key => $val) {
73
+                $new[$key] = $this->object_to_array($val);
74
+            }
75
+         }
76
+         else $new = $obj;
77
+         return $new;
78
+      }
79
+
80
+
81
+      /**
82
+       * @NoAdminRequired
83
+       */
84
+      public function dismount($object) {
85
+         $reflectionClass = new ReflectionClass(get_class($object));
86
+         $array = array();
87
+         foreach ($reflectionClass->getProperties() as $property) {
88
+            $property->setAccessible(true);
89
+            $array[$property->getName()] = $property->getValue($object);
90
+            $property->setAccessible(false);
91
+         }
92
+         return $array;
93
+      }
94
+
95
+
96
+      /**
97
+       * @NoAdminRequired
98
+       *
99
+       */
100
+      public function getsettings($userId) {
101
+
102
+          $sql = $this->connection->prepare('
103
+	           SELECT `id`, `user_id`, `api_key`, `api_secret`, `webhook_token`, `receive_url`, `sinch_project_id`, `sinch_key_id`, `sinch_key_secret`, `sinch_service_id`, `sinch_callback_url`, `get_notification`, `notification_email` 
104
+                   FROM `*PREFIX*pax_fax`
105
+                   WHERE `user_id` = ?');
106
+	  $result = $sql->execute([$userId]);
107
+          $settingsfromdb = $result->fetch();
108
+          $result->closeCursor();
109
+
110
+          if ($settingsfromdb) {
111
+
112
+              if ($settingsfromdb['api_key'] != '') {
113
+
114
+                  // Send a placeholder to the browser, instead of the real data
115
+                  $settingsfromdb['api_key'] = "%20%20%20%20%20%20%20%20%20%20%20%20%20%20";
116
+              }
117
+              if ($settingsfromdb['api_secret'] != '') {
118
+                  $settingsfromdb['api_secret'] = "%20%20%20%20%20%20%20%20%20%20%20%20%20%20";
119
+              }
120
+              if ($settingsfromdb['webhook_token'] != '') {
121
+                  $settingsfromdb['webhook_token'] = "%20%20%20%20%20%20%20%20%20%20%20";
122
+              }
123
+              if ($settingsfromdb['receive_url'] != '') {
124
+                  $settingsfromdb['receive_url']= "%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20";
125
+              }
126
+              if ($settingsfromdb['sinch_project_id'] != '') {
127
+                  $settingsfromdb['sinch_project_id'] = "%20%20%20%20%20%20%20%20%20%20%20%20";
128
+              }
129
+              if ($settingsfromdb['sinch_key_id'] != '') {
130
+                  $settingsfromdb['sinch_key_id'] = "%20%20%20%20%20%20%20%20%20%20%20%20";
131
+              }
132
+              if ($settingsfromdb['sinch_key_secret'] != '') {
133
+                  $settingsfromdb['sinch_key_secret'] = "%20%20%20%20%20%20%20%20%20%20%20%20";
134
+              }
135
+              if ($settingsfromdb['sinch_service_id'] != '') {
136
+                  $settingsfromdb['sinch_service_id'] = "%20%20%20%20%20%20%20%20%20%20%20%20";
137
+              }
138
+              if ($settingsfromdb['sinch_callback_url'] != '') {
139
+                  $settingsfromdb['sinch_callback_url'] = "%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20";
140
+              }
141
+              return $settingsfromdb;
142
+          }
143
+      }
144
+
145
+
146
+      /**
147
+       * @NoAdminRequired
148
+       *
149
+       */
150
+      public function updatesettings($userId, $apiKey, $apiSecret, $webhookToken, $receiveUrl, $sinchProjectId, $sinchKeyId, $sinchKeySecret, $sinchServiceId, $sinchCallbackUrl, $getNotification, $notificationEmail) {
151
+
152
+          $sqlsel = $this->connection->prepare('
153
+	             SELECT `id`, `user_id`, `api_key`, `api_secret`, `webhook_token`, `receive_url`, `sinch_project_id`, `sinch_key_id`, `sinch_key_secret`, `sinch_service_id`, `sinch_callback_url`, `get_notification`, `notification_email` 
154
+                     FROM `*PREFIX*pax_fax`
155
+                     WHERE `user_id` = ?');
156
+	  $resultsel = $sqlsel->execute([$userId]);
157
+          $row = $resultsel->fetch();
158
+          $resultsel->closeCursor();
159
+
160
+          if ($resultsel && !$row) {
161
+
162
+              if ($apiKey != '') {
163
+                  $apikeystrenc = $this->crypto->encrypt($apiKey);                
164
+              } else { $apikeystrenc = ''; }
165
+
166
+              if ($apiSecret != '') {
167
+                  $apisecretstrenc = $this->crypto->encrypt($apiSecret);                
168
+              } else { $apisecretstrenc = ''; }
169
+
170
+              if ($webhookToken != '') {
171
+                  $webhookTokenenc = $this->crypto->encrypt($webhookToken);               
172
+              } else { $webhookTokenenc = ''; }
173
+
174
+              if ($receiveUrl != '') {
175
+                  $receiveUrlenc = $this->crypto->encrypt($receiveUrl);                
176
+              } else { $receiveUrlenc = ''; }
177
+
178
+              if ($sinchProjectId != '') {
179
+                  $sinchProjectIdenc = $this->crypto->encrypt($sinchProjectId);                
180
+              } else { $sinchProjectIdenc = ''; }
181
+
182
+              if ($sinchKeyId != '') {
183
+                  $sinchKeyIdenc = $this->crypto->encrypt($sinchKeyId);                
184
+              } else { $sinchKeyIdenc = ''; }
185
+
186
+              if ($sinchKeySecret != '') {
187
+                  $sinchKeySecretenc = $this->crypto->encrypt($sinchKeySecret);                
188
+              } else { $sinchKeySecretenc = ''; }
189
+
190
+              if ($sinchServiceId != '') {
191
+                  $sinchServiceIdenc = $this->crypto->encrypt($sinchServiceId);                
192
+              } else { $sinchServiceIdenc = ''; }
193
+
194
+              if ($sinchCallbackUrl != '') {
195
+                  $sinchCallbackUrlenc = $this->crypto->encrypt($sinchCallbackUrl);                
196
+              } else { $sinchCallbackUrlenc = ''; }
197
+
198
+              $sqlns = $this->connection->prepare('
199
+				INSERT INTO `*PREFIX*pax_fax`
200
+					(`user_id`, `api_key`, `api_secret`, `webhook_token`, `receive_url`, `sinch_project_id`, `sinch_key_id`, `sinch_key_secret`, `sinch_service_id`, `sinch_callback_url`, `get_notification`, `notification_email`)
201
+				VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');
202
+	      $sqlns->execute([$userId, $apikeystrenc, $apisecretstrenc, $webhookTokenenc, $receiveUrlenc, $sinchProjectIdenc, $sinchKeyIdenc, $sinchKeySecretenc, $sinchServiceIdenc, $sinchCallbackUrlenc, $getNotification, $notificationEmail]);
203
+
204
+          } elseif ($resultsel && $row) {  
205
+
206
+              if ($apiKey != '' && $apiKey != "%20%20%20%20%20%20%20%20%20%20%20%20%20%20") {
207
+                  $apikeystrenc = $this->crypto->encrypt($apiKey);                
208
+              } elseif ($apiKey == "%20%20%20%20%20%20%20%20%20%20%20%20%20%20") {
209
+                  $apikeystrenc = $row['api_key'];
210
+              } elseif ($apiKey == '') {
211
+                  $apikeystrenc = '';
212
+              }
213
+
214
+              if ($apiSecret != '' && $apiSecret != "%20%20%20%20%20%20%20%20%20%20%20%20%20%20") {
215
+                  $apisecretstrenc = $this->crypto->encrypt($apiSecret);                
216
+              } elseif ($apiSecret == "%20%20%20%20%20%20%20%20%20%20%20%20%20%20") {
217
+                  $apisecretstrenc = $row['api_secret'];
218
+              } elseif ($apiSecret == '') {
219
+                  $apisecretstrenc = '';
220
+              }
221
+
222
+              if ($webhookToken != '' && $webhookToken != "%20%20%20%20%20%20%20%20%20%20%20") {
223
+                  $webhookTokenenc = $this->crypto->encrypt($webhookToken);                
224
+              } elseif ($webhookToken == "%20%20%20%20%20%20%20%20%20%20%20") {
225
+                  $webhookTokenenc = $row['webhook_token'];
226
+              } elseif ($webhookToken == '') {
227
+                  $webhookTokenenc = '';
228
+              }
229
+
230
+              if ($receiveUrl != '' && $receiveUrl != "%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20") {
231
+                  $receiveUrlenc = $this->crypto->encrypt($receiveUrl);                
232
+              } elseif ($receiveUrl == "%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20") {
233
+                  $receiveUrlenc = $row['receive_url'];
234
+              } elseif ($receiveUrl == '') {
235
+                  $receiveUrlenc = '';
236
+              }
237
+
238
+              if ($sinchProjectId != '' && $sinchProjectId != "%20%20%20%20%20%20%20%20%20%20%20%20") {
239
+                  $sinchProjectIdenc = $this->crypto->encrypt($sinchProjectId);                
240
+              } elseif ($sinchProjectId == "%20%20%20%20%20%20%20%20%20%20%20%20") {
241
+                  $sinchProjectIdenc = $row['sinch_project_id'];
242
+              } elseif ($sinchProjectId == '') {
243
+                  $sinchProjectIdenc = '';
244
+              }
245
+
246
+              if ($sinchKeyId != '' && $sinchKeyId != "%20%20%20%20%20%20%20%20%20%20%20%20") {
247
+                  $sinchKeyIdenc = $this->crypto->encrypt($sinchKeyId);                
248
+              } elseif ($sinchKeyId == "%20%20%20%20%20%20%20%20%20%20%20%20") {
249
+                  $sinchKeyIdenc = $row['sinch_key_id'];
250
+              } elseif ($sinchKeyId == '') {
251
+                  $sinchKeyIdenc = '';
252
+              }
253
+
254
+              if ($sinchKeySecret != '' && $sinchKeySecret != "%20%20%20%20%20%20%20%20%20%20%20%20") {
255
+                  $sinchKeySecretenc = $this->crypto->encrypt($sinchKeySecret);                
256
+              } elseif ($sinchKeySecret == "%20%20%20%20%20%20%20%20%20%20%20%20") {
257
+                  $sinchKeySecretenc = $row['sinch_key_secret'];
258
+              } elseif ($sinchKeySecret == '') {
259
+                  $sinchKeySecretenc = '';
260
+              }
261
+
262
+              if ($sinchServiceId != '' && $sinchServiceId != "%20%20%20%20%20%20%20%20%20%20%20%20") {
263
+                  $sinchServiceIdenc = $this->crypto->encrypt($sinchServiceId);                
264
+              } elseif ($sinchServiceId == "%20%20%20%20%20%20%20%20%20%20%20%20") {
265
+                  $sinchServiceIdenc = $row['sinch_service_id'];
266
+              } elseif ($sinchServiceId == '') {
267
+                  $sinchServiceIdenc = '';
268
+              }
269
+
270
+              if ($sinchCallbackUrl != '' && $sinchCallbackUrl != "%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20") {
271
+                  $sinchCallbackUrlenc = $this->crypto->encrypt($sinchCallbackUrl);                
272
+              } elseif ($sinchCallbackUrl == "%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20") {
273
+                  $sinchCallbackUrlenc = $row['sinch_callback_url'];
274
+              } elseif ($sinchCallbackUrl == '') {
275
+                  $sinchCallbackUrlenc = '';
276
+              }
277
+
278
+	      $sqlup = $this->connection->prepare('
279
+			UPDATE `*PREFIX*pax_fax`
280
+			SET `api_key` = ?, `api_secret` = ?, `webhook_token` = ?, `receive_url` = ?, `sinch_project_id` = ?, `sinch_key_id` = ?, `sinch_key_secret` = ?, `sinch_service_id` = ?, `sinch_callback_url` = ?, `get_notification` = ?, `notification_email` = ?
281
+                        WHERE `user_id` = ?');
282
+	      $updateRes = $sqlup->execute([$apikeystrenc, $apisecretstrenc, $webhookTokenenc, $receiveUrlenc, $sinchProjectIdenc, $sinchKeyIdenc, $sinchKeySecretenc, $sinchServiceIdenc, $sinchCallbackUrlenc, $getNotification, $notificationEmail, $userId]);
283
+	      $updateRes->closeCursor();
284
+          }
285
+      }
286
+
287
+      /**
288
+       * @NoAdminRequired
289
+       */
290
+      public function getapicredentials($userId) {
291
+
292
+              $sqlselcr = $this->connection->prepare('
293
+	                    SELECT `id`, `user_id`, `api_key`, `api_secret`, `webhook_token`, `receive_url`, `sinch_project_id`, `sinch_key_id`, `sinch_key_secret`, `sinch_service_id`, `sinch_callback_url`, `get_notification`, `notification_email` 
294
+                            FROM `*PREFIX*pax_fax`
295
+                            WHERE `user_id` = ?');
296
+	      $resultselcr = $sqlselcr->execute([$userId]);
297
+              $settingsfrdb = $resultselcr->fetch();
298
+              $resultselcr->closeCursor();
299
+
300
+              if (($settingsfrdb['api_key'] != '') && ($settingsfrdb['api_key'] != 'undefined') && ($settingsfrdb['api_key'] != null)) {
301
+                   $apikeystr = $this->crypto->decrypt($settingsfrdb['api_key']);
302
+              } else { $apikeystr = ''; }
303
+
304
+              if (($settingsfrdb['api_secret'] != '') && ($settingsfrdb['api_secret'] != 'undefined') && ($settingsfrdb['api_secret'] != null)) {              
305
+                   $apisecretstr = $this->crypto->decrypt($settingsfrdb['api_secret']);
306
+              } else { $apisecretstr = ''; }
307
+
308
+              if (($settingsfrdb['webhook_token'] != '') && ($settingsfrdb['webhook_token'] != 'undefined') && ($settingsfrdb['webhook_token'] != null)) {            
309
+                   $webhookToken = $this->crypto->decrypt($settingsfrdb['webhook_token']);
310
+              } else { $webhookToken = ''; }
311
+
312
+              if (($settingsfrdb['receive_url'] != '') && ($settingsfrdb['receive_url'] != 'undefined') && ($settingsfrdb['receive_url'] != null)) {
313
+                   $receiveUrl = $this->crypto->decrypt($settingsfrdb['receive_url']);
314
+              } else { $receiveUrl = ''; }
315
+
316
+              if (($settingsfrdb['sinch_project_id'] != '') && ($settingsfrdb['sinch_project_id'] != 'undefined') && ($settingsfrdb['sinch_project_id'] != null)) {
317
+                   $sinchProjectId = $this->crypto->decrypt($settingsfrdb['sinch_project_id']);
318
+              } else { $sinchProjectId = ''; }
319
+
320
+              if (($settingsfrdb['sinch_key_id'] != '') && ($settingsfrdb['sinch_key_id'] != 'undefined') && ($settingsfrdb['sinch_key_id'] != null)) {
321
+                   $sinchKeyId = $this->crypto->decrypt($settingsfrdb['sinch_key_id']);
322
+              } else { $sinchKeyId = ''; }
323
+
324
+              if (($settingsfrdb['sinch_key_secret'] != '') && ($settingsfrdb['sinch_key_secret'] != 'undefined') && ($settingsfrdb['sinch_key_secret'] != null)) {
325
+                   $sinchKeySecret = $this->crypto->decrypt($settingsfrdb['sinch_key_secret']);
326
+              } else { $sinchKeySecret = ''; }
327
+
328
+              if (($settingsfrdb['sinch_service_id'] != '') && ($settingsfrdb['sinch_service_id'] != 'undefined') && ($settingsfrdb['sinch_service_id'] != null)) {
329
+                   $sinchServiceId = $this->crypto->decrypt($settingsfrdb['sinch_service_id']);
330
+              } else { $sinchServiceId = ''; }
331
+
332
+              if (($settingsfrdb['sinch_callback_url'] != '') && ($settingsfrdb['sinch_callback_url'] != 'undefined') && ($settingsfrdb['sinch_callback_url'] != null)) {
333
+                   $sinchCallbackUrl = $this->crypto->decrypt($settingsfrdb['sinch_callback_url']);
334
+              } else { $sinchCallbackUrl = ''; }
335
+
336
+              $getnotification = $settingsfrdb['get_notification'];
337
+              $notifyemail = $settingsfrdb['notification_email'];
338
+
339
+              return [$apikeystr, $apisecretstr, $webhookToken, $receiveUrl, $sinchProjectId, $sinchKeyId, $sinchKeySecret, $sinchServiceId, $sinchCallbackUrl, $getnotification, $notifyemail];
340
+      }
341
+
342
+}
0 343
new file mode 100644
... ...
@@ -0,0 +1,116 @@
1
+<?php
2
+/**
3
+ * @copyright 2021 Double Bastion LLC <www.doublebastion.com>
4
+ *
5
+ * @author Double Bastion LLC
6
+ *
7
+ * @license GNU AGPL version 3 or any later version
8
+ *
9
+ * This program is free software; you can redistribute it and/or
10
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
11
+ * License as published by the Free Software Foundation; either
12
+ * version 3 of the License, or any later version.
13
+ *
14
+ * This program is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
18
+ *
19
+ * You should have received a copy of the GNU Affero General Public
20
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
+ *
22
+ */
23
+
24
+declare(strict_types=1);
25
+
26
+script('pax_fax', 'sendfax');
27
+style('pax_fax', 'style');
28
+
29
+?>
30
+
31
+<div id="pax_fax_vbar">
32
+
33
+    <div id="currentbaldiv">Balance:
34
+            <div id="currentbalance"></div>
35
+            <button id="checkbalance" title="Refresh to see the current balance."></button>
36
+    </div>
37
+
38
+    <div id="faxnumbersdiv" class="cllridcls">
39
+            <div id="pickid">Set ID:</div>
40
+            <select id="currentfaxnmbrs" class="optselectfxnb">
41
+               <option value="" selected="selected" disabled hidden class="optselectfxnb">click refresh button</option>
42
+            </select>
43
+            <button id="selectcalleridbttn" title="Refresh the list of Sender IDs."></button>
44
+            <div class="fortooltipinit">
45
+                 <div id="infosetid">i</div>
46
+                 <span class="calleridtooltip">The Caller ID is the 'From' number that the receiver sees on the fax that you send. You can set as
47
+                       Caller ID one of your fax numbers (first refresh the list, then select from the drop-down). Phaxio also allows a blank Caller ID.
48
+                 </span>
49
+            </div>
50
+    </div>
51
+
52
+    <div  class="pfheader">
53
+            Enter the recipient's number as:
54
+    </div>
55
+    <div class="faxnbformat">
56
+            <a id="countryCallCode" href="https://en.wikipedia.org/wiki/List_of_country_calling_codes#Alphabetical_order"
57
+               target="_blank" rel="noreferrer noopener">CountryCallingCode</a><font style="color:#aa2e4b">FaxNumber</font>
58
+    </div>
59
+    <div class="fortooltip">
60
+         <div id="infonumber">i</div>
61
+         <span class="fortooltiptext">
62
+            For example, to send a fax to the German fax number 1212121212, enter 491212121212, where 49 is the country calling code of Germany. (For US the calling
63
+            code is 1, for UK 44, for France 33, etc.) The <a href="https://en.wikipedia.org/wiki/List_of_country_calling_codes#Alphabetical_order"
64
+            target="_blank" rel="noreferrer noopener" style="color:#1b60ba">country calling code</a> must be always included, even if the fax is sent locally. 
65
+            You don't need to add the '+' sign or '00' in front of the number, because the '+' sign will be added automatically. If you want to send the same fax simultaneously 
66
+            to multiple numbers, add them one after the other separated by a comma like this: 497777777777,442222222222 You can send a fax to up to 15 numbers at once.
67
+         </span>
68
+    </div>
69
+
70
+    <div id="faxtodiv">
71
+         <input type="text" id="faxto" name="faxto" />
72
+    </div>
73
+
74
+    <div class="pfheader">Choose the document(s) that you want to send as fax:</div>
75
+    <div class="fortooltipsec">
76
+          <div id="infoformat">i</div>
77
+          <span class="fortooltiptextsec">
78
+              Phaxio supports pdf, odt, jpeg/jpg, png, txt, tiff/tif, html, doc and docx files, while Sinch supports pdf, jpeg/jpg, png, txt, tiff/tif, html and docx files. You can send up to 20 files with a cumulative size of up to 20 MB and up to 200 pages, in one fax call. (docx and doc files can be sent as fax but cannot be previewed in the adjoining preview pane. Preview docx and doc files outside Pax Fax before sending them.)
79
+          </span>
80
+    </div>
81
+
82
+    <div id="filestotsize">Total files size:<div id="filessizetext"></div></div>
83
+
84
+    <div id="fileuploadednm" class="fileuploadstl"></div>
85
+    <div class="uploadfiledv">
86
+          <form class="uploadflbt"  enctype="multipart/form-data" >
87
+                <div id="uploadFile">Upload a file</div>
88
+                <input id="uploadfileforfax" class="fileupload" name="uploadedtofax[]" type="file" multiple />
89
+                <label for="uploadfileforfax" class="button icon-upload svg" id="uploadfileforfax" </label>
90
+          </form>
91
+    </div>
92
+
93
+    <div id="pf_upload_msg"></div>
94
+
95
+    <div id="filespickednc" class="filesfromnc"></div>
96
+  
97
+    <div id="pickFromNext">Pick from Nextcloud</div>
98
+
99
+    <button id="choosefilen"></button>
100
+
101
+    <div id="pf_choose_msg"></div>
102
+
103
+    <p class="pickedflnm"></p>
104
+
105
+    <input type="submit" id="submitfax" value="Send Fax" />
106
+
107
+    <div id="pf_submit_msg"></div>
108
+
109
+    <div id="dirbuttons">
110
+       <button id="receivedfaxdir" class="openfaxfolder">Received Faxes</button>
111
+       <button id="sentfaxdir" class="openfaxfolder">Sent Faxes</button>
112
+       <button id="receivedfaileddir" class="openfaxfolder">Failed Received Faxes</button>
113
+       <button id="sentfaileddir" class="openfaxfolder">Failed Sent Faxes</button>
114
+    </div>
115
+
116
+</div>
0 117
new file mode 100644
... ...
@@ -0,0 +1,143 @@
1
+<?php
2
+/**
3
+ * @copyright 2021 Double Bastion LLC <www.doublebastion.com>
4
+ *
5
+ * @author Double Bastion LLC
6
+ *
7
+ * @license GNU AGPL version 3 or any later version
8
+ *
9
+ * This program is free software; you can redistribute it and/or
10
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
11
+ * License as published by the Free Software Foundation; either
12
+ * version 3 of the License, or any later version.
13
+ *
14
+ * This program is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
18
+ *
19
+ * You should have received a copy of the GNU Affero General Public
20
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
+ *
22
+ */
23
+
24
+declare(strict_types=1);
25
+
26
+script('pax_fax', 'settings');
27
+style('pax_fax', 'style');
28
+
29
+?>
30
+
31
+<div id="pax_fax_adm">
32
+	<div class="section">
33
+           <h2><?php p($l->t('Pax Fax'));?></h2>
34
+	   <p id="settings-dscr"><?php p($l->t('Enter either your Phaxio credentials or your Sinch credentials in the fields from below:')); ?></p><br>
35
+
36
+           <div class="stp_followupsection">
37
+
38
+                <form id="phaxio_credentials" action="#" >
39
+
40
+                   <p><label for="api_key" class="setlabeltext"><b><?php p($l->t('Phaxio API Key'));?></b> (Log in to your Phaxio account, click 'API Keys' on the left
41
+                          panel, then, under 'Live Keys' you will find the 'API Key'. Enter the 'API Key' in the field from below.):</label></p>
42
+                   <input type="password" class="pax_fax_box" id="api_key" name="api_key" autocomplete="false"
43
+                          placeholder="E.g.: d6f172ce92e4f2 ..." /><br>
44
+
45
+                   <p><label for="api_secret" class="setlabeltext"><b><?php p($l->t('Phaxio API Secret'));?></b> (While logged in to your Phaxio account, click 'API Keys' on the left
46
+                          panel, then, under 'Live Keys' you will find the 'API Secret'. Enter the 'API Secret' in the field from below.):</label></p>
47
+                   <input type="password" class="pax_fax_box" id="api_secret" name="api_secret" autocomplete="false"
48
+                          placeholder="E.g.: 8af589b8ad9579 ..." /><br>
49
+
50
+                   <p><label for="webhook_token" class="setlabeltext"><b><?php p($l->t('Phaxio Webhook Token'));?></b> (While logged in to your Phaxio account, click 'Webhooks' on the
51
+                          left panel, then copy the token found under 'Webhook Token' and enter it in the field from below.):</label></p>
52
+                   <input type="password" class="pax_fax_box" id="webhook_token" name="webhook_token" autocomplete="false"
53
+                          placeholder="E.g.: b6d90b72ab6cce450025abd46f4d697" /><br>
54
+
55
+                   <p><label for="receive_url" class="setlabeltext"><b>Phaxio callback URL for incoming faxes</b> (This URL must have the form:
56
+                          <b>https://<font style="color:#a11a1a;">username</font>:<font
57
+                          style="color:#a11a1a;">6VTGs-c36j4-qK2wm-RgJcl-9pjUD</font>@<font style="color:#a11a1a;">cloud.example.com</font>/apps/pax_fax/api/recfaxphaxio</b> if 
58
+                          Nextcloud is served on a subdomain, or <b>https://<font style="color:#a11a1a;">username</font>:<font
59
+                          style="color:#a11a1a;">6VTGs-c36j4-qK2wm-RgJcl-9pjUD</font>@<font style="color:#a11a1a;">example.com/nextcloud</font>/apps/pax_fax/api/recfaxphaxio</b> 
60
+                          if Nextcloud is served on a subdirectory, where <b><font style="color:#a11a1a;">username</font></b> is the Nextcloud user who has a Phaxio phone number 
61
+                          in his Phaxio account (Callback URLs can only be configured one per Phaxio phone number. If <b><font style="color:#a11a1a;">username</font></b> 
62
+                          contains an <b>@</b> , replace <b>@</b> with <b>&amp;commat;</b> otherwise the URL won't function), 
63
+                          <b><font style="color:#a11a1a;">6VTGs-c36j4-qK2wm-RgJcl-9pjUD</font></b> is the 'application password' created for this purpose as explained below, and 
64
+                          <b><font style="color:#a11a1a;">cloud.example.com</font></b> is your Nextcloud domain. To create the Nextcloud 'application password' click on the user 
65
+                          picture in the upper right corner, then click 'Personal settings', then, on the left panel, under 'Personal' click 'Security', then under 'Devices & sessions', 
66
+                          in the 'App name' field enter Pax_Fax, then click the 'Create new app password' button. The password will be displayed only when created. Copy the password, 
67
+                          click the 'Done' button, enter the password in the constructed callback URL between ':' and '@' as shown above, copy the entire callback URL to a safe 
68
+                          location, then enter the callback URL in the field from below. The next step is to enter the callback URL that you have just created in your Phaxio account: 
69
+                          log in to Phaxio, click 'Phone Numbers' on the left panel, click the settings wheel on the row of the phone number for which you want to set up the callback 
70
+                          URL, enter the URL in the 'Callback URL' field, then click 'Save'. Also, click on 'Webhooks' on the left panel, then scroll down to 'Webhook Version' and 
71
+                          choose 'Version 2.1.0', then click the 'Update' button. Don't forget to also click the 'Save' button at the bottom of this page to save all the settings to 
72
+                          the database.):</label></p>
73
+                   <input type="password" class="pax_fax_boxspec" id="receive_url" name="receive_url" autocomplete="false"
74
+                          placeholder="E.g.:  https://username:6VTGs-c36j4-qK2wm-RgJcl-9pjUD@cloud.example.com/apps/pax_fax/api/recfaxphaxio" /><br><br><br>
75
+
76
+                   <p><label for="sinch_project_id" class="setlabeltext"><b><?php p($l->t('Sinch Project ID'));?></b> (While logged in to your Sinch account, click the 'Project' 
77
+                          drop-down menu located at the left end of the upper bar, then click 'View all projects'. On the 'Projects' page you will see a list with all the available 
78
+                          projects and their respective Project IDs. Copy the ID of the project that you use for faxing (usually this is the default 'First project') and paste it in 
79
+                          the field from below.):</label></p>
80
+                   <input type="password" class="pax_fax_box" id="sinch_project_id" name="sinch_project_id" autocomplete="false"
81
+                          placeholder="E.g.: d5d91b72ab6cce450024abd46f4d6d9" /><br>
82
+
83
+                   <p><label for="sinch_key_id" class="setlabeltext"><b><?php p($l->t('Sinch Key ID'));?></b> (While logged in to your Sinch account, select the name of the project
84
+                          you use for faxing from the 'Project' drop-down menu on the upper bar (usually this is the default 'First project'), then click 'Settings' on the left panel,
85
+                          then click 'Access Keys'. On the 'Access Keys' page you will see a list with all the access keys for the selected project. If you haven't created any access
86
+                          keys for the project, create a key by clicking the 'Create access key' button. On the 'Create Access Key' popup window, in the 'Name' field enter a display 
87
+                          name for your key and click 'Create'. The access key will be created and the Key ID and Key Secret window will be displayed. Copy the Key ID and Key Secret
88
+                          to a safe location, then enter the Key ID in the field from below. The Key Secret can be viewed only when the key is created. If you lose it, simply 
89
+                          generate a new key. Each project has its own set of access keys.):</label></p>
90
+                   <input type="password" class="pax_fax_box" id="sinch_key_id" name="sinch_key_id" autocomplete="false"
91
+                          placeholder="E.g.: c0d50b72ab6ced450025abd46f6d5c4" /><br>
92
+
93
+                   <p><label for="sinch_key_secret" class="setlabeltext"><b><?php p($l->t('Sinch Key Secret'));?></b> (Copy the Key Secret created as described above, in the field from
94
+                          below.):</label></p>
95
+                   <input type="password" class="pax_fax_box" id="sinch_key_secret" name="sinch_key_secret" autocomplete="false"
96
+                          placeholder="E.g.: e4d50b72ab6cdf450025abd46f4d6c2" /><br>
97
+
98
+                   <p><label for="sinch_service_id" class="setlabeltext"><b><?php p($l->t('Sinch service ID'));?></b> (While logged in to your Sinch account click 'Fax' on the left 
99
+                          panel, then click 'Services'. On the 'Services' page you will see a list with your fax services. If you haven't created any service manually, you will see 
100
+                          only the 'Default Service' created automatically. If you want to associate different callback URLs (for incoming faxes) with different numbers, you will 
101
+                          want to create multiple services and assign a different callback URL and a different set of numbers to each service. You can create a new service by clicking 
102
+                          'Add New Service' on the 'Services' page. If you don't need multiple services, just use the 'Default Service'. On the 'Services' page, below the name of each 
103
+                          fax service you will see its ID. Copy the ID of the service you want to use, in the field from below.):</label></p>
104
+                   <input type="password" class="pax_fax_box" id="sinch_service_id" name="sinch_service_id" autocomplete="false"
105
+                          placeholder="E.g.: e6d50b72ab6cbe450025abd46f4d74d" /><br>
106
+
107
+                   <p><label for="sinch_callback_url" class="setlabeltext"><b><?php p($l->t('Sinch callback URL for incoming faxes'));?></b> (The callback URL for incoming faxes must 
108
+                          have the form: <b>https://<font style="color:#a11a1a;">username</font>:<font style="color:#a11a1a;">6VTGs-c36j4-qK2wm-RgJcl-9pjUD</font>@<font style="color:#a11a1a;">cloud.example.com</font>/apps/pax_fax/api/recfaxsinch</b> if Nextcloud is served on a subdomain, or <b>https://<font 
109
+                          style="color:#a11a1a;">username</font>:<font style="color:#a11a1a;">6VTGs-c36j4-qK2wm-RgJcl-9pjUD</font>@<font style="color:#a11a1a;">example.com/nextcloud</font>/apps/pax_fax/api/recfaxsinch</b> if Nextcloud is served on a subdirectory, where <b><font style="color:#a11a1a;">username</font>
110
+                          </b> is the Nextcloud user who has a Sinch phone number in his Sinch account (If <b><font style="color:#a11a1a;">username</font></b> contains an <b>@</b> , 
111
+                          replace <b>@</b> with <b>&amp;commat;</b> otherwise the URL won't function), <b><font style="color:#a11a1a;">6VTGs-c36j4-qK2wm-RgJcl-9pjUD</font></b> is the 
112
+                          'application password' created for this purpose as explained below, and <b><font style="color:#a11a1a;">cloud.example.com</font></b> is your Nextcloud domain. 
113
+                          To create the Nextcloud 'application password' click on the user picture in the upper right corner, then click 'Personal settings', then, on the left panel, 
114
+                          under 'Personal' click 'Security', then under 'Devices & sessions', in the 'App name' field enter Pax_Fax, then click the 'Create new app password' button. 
115
+                          The password will be displayed only when created. Copy the password, click the 'Done' button, enter the password in the constructed callback URL between ':' 
116
+                          and '@' as shown above, copy the entire callback URL to a safe location, then enter the callback URL in the field from below. Next, while logged in to your 
117
+                          Sinch account click 'Fax' on the left panel, then click 'Services'. On the 'Services' page click the name of the service you want to use, then, on the 
118
+                          'Incoming' tab, in the 'Incoming webhook url' field enter the callback URL for incoming faxes that you have just created, under 'Webhook content type' select
119
+                          'multipart/form-data' and click 'Save'.):</label></p>
120
+                   <input type="password" class="pax_fax_box" id="sinch_callback_url" name="sinch_callback_url" autocomplete="false"
121
+                          placeholder="E.g.:  https://username:5CHGv-c36j9-kV2wm-RgJcl-7pjVE@cloud.example.com/apps/pax_fax/api/recfaxsinch" /><br><br>
122
+
123
+                   <p><label for="get_notification" class="setlabeltext"><b><?php p($l->t('I want to see a notification in Nextcloud when a new fax is received:'));?></b></label></p>
124
+                   <input type="checkbox" class="pax_fax_checkbox" id="get_notification" name="get_notification" autocomplete="false" /><br>
125
+
126
+                   <p><label for="notification_email" class="setlabeltext"><b><?php p($l->t('I want to receive a notification to the email address from below, when a new fax is received'));?></b>
127
+                          (To enable email notifications for every received fax, the "sendmail" utility  ("/usr/sbin/sendmail" on Debian Linux), has to be present on the server. "sendmail" 
128
+                          is a binary that gets installed when Postfix is installed. Also, the web server user (www-data) has to be allowed to send emails from command line (by 
129
+                          specifying "authorized_submit_users = www-data" in "/etc/postfix/main.cf" for Postfix on a Debian based Linux distribution).):
130
+                      </label></p>
131
+                   <input type="text" class="pax_fax_box" id="notification_email" name="notification_email" autocomplete="false"
132
+                          placeholder="E.g.: john.doe@example.com" /><br>
133
+
134
+                   <input type="hidden" id="user_id" name="user_id" />
135
+
136
+                   <input id="save_fax_settings" type="submit" value="<?php p($l->t('Save')) ?>" />
137
+
138
+                   <span id="paxfax_save_msg"></span>
139
+
140
+               </form>
141
+           </div>
142
+        </div>
143
+</div>