@@ -25,71 +25,71 @@ discard block |
||
| 25 | 25 | use Test\TestCase; |
| 26 | 26 | |
| 27 | 27 | class AppFetcherTest extends TestCase { |
| 28 | - /** @var IAppData|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 29 | - protected $appData; |
|
| 30 | - /** @var IClientService|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 31 | - protected $clientService; |
|
| 32 | - /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 33 | - protected $timeFactory; |
|
| 34 | - /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 35 | - protected $config; |
|
| 36 | - /** @var CompareVersion|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 37 | - protected $compareVersion; |
|
| 38 | - /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 39 | - protected $logger; |
|
| 40 | - /** @var IRegistry|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 41 | - protected $registry; |
|
| 42 | - /** @var AppFetcher */ |
|
| 43 | - protected $fetcher; |
|
| 44 | - /** @var string */ |
|
| 45 | - public static $responseJson = <<<'EOD' |
|
| 28 | + /** @var IAppData|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 29 | + protected $appData; |
|
| 30 | + /** @var IClientService|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 31 | + protected $clientService; |
|
| 32 | + /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 33 | + protected $timeFactory; |
|
| 34 | + /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 35 | + protected $config; |
|
| 36 | + /** @var CompareVersion|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 37 | + protected $compareVersion; |
|
| 38 | + /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 39 | + protected $logger; |
|
| 40 | + /** @var IRegistry|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 41 | + protected $registry; |
|
| 42 | + /** @var AppFetcher */ |
|
| 43 | + protected $fetcher; |
|
| 44 | + /** @var string */ |
|
| 45 | + public static $responseJson = <<<'EOD' |
|
| 46 | 46 | [{"id":"direct_menu","categories":["customization"],"userDocs":"","adminDocs":"","developerDocs":"","issueTracker":"https://github.com/juliushaertl/direct_menu/issues","website":"","created":"2016-10-01T09:16:06.030994Z","lastModified":"2016-10-06T14:01:05.584192Z","releases":[{"version":"0.9.2","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/juliushaertl/direct_menu/releases/download/v0.9.2/direct_menu.tar.gz","created":"2016-10-06T14:01:05.578297Z","licenses":["agpl"],"lastModified":"2016-10-06T14:01:05.643813Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"ERBS9G5bZ3vwCizz2Ht5DehsVJmb63bzF3aYcH7xjbDVMPagOFWdUAiLDwTeZR1n\ni4gdZ73J/IjHQQJoOPwtCjgbZgLPFqL5x13CLUO9mb/33dZe/+gqEDc/3AuJ4TlA\nXUdLxHRb1bwIlJOwuSr/E24452VG20WUhLXBoM0Zm7WcMxvJWo2zAWnuqnLX3dy9\ncPB4PX+6JU2lUMINj8OYQmM1QnqvjG8YV0cYHbBbnSicOGwXEnni7mojsC8T0cn7\nYEJ2O2iO9hh3fvFEXUzDcL7tDQ5bZqm63Oa991bsAJxFo/RbzeJRh//DcOrd8Ufn\nu2SqRhwybS8j4YvfjAL9RPdRfPLwf6X2gx/Y6QFrKHH0QMI/9J/ZFyoUQcqKbsHV\n85O+yuWoqVmza71tkp4n9PuMdprCinaVvHbHbNGUf2SIh9BWuEQuVvvnvB+ZW8XY\n+Cl+unzk3WgOgT0iY3uEmsQcrLIo4DSKhcNgD1NS13fR/JTSavvmOqBarUMFZfVC\nbkR1DTBCyDjdpNBidpa3/26675dz5IT5Zedp4BBBREQzX08cIhJx5mgqDdX3CU09\nuWtzoaLi71/1BWTFAN+Y9VyfZ8/Z3Pg3vKedRJ565mztIj0geL3riEsC5YnPS0+C\n+a3B9sDiiOa101EORzX3lrPqL7reEPdCxrIwN+hKFBQ=","translations":{}}],"screenshots":[{"url":"https://bitgrid.net/~jus/direct_menu_nc.png"}],"translations":{"en":{"name":"Direct Menu","summary":"Provide easy access to all apps in the header.","description":"Provide easy access to all apps in the header."}},"isFeatured":false,"authors":[{"name":"Julius Härtl","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\r\nMIIEBjCCAu4CAhADMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\r\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\r\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\r\ndXRob3JpdHkwHhcNMTYwOTE0MTI1MDU0WhcNMjYxMjIxMTI1MDU0WjAWMRQwEgYD\r\nVQQDDAtkaXJlY3RfbWVudTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB\r\nAMkzWsAkKP/40ktvJMpnr0IJNVoPOR0hvh24igcDskL1WKiD2eiRUenj5LE0Nvn+\r\nsiGmWsAqRVpdiz+Y8ghQqQMzKi43IrRN0AxlCrHWrSqBZT3wIAUcFz4RzEoFxc1N\r\nUZzWma6ljukGnvt4V1ZyT+H/cjqxUkBhh/y9SS0jUen1a1grND6Rw54X46V2dlCu\r\nFH+pLsfPJJGw+QLeTGHn7dqdv18cYMAlWDCzPixVnNiCXHZcUtKMmstU2xU4R2e6\r\nzimp2rgkE4TNHrafpjH8xGdNi2FG5Dmokob/L5Q2r8jyNaW7UsFfrvLTRj371b3/\r\n2FhhxoGUvDzaG2An02Exwm52LJfdTVMHAMPZub5poHfy5vAEdZGPQ/m02l8ZK/Y2\r\n7yT807GlfPMXfdfjCxR6wNtmv7rvBDdrUZmIRNJfpFSdvlH/+MOTWnabyfQv2K4Q\r\nBIwltX6Elh0lh4ntvt1ZVtvFv+PL1Dc7QLV+w19+/LJA0mnsh7GIFYKFlbA65gA0\r\nc/w+uqDy0+5MxkR9WGPpd79KRA1tKWTis4Ny1lApK5y3zIsVGa3DfBHXcwqkWHbV\r\nwIpyuyyDsFtC1b9LTFONX7iU9cbNk5C5GTM331MdA2kLcD/D5k42GNTBSca7MkPx\r\nFx/ETSn0Ct167el30symf2AxvXjw+mBYPN71rVTMDwe9AgMBAAEwDQYJKoZIhvcN\r\nAQELBQADggEBAC0fJKnbEhXA8M283jA9GxABxLyTBcQyVVNnz2L/bYYNi81Y9iZv\r\n+U0S3qaIfoqNcV9FTKAutbsKvWyolnI7MRRK6feNuFfoP2jKubM1CnawpyT/RF2Q\r\ne/zxnB1EmeI2X5D2xceJDLB7Fy5W0EGrLixRIdFaSUommWFUm9E2hSIaNlziSBdc\r\n1J/mOQeNYO5zg5ouEt1rzQW4Mhh1I2uNQmGe4ip+Jl/2LAv3FZuu4NrSEcoXH3ro\r\nG2dF9Gtu4GiQ5fuaJknaxlgXHovfqeZwZJX9o4M+Ug81AqiY7XjdiaCPdh0Tthcx\r\n2OmWZo7UBREWenjKyFZZ/iKoqH5sdenBtpo=\r\n-----END CERTIFICATE-----"},{"id":"apporder","categories":["customization"],"userDocs":"","adminDocs":"","developerDocs":"","issueTracker":"https://github.com/juliushaertl/apporder/issues","website":"","created":"2016-10-01T09:16:47.111889Z","lastModified":"2016-10-12T19:50:16.038821Z","releases":[{"version":"0.3.3","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/juliushaertl/apporder/releases/download/0.3.3/apporder.tar.gz","created":"2016-10-12T19:14:10.802359Z","licenses":["agpl"],"lastModified":"2016-10-12T19:50:16.104357Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"nhlT9lhrmBxIsqh/e3RLm2NDw/U8ZvvoMyYQTLMM3H19DQmVcPYPYC9QWVTsowUzXblVaOXVGylbpKma9yOlOAqJtF3qyXecLl4+tA/Awb6BBhKPgHFdcLDAL5yy1K7/uei3SgEojMlJoI9vEK5I1C5YTh43yNH+//Im6MAuNYFUTlMXK426zdOe6ogpCI5GlYdXopqYANxcpT+WXWET6DDSM5Ev+MYwMcSAY4r8+tvARRU4ZAenRgjkBT6R5z6cD76emRax14tbV6vkjjwRcO+dQtM0tFPbd+5fsNInbauv50VzIMgjA6RnKTOI17gRsSdGlsV4vZn2aIxEPWauu6T/UohMvAE9HMn13vtbpPBSFwJAktj6yHASYGzupNQLprA0+OdyALoLZPpQAKNEXA42a4EVISBKu0EmduHJlUPeqhnIGkkGgVNWS8AWqzP2nFoPdXBgUWateiMcBTHxgEKDac5YmNc9lsXpzf1OxBaXHBhGYKuXPwIfyH3jTWb1OdwixJEuRe9dl63T9qOTRre8QWns/bMqKLibGfMtFhVB21ARJayBuX70eVvabG/2N7Y5t1zUlFygIKu51tvo3AVCRDdRrFWDvkAjxzIz5FIdALVZ+DReFYu/r4WF/w3V9rInFuEDSwb/OH4r8sQycs07tSlMyA74Y3FpjKTBxso=","translations":{}},{"version":"0.3.2","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/juliushaertl/apporder/releases/download/0.3.2/apporder.tar.gz","created":"2016-10-06T14:00:51.532409Z","licenses":["agpl"],"lastModified":"2016-10-06T14:00:51.598455Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"gRVFOtj9414ZNSdRH/qNB2SwVZUQh+gaFnNLFjjXjJ1MdRMCISzvwb+QU1qYuK/y\nuL8K0pn1+fFQf8A3VsC2pb6yaLQ5U9C3Guf886Flf4qtYw1P8UWRA9yOJ+6Md+PH\n6pTEiDIdm4xbmM0KkBhsE5kL8dvLIq4EwwcAh2Qq8fjytzAk1YiP+KrTaYrVwskM\nDmm0lgP4NVnjRBTX9myW6tr6N3w0tq2jJ/+a/vEDJv+5ozKJx8N5gbJNdrtI4k7I\nyaQNWJ7cngtAHmUREeoBggV5uJayDceu83PPQR6N9/WVyNyZjw1Q8/Q6e/NyiXT2\no8mGv5tHl3DBOVuv8v7gBQgDh6ppp12M81aiCZymn2XIgjw50VQ+K15KHnLHuFFw\nwuHZVcoQ7b6oR4K4TURSfPFUeNgGS4R9v6gjg1RUcSm1Pnryc6pYnh10AUY8dk6q\n1CZ6Upt6SScP2ZEGWsFwVjjQhY/ZJmNfnhaGoFOZ5L9CnzyNCkGXFg0rL36i6djb\naqFy/z+Brnklng5ct6XWoP7uDt5BaHznQj1NHSfHn0GUQ0N968zWm9vQvy+dyXyC\nxR7vKeu2ppZ2ydoeQ9CVwfhOEsGs5OvrpapQdh9KbUHcX7b7ql01J7/P6dFuNuHe\n+7/y4ex3sEVg5YBmDtF8iZ6d7zsHd6peL1s1EsLnenQ=","translations":{}}],"screenshots":[{"url":"https://bitgrid.net/~jus/apporder-nc.gif"}],"translations":{"en":{"name":"AppOrder","summary":"Sort apps in the menu with drag and drop","description":"\nEnable sorting for icons inside the app menu. The order will be saved for each\nuser individually. Administrators can define a custom default order.\nAppOrder works with the default owncloud menu as well as with the direct_menu\napp.\n\n## Set a default order for all new users\n\nGo to the Admin settings > Additional settings and drag the icons under App order.\n\n## Use first app as default app\n\nYou can easily let Nextcloud redirect your user to the first app in their\npersonal order by changing the following parameter in your config/config.php:\n\n'defaultapp' => 'apporder',\n\nUsers will now get redirected to the first app of the default order or to the\nfirst app of the user order.\n "}},"isFeatured":false,"authors":[{"name":"Julius Härtl","mail":"[email protected]","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\r\nMIIEAzCCAusCAhAEMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\r\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\r\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\r\ndXRob3JpdHkwHhcNMTYwOTE0MTI1MjQ4WhcNMjYxMjIxMTI1MjQ4WjATMREwDwYD\r\nVQQDDAhhcHBvcmRlcjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKVK\r\nKn5jivCu+eRfe5BECjDOzNaGHlpiegb49Hf4nh0W7DqcoLHip5c1O2BcEYdH6rkw\r\n20WclvjoQpgavG5aFXzXzur6eKTT5TpgY5oZTLoWjbx4e+fKdhyDPTpqNZzs1pxz\r\nsZLDL/ElpbSErE0s+QK/pzP11WNPylAkI9AKSyDMO3Mbllg8I8Bt+bT7LJKYOO/T\r\nLhv9m0anLZ4HrdfimhVIoMiu3RpyRigk8titXZA94+F8Fbf7ZQ9f14Y/v3+rfJFQ\r\nii9cDoox5uUrjplH2LrMr5BodfCfydLu4uVpPWYkdccgvcZ1sugjvNXyCQgdzQDK\r\npOpiwVkkiQFaQJYbGSDblFWPl/cLtA/P/qS7s8tWyTQuc1rYlEpCHG/fG8ZFkSVK\r\n9eCMGxK908VB4IU2DHZHOHi7JvtOz8X/Ak6pIIFdARoW3rfKlrz6DD4T9jEgYq0n\r\nRe7YwCKEIU3liZJ+qG6LCa+rMlp/7sCzAmqBhaaaJyX4nnZCa2Q2cNZpItEAdwVc\r\nqxLYL1FiNFMSeeYhzJJoq5iMC3vp2LScUJJNoXZj9zv+uqTNGHr+bimchR2rHUBo\r\nPzDLFJmat03KdWcMYxcK5mxJNGHpgyqM7gySlbppY/cgAospE8/ygU2FlFWIC9N0\r\neDaY+T8QA1msnzsfMhYuOI8CRYigan1agGOMDgGxAgMBAAEwDQYJKoZIhvcNAQEL\r\nBQADggEBAGsECd+meXHg1rr8Wb6qrkDz/uxkY1J+pa5WxnkVcB6QrF3+HDtLMvYm\r\nTTS02ffLLyATNTOALZFSy4fh4At4SrNzl8dUaapgqk1T8f+y1FhfpZrEBsarrq+2\r\nCSKtBro2jcnxzI3BvHdQcx4RAGo8sUzaqKBmsy+JmAqpCSk8f1zHR94x4Akp7n44\r\n8Ha7u1GcHMPzSeScRMGJX/x06B45cLVGHH5GF2Bu/8JaCSEAsgETCMkc/XFMYrRd\r\nTu+WGOL2Ee5U4k4XFdzeSLODWby08iU+Gx3bXTR6WIvXCYeIVsCPKK/luvfGkiSR\r\nCpW1GUIA1cyulT4uyHf9g6BMdYVOsFQ=\r\n-----END CERTIFICATE-----"},{"id":"twofactor_totp","categories":["tools"],"userDocs":"","adminDocs":"","developerDocs":"","issueTracker":"","website":"","created":"2016-10-08T14:13:54.356716Z","lastModified":"2016-10-12T14:38:56.186269Z","releases":[{"version":"0.4.1","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":">=5.4.0 <7.1.0","platformVersionSpec":">=10.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/ChristophWurst/twofactor_totp/releases/download/0.4.1/twofactor_totp.tar.gz","created":"2016-10-12T14:38:56.174612Z","licenses":["agpl"],"lastModified":"2016-10-12T14:38:56.248223Z","isNightly":false,"rawPhpVersionSpec":">=5.4 <=7.0","rawPlatformVersionSpec":">=10 <=11","signature":"bnwWxmHEn8xkoWbtwhC1kIrJ0dQfAI3PUtU62k+Tru/BHt1G2aVxqO8bCdghojZ7\nzdFMlIJw4kekYFsVfLk8jzjUTZKVbNVKCdkHrVTQ0bUUryMAMLqGQ3PSRI5NX6D5\nFpkvwO1coYwU0XVWF8KAS0meX0ztSkT3Mv96LLrxr8F8SrB/MGmKIE4WTjt1fAIa\nZLAVEUo/3sNFTGLYBtL3wjctrkZvJltP8abeRfls9FkRHu+rN7R3uLFzk42uZn3X\nWpt5BBmlYm5ORbnJ2ApsxEkMNK+rOy8GIePaz5277ozTNrOnO04id1FXnS9mIsKD\n20nRzjekZH+nneQYoCTfnEFg2QXpW+a+zINbqCD5hivEU8utdpDAHFpNjIJdjXcS\n8MiCA/yvtwRnfqJ5Fy9BxJ6Gt05/GPUqT8DS7P1I1N+qxhsvFEdxhrm2yIOhif8o\nh7ro5ls+d3OQ8i3i4vdZm821Ytxdu/DQBHiVoOBarvFWwWAv2zd2VAvpTmk6J5yv\n3y+csRqpEJYd9fcVMPsTu7WBRRrpBsAqdAHJcZEwak2kz1kdOgSf8FIzP1z6Q71d\nMl2RKcPeutMHHSLiGIN/h7fM5aSs49wGgGZmfz28fHVd7/U0HFSMYmkT/GMq5tMP\nIyc+QZAN4qbX8G0k/QSTkK/L4lOT2hQiQqiSqmWItMk=","translations":{}}],"screenshots":[],"translations":{"en":{"name":"Two Factor TOTP Provider","summary":"A Two-Factor-Auth Provider for TOTP (e.g. Google Authenticator)","description":"A Two-Factor-Auth Provider for TOTP (e.g. Google Authenticator)"}},"isFeatured":true,"authors":[{"name":"Christoph Wurst","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\r\nMIIECTCCAvECAhASMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\r\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\r\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\r\ndXRob3JpdHkwHhcNMTYxMDEyMDkzNDMxWhcNMjcwMTE4MDkzNDMxWjAZMRcwFQYD\r\nVQQDDA50d29mYWN0b3JfdG90cDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC\r\nggIBALC1K94104L/nOtmTygx7QNjUcnHs3yrn71mw4pMxTlonXOnMTpwxsfL1Hhu\r\n/5GMSgupTbQPlevSl6J86UMs455/sPShd6ifmAuhb8VFaAsjpizjs0RMaUg1sjmF\r\nuV18PD9FXLourx51V/c4MG5kpavlV+bLUrVMAjbsJY2+k30tCC/XkP5u8jUWmM/T\r\n5REChn7/obPgaeddhuJoILYhKEW3VNrR8Fm9SYiviB3FLhM7URDZ97IBnXYqbvbT\r\nZnvq+E74Zc7HgYwQwrjU/AqQAInhNpAR4ZM6CkWWWWaL96O1q3lCfKJNaxqC0Kg/\r\nkGn/pxYkl9062jtMUz60s9OPDyuisfyl68UyM68Ozyz4SMRLmDVbewOqQAwmAbtz\r\n8p9AQrX3Pr9tXhARR4pDSsQz1z+8ExEd6EKbhMyiTtHtZQ1Vm9qfoR52snpznb5N\r\ne4TcT2qHAkOWV9+a9ESXmQz2bNjgThxEl5edTVY9m4t248lK5aBTGq5ZKGULNHSQ\r\nGGpr/ftMFpII45tSvadexUvzcR/BHt3QwBAlPmA4rWtjmOMuJGDGk+mKw4pUgtT8\r\nKvUMPQpnrbXSjKctxb3V5Ppg0UGntlSG71aVdxY1raLvKSmYeoMxUTnNeS6UYAF6\r\nI3FiuPnrjVFsZa2gwZfG8NmUPVPdv1O/IvLbToXvyieo8MbZAgMBAAEwDQYJKoZI\r\nhvcNAQELBQADggEBAEb6ajdng0bnNRuqL/GbmDC2hyy3exqPoZB/P5u0nZZzDZ18\r\nLFgiWr8DOYvS+9i6kdwWscMwNJsLEUQ2rdrAi+fGr6dlazn3sCCXrskLURKn5qCU\r\nfIFZbr2bGjSg93JGnvNorfsdJkwpFW2Z9gOwMwa9tAzSkR9CsSdOeYrmdtBdodAR\r\ndIu2MkhxAZk9FZfnFkjTaAXcBHafJce7H/IEjHDEoIkFp5KnAQLHsJb4n8JeXmi9\r\nVMgQ6yUWNuzOQMZpMIV7RMOUZHvxiX/ZWUFzXNYX0GYub6p4O2uh3LJE+xXyDf77\r\nRBO7PLY3m4TXCeKesxZlkoGke+lnq7B8tkADdPI=\r\n-----END CERTIFICATE-----"},{"id":"contacts","categories":["office","organization","social"],"userDocs":"https://docs.nextcloud.com/server/11/user_manual/pim/contacts.html","adminDocs":"https://docs.nextcloud.com/server/11/admin_manual/configuration_server/occ_command.html?highlight=occ%20commands#dav-label","developerDocs":"https://github.com/nextcloud/contacts#building-the-app","issueTracker":"https://github.com/nextcloud/contacts/issues","website":"https://github.com/nextcloud/contacts#readme","created":"2016-10-30T14:00:58.922766Z","lastModified":"2016-11-22T22:08:01.904319Z","releases":[{"version":"1.5.0","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/contacts/releases/download/v1.5.0/contacts.tar.gz","created":"2016-11-22T22:08:01.861942Z","licenses":["agpl"],"lastModified":"2016-11-22T22:08:02.306939Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"ZqqhqtbHcNB+rzGCQ7FDIjjvHjit+dhAE1UhFgiXApkx3tmPP4nJOBAGNjHe+2Ao\nVcTIX2SrWEfieRrA4Gp+0k7pUPWag1Z0T1OVOwO4cmS1AVFyGIOE1bRvDhMfsWTU\n4CI4oXaKBFAY6mtnf7VJ7EeIdNqhImkohyWDQ88NiPRLM1XNkJJk6AvZBcT0fvCv\no145X4dLpbixSXsN99QFNJ/oXvK+9tBGwTd5i/WnNFY90vcNRLia8aRo7SA0YJRx\nLnxnj2HMqwTTDQEKE+1elYKWsqQ2DeqwScP97UIKe5bZXnrwOi9kH9PDmR4abtzd\nlHL8E1Wgw25ePDeHG7APrx0tVOJy1bP+g8vcarpGynWZoizDkBvYZD+xtxizpBXC\nJsDOSzczApptY6dnOtv0Vat8oh/Z/F99gBUahEu4WZ16ZgR1nj40PDK1Snl18Cgk\nMe1EZcde8SLEpTbCWYIfIw/O9Fkp5cWD/dAqoiO6g+gNxSZ/gGp57qoGfFxn7d/x\nH3aH8GljatAFjrwItw1JzR0THt0ukkOK+bw/pfCslk10sjHMitmz/GXa4qMS91DZ\nBKLUd0dSfQUQzkfwcojImbzJRvca4/DYe3mfG7+RCH0tDL6t72dKL9joB++u5R1u\nVZPgkToexlXcKWpiDB8H2/SEShKr4udAOjR5de9CYWM=","translations":{}}],"screenshots":[{"url":"https://raw.githubusercontent.com/nextcloud/screenshots/master/apps/Contacts/contacts.png"}],"translations":{"en":{"name":"Contacts","summary":"The new and improved app for your Contacts.","description":"The new and improved app for your Contacts."}},"isFeatured":true,"authors":[{"name":"Alexander Weidinger","mail":"","homepage":""},{"name":"Jan-Christoph Borchardt","mail":"","homepage":""},{"name":"Hendrik Leppelsack","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\r\nMIIEAzCCAusCAhATMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\r\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\r\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\r\ndXRob3JpdHkwHhcNMTYxMDEyMjAzNzIyWhcNMjcwMTE4MjAzNzIyWjATMREwDwYD\r\nVQQDDAhjb250YWN0czCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANzx\r\n/zJF+5/s4lOJLWIlfKQgTy+UpvIpiUXCgrsHsDZTx+hjQAhIWukH88a+7NVAL7Ys\r\nkQNC0Tlm755FJi/T6EdR7edOwIRdo2ZwakOWLZXd209+6cCd2UloHL0bgnbWepTl\r\nR/4YgbLg/G+FVKCfkEiYc3PuDZ3EVrcwQFcg7h74X9ne6CHH0Z1WQLydxJuVEb2n\r\nX9I+nIRpPHcVostkSiUmzHR7C5TjTIo2PzzgnCU6GC0iBa6z6dDYfz24QEp/b8UA\r\nZaLhjkyKghVGMnoF/s9KPgH4NM8pvvtadQN8pxlOPju4wbmKPUrsXo4ujurDXbbc\r\nYkzNt8ojobGwdTXoyDogAsGZLQd2FQksWpRvY+I3zVPokBfPMdUPLllG5VcV0VA5\r\nDRK+h2ms+XmspdBvGonjF+XdbFm9hEmDoFmoi9aU6C6AdofjmG/e9+pw/20dXUWk\r\nmMorWwXQ5yLmIn5LnpRXrOuK7CS28VRhBYuVNMlsyKhzU0rophbsD9OFXxYLjr6s\r\n7UPNwZ5h+kjXZDBKD89QctBSViT8RhLe8nulRIm0iJn1sb9hca/CF63KmsFzENfK\r\nQeM6MO0H34PB84iNyz5AX1OIy+1wHD4Wrzt9O/i2LkWK6tBhL69aZiBqdLXWKffj\r\nARDCxxIfews51EZFyHzwsw65I97y46aBKxY382q7AgMBAAEwDQYJKoZIhvcNAQEL\r\nBQADggEBACLypX0spxAVAwQIS9dlC9bh1X/XdW2nAvSju2taUTBzbp074SnW6niI\r\nbnY4ihYs4yOuGvzXxnp/OlvWH7qhOIchJUq/XPcEFMa7P03XjVpcNnD3k0zQWlZb\r\ntGonX9EUOeLZKdqI4fkrCkMLScfjgJzoHGYQrm8vlIg0IVuRLCKd5+x4bS7KagbG\r\niuPit2pjkw3nWz0JRHneRXz/BNoAWBnJiV7JMF2xwBAHN4ghTM8NSJzrGTurmpMI\r\nGld7yCP47xNPaAZEC66odcClvNtJ2Clgp8739jD6uJJCqcKDejeef0VU1PG7AXId\r\n52bVrGMxJwOuL1393vKxGH0PHDzcB1M=\r\n-----END CERTIFICATE-----"},{"id":"mail","categories":["tools"],"userDocs":"","adminDocs":"https://github.com/nextcloud/mail#readme","developerDocs":"","issueTracker":"","website":"","created":"2016-10-19T19:41:41.710285Z","lastModified":"2016-10-19T19:57:33.689238Z","releases":[{"version":"0.6.0","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":">=5.4.0 <7.1.0","platformVersionSpec":">=10.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/mail/releases/download/v0.6.0/mail.tar.gz","created":"2016-10-19T19:57:33.676730Z","licenses":["agpl"],"lastModified":"2016-10-19T19:57:33.834580Z","isNightly":false,"rawPhpVersionSpec":">=5.4 <=7.0","rawPlatformVersionSpec":">=10 <=11","signature":"VbMsvDpt+gSPeFM8LrZXEK10rk8kkLlgCcblgqNdCSeGZeVpwDAYv3CccVSLa0+l\nlTSqQ0VIoH+OIU6vIQNBKHmSCzTplk7OrY0+L5FajXx8LnBaOh892GfGSlEt1neN\nKyM0i0uOjO/xpCP/NoUlgkz6hnmYY5XEdN6DTsJtJ/XZhDQ45IYuIkMkHE/eFehS\n0JnOagIz+PSipeBY2Ry+tV8YbRa7bC1JAvZzlod0dyI015AHZESeitRUY+MwMWkt\nN/me7g7/Kev0wggIQQZm9aYcw63GMk/1VHUPB7Y0ESW9tx2nR5+KwTDn/Jy4DGf1\nrg8h0t5I+aPhHOBLrpczH0qaZWY2lsVZWq8KWjJI9aR9P0v2f2aXixXzD/Cuz1cK\nhvhKWkOSla4D+/FxeyHGjQvdXMG8gXm0ZmTimKChCoVuCbncDd8pzkdyNoGXcvuk\nsP8OrkQFooL4E7S4BWfdSiN/a8jUITJQkuXp/OVrVGeCupLWJh7qegUw6DvoqyGy\nD4c6b+qYn68kx3CLaPPiz+tFAZQZQdj7+Kx/lohso8yTnVSiGYrMj4IvvCbpsQjg\nWF3WSqF/K/tTnPYTWb9NUPSihTbVNv6AXOfTsPEp/ba2YSS5DjvjVjkr5vhR9eg1\nikQ3Cw6lW3vaA4LVCC+hFkMRnI4N0bo5qQavP3PnZPc=","translations":{"en":{"changelog":"### Added\n- Alias support\n [#1523](https://github.com/owncloud/mail/pull/1523) @tahaalibra\n- New incoming messages are prefetched\n [#1631](https://github.com/owncloud/mail/pull/1631) @ChristophWurst\n- Custom app folder support\n [#1627](https://github.com/owncloud/mail/pull/1627) @juliushaertl\n- Improved search\n [#1609](https://github.com/owncloud/mail/pull/1609) @ChristophWurst\n- Scroll to refresh\n [#1595](https://github.com/owncloud/mail/pull/1593) @ChristophWurst\n- Shortcuts to star and mark messages as unread\n [#1590](https://github.com/owncloud/mail/pull/1590) @ChristophWurst\n- Shortcuts to select previous/next messsage\n [#1557](https://github.com/owncloud/mail/pull/1557) @ChristophWurst\n\n## Changed\n- Minimum server is Nextcloud 10/ownCloud 9.1\n [#84](https://github.com/nextcloud/mail/pull/84) @ChristophWurst\n- Use session storage instead of local storage for client-side cache\n [#1612](https://github.com/owncloud/mail/pull/1612) @ChristophWurst\n- When deleting the current message, the next one is selected immediatelly\n [#1585](https://github.com/owncloud/mail/pull/1585) @ChristophWurst\n\n## Fixed\n- Client error while composing a new message\n [#1609](https://github.com/owncloud/mail/pull/1609) @ChristophWurst\n- Delay app start until page has finished loading\n [#1634](https://github.com/owncloud/mail/pull/1634) @ChristophWurst\n- Auto-redirection of HTML mail links\n [#1603](https://github.com/owncloud/mail/pull/1603) @ChristophWurst\n- Update folder counters when reading/deleting messages\n [#1585](https://github.com/owncloud/mail/pull/1585)"}}}],"screenshots":[],"translations":{"en":{"name":"Mail","summary":"Easy to use email client which connects to your mail server via IMAP and SMTP.","description":"Easy to use email client which connects to your mail server via IMAP and SMTP."}},"isFeatured":false,"authors":[{"name":"Christoph Wurst, Thomas Müller, Jan-Christoph Borchardt, Steffen Lindner & many more …","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\nMIID/zCCAucCAhAVMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\ndXRob3JpdHkwHhcNMTYxMDE5MTkzMDM0WhcNMjcwMTI1MTkzMDM0WjAPMQ0wCwYD\nVQQDDARtYWlsMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp++RuliQ\nlBeeiPtP0ecBn00OaU1UCpft/NVI5pnSiT9nU4l2kc5IvKjA8UxDB3gWfYTOeBFh\ntUHQ2P6UKCmHZT9sApHhqLu2n0V+YhlFIViuaxndSID/M414cl56xOYQusV3Pcae\no2dOSeRRzLab3tEaVHlkBSFkGmAwPZItsmTklvV3h1sUysDicYgfXPCkf7K+JgWA\nBP7vsWC8B7MDRhcB3enYv5tTcpsyvtGX7bb1oTIWVypcmKsGYfTX12VNBxKzNBIG\n8pwdb8Xo0o14TytWsWN7mSHf1XbwfwYMjDWOlMqiRc+mcoKMBH41TfM/CXslSivI\nsyvxasEaFdlj8lmKPENdzw1OfYRs43usIf4szwyt4rb8ocXfDipnY3P2hccN6YcZ\nl8y8Vsr69ASluDj2A2Pl5vH6xp6tNybZRnN5G6sghhaYaLNDU/TdMyYzz4AY33Ra\nHSaMypfcXjd76Aj8jZvcwk1BH+ZsvFqNK7ZKCb7WVcMH8KRcU1sxZ4rp9vviM2fL\nL7EVtznm3bSI9jjHXbiwq7RvNRRy+F6YRpAdWGwTU8uUkDabPFi41FikYyzNWauK\nJhlDJXl514XjKyMVBjAZYVr5gZZkO1J7C4XzLFbC5UzYNSzW5Iwx/1j5OeYJRxh6\n5rhiUwR+COT1wdVsl6khMC8MfBR4unSd338CAwEAATANBgkqhkiG9w0BAQsFAAOC\nAQEATBvpqz75PUOFPy7Tsj9bJPaKOlvBSklHH7s43fDDmQbJwswXarZi3gNdKf8D\nyO/ACZvO8ANWAWL/WahkOyQtKOYzffaABGcEIP7636jzBdKtgwSGzW3fMwDghG10\nqBr2dE6ruOEdSpuZxgMgh2EulgknZUXaHAMI2HjjtAMOBScLQVjOgUqiOHmICrXy\nZETmzhx0BXDt5enJYs8R2KMYJNIme1easQRYmWKliXogNY09W7ifT9FHtVW1HX+K\nxRS4JXbapjolkxyGSpP+iYSgItVnYzl6o9KZResR4yDsBv7G/8fpV4GQU9IS3zLD\nPiZOosVHWJdpUKCw9V4P1prGTQ==\n-----END CERTIFICATE-----"},{"id":"audioplayer","categories":["multimedia"],"userDocs":"https://github.com/rello/audioplayer/wiki#user-documentation","adminDocs":"https://github.com/rello/audioplayer/wiki#admin-documentation","developerDocs":"","issueTracker":"https://github.com/rello/audioplayer/issues","website":"https://github.com/rello/audioplayer","created":"2016-09-16T05:44:24.857567Z","lastModified":"2016-11-17T22:34:34.637028Z","releases":[{"version":"1.3.1","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":">=5.4.0","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/Rello/audioplayer/releases/download/1.3.1/audioplayer-1.3.1.tar.gz","created":"2016-11-17T22:34:34.215350Z","licenses":["agpl"],"lastModified":"2016-11-17T22:34:34.867778Z","isNightly":false,"rawPhpVersionSpec":">=5.4","rawPlatformVersionSpec":">=9 <=11","signature":"p6Zz0IEFrxvw6y/3jHgGWWCxR6qpMzvU2HKfxcIVsK6sJnoRUhWLeAXwZ432fH2a S2llj+IGS9OvW+5VQElrXgPtEjDK1BT00DRJnp5RFCRlUv0LNoedJMzx6B6AHqPP JBufk3cG1O/CO0M0L1ITGSmSOzfKvWTRo3lxVGF792NyBaP/SyZCkH1N1TzBQzUi Ywl3+HiglPcXbHjtJm/arnKorbJWVKoaN93xFuaBapd2ozQSpi0fE0uGRsici+U7 HNa1M5WFE1rzUJoufE0E9246At07rFY1e+TdNEq8IlLgCXg5vGCKkEyuWpWno6aX LfRaIiT9x39UTAwNvuDKS0c+n4uWDYPsGfKhDx9N7CXpUrthfXVEWRzZEXG7as10 6ANvrRPJemSZH8FUSrdJhD7k12qa9R825y7mIG68Li8P71V92EOxFfo9tNXqXwBt VuDGxBqByFVPqSCj5I8hrzJzQl2Xt40g8+8ZcSF96RMg/pM+bwRMTv+mz0V+vQQ4 DWjqnWVPalaJ1PPD5/QFFErtXuNRbyxKZ6BMWxfJlLM9Kz66P75K+8fYaSwz+2KG NxY7I3svzS2K9LGH3fBLUy1t3Hl+c3zGFq/ll1MJrf9NswV4yxt2WmISfM/KDww8 yELkGs2cRzbw2tCvnmYlJJhIqRLkyFAbDzWRH/XdVx4=","translations":{"en":{"changelog":"2016-11-17\n- fix: one-click-play for wav not working\n- fix: wrong sql statement for PostgreSQL [#90](https://github.com/rello/audioplayer/issues/90)"}}},{"version":"1.3.0","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":">=5.4.0","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/Rello/audioplayer/releases/download/1.3.0/audioplayer-1.3.0.tar.gz","created":"2016-11-15T18:11:19.539636Z","licenses":["agpl"],"lastModified":"2016-11-15T18:11:19.592881Z","isNightly":false,"rawPhpVersionSpec":">=5.4","rawPlatformVersionSpec":">=9 <=11","signature":"lbp7wd3JhMHW5mC8kVnQFvcwzf3aTIhYhq3ak/C/vfDXJDIPFuQ1odVRWtaHXEKQ XmKYIoTobV1TAU5q9G0O0Kds73T/XtHG4ATLxMZE8RsUWNSj5v3H4YDub6A0uoX6 rzyLEYV6SGEtdPFMwLcUjDExKpzAzKpgxcd9uyz2NhcHJEO8FJmirn34bm69//TO vjjiMW4zpL+dho+7LQbOX+L1SmwmdBqwypE9zzeuIuhUWDEQtImHAvjIO6Temajm lX0H5JaowJa8kvP6Jkh3KAvsHQ4sJklvWTPGcv0gboN+o6CmjWNOb+3LeSH0nhe6 BmiPloUDJcPQwq2gQejH2pY+qJEdRcULSKS09/dRbE3gOSlG36FThN0INpv6uNP4 qVIiYs3/SEHMmlS5CHvJDt2S2XN9LT9IX7QPeuS/0CMcuopaG/+cdC4KscVCq4D4 bllgew9asiBqix8iV8C4oerYOiC5vWcgBrZhGShoJT1Qq+NKz+H10dFgjFCAZuPj nVagJkbXmf2NdcvpSC7qsufhyEZyCSp+I7QEYsbo1PW3aUU35Syt47lgeVFX0hVQ jC1wMIhEW5Rm2nCkRSZkRupKDQ+N6uWuB0lykeMV2ShcDvvUZrhN3c49sooWgigB yIqKryzM4fLErjjNHdYgwCq6bbgPDLK3ic9b3B4rF3E=","translations":{"en":{"changelog":"2016-11-15\n- fix: handling of temporary scanner files [#68](https://github.com/rello/audioplayer/issues/68)\n- fix: simpler analysis of incorrect files in scanner [#57](https://github.com/rello/audioplayer/issues/57)\n- fix: album sorted correctly by artist and album [#80](https://github.com/rello/audioplayer/issues/80)\n- fix: neutral cover for unknown album [#16](https://github.com/rello/audioplayer/issues/16)\n- fix: error message from ID3 editor shown in front-end [#77](https://github.com/rello/audioplayer/issues/77)\n- enhancement: occ support for library scan and reset [#72](https://github.com/rello/audioplayer/issues/72)\n- enhancement: select a dedicated folder for scanning in personal settings [#79](https://github.com/rello/audioplayer/issues/79)\n- enhancement: exclude folders from scanning via .noaudio file [#79](https://github.com/rello/audioplayer/issues/79)\n- enhancement: significantly reduce database reads during scanning [#79](https://github.com/rello/audioplayer/issues/79)\n- enhancement: cleanup of classes; move from \\OC\\Files\\View to \\OCP\\Files\\IRootFolder [#72](https://github.com/rello/audioplayer/issues/72)"}}},{"version":"1.2.2","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":">=5.4.0","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/Rello/audioplayer/releases/download/1.2.2/audioplayer-1.2.2.tar.gz","created":"2016-10-06T21:21:05.414691Z","licenses":["agpl"],"lastModified":"2016-10-06T21:21:05.483224Z","isNightly":false,"rawPhpVersionSpec":">=5.4","rawPlatformVersionSpec":">=9 <=11","signature":"toeS45z50Lm0djgrQokOTN7gA8a113IZtiKKiLsGUKWrCV/6AKJBmEFcSun6rhLH\nbz/RtIdFKwQql6O3E0m1Zch2y1A8aLWHzFTO+5orLCVi7y15SshrJYbb9aI5Pj3i\nSR7+kMHGS8uNx2uIn3B4mO6UYF8AzCfp+ule18DOjnpu86KWvEOGtFXsQkLtgepp\nbJhOGWW/uOVIos/T1xPP4GCmtVmgn7U3b9q0pMYRH7ONXEiNsfQxDrR66EZH3Jfo\nlVyM9UvQmMKoDSdBUlvLlhCEGJGqFOD7hFntLYloI4oXv9uGqcagaJVh3TkEysY2\nMbBZpVhch5zRJ/HGlZOvmEzZ8Inxkk3iap+JmJ5/gZTefwfKUyYHALsILlh820U2\nNA/1B5A015XH5a5uflGE/tnlPtrOeecIN4mg+1njo2RG89HJWJNHM2ZDO4SkXjSR\njgygmAS5aR5+KKifiA/pwjhLozDWPU4lNzsj3Foz3bx3Okopy7eq83LORqieT4Jp\nFvP64q/45LOSRBWIWLitYzRzZp7HYywMsnz12WpxtqxIjO7+7y/ByeWWOBNU1IJC\nK2D+035ZGWZr0CxDJte33WOISwjVoSwrcov++O3BQW8lM5IkcDNcJFyzNPKAXcQU\nPUXmQpYurHoIw6odAYcbrG6iOiSesuNOf2kQWbjV3/c=","translations":{"en":{"changelog":"2016-09-18\n- fix: icon issues with alternative apps folder [#65](https://github.com/rello/audioplayer/issues/65)"}}}],"screenshots":[{"url":"https://github.com/rello/screenshots/raw/master/audioplayer_main.png"},{"url":"https://github.com/rello/screenshots/raw/master/audioplayer_lists.png"},{"url":"https://github.com/rello/screenshots/raw/master/audioplayer_share.png"}],"translations":{"en":{"name":"Audio Player","summary":"Audio Player for ownCloud and Nextcloud","description":"Audio Player for MP3, MP4, Ogg, and Wave with a lot of flexibility for all your needs."}},"isFeatured":false,"authors":[{"name":"Marcel Scherello","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\r\nMIIEBjCCAu4CAhAIMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\r\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\r\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\r\ndXRob3JpdHkwHhcNMTYwOTE1MjExMjA4WhcNMjYxMjIyMjExMjA4WjAWMRQwEgYD\r\nVQQDDAthdWRpb3BsYXllcjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB\r\nALyC+iLscLs62NeNmUXEBmg+xMuUtDmZKr+xzJWtl6SSNRz+8K1JygvUIXFJ3RIL\r\nCYA3xyq8/wyZH1gNrLKyz5eTeYawG+eT3ges/FT6MWGUbZoRrBrikVcLC94QzxTH\r\nxOl8Dn+SCV/2bhcvPTQdhK+dqtvGilOtjHa40iMrk9gSdlKVys5CK/xdlEp8uiMa\r\nkz1WENn8MVCCJV58bAUbaCupDWXR9CCoSsw8XinNsCenZ2B2XlnmbM44280w0ojs\r\n72rfQRgj3yDG+ZUUyUOuxIuodu8liXYciLf0ph6t/f/qoSmctbBdsR5Fl1Upj1Ac\r\nqeHb5Yf/B3Vi6Mn3XfDx0H2EHk1v9Dhzxay+v9BHUzyIX2iH/q+7TE0/Jzo5AwBW\r\nvFKWXvG7wXaALcHYZf5v/M93IE0iCHsv2EsZKQPBnzXVGmp4DwFSP4po1B7hcog1\r\ngAMaellAzzvUAizgCovN6Qct3qDEANYniPlvtnlcaQGonajW4N019kFQRHLIzPFR\r\njab5iUMMwSnT8FhZO2ZOWuWhJven+gXjxC8mfMVgBfZnAVgydNfx9rN+KzTc88ke\r\nobUdZ0OOeBzA7pIxGEFg9V6KTEEWZ+qH048vxXz4HI9B1I+2wQLBrZl8CvweEZ5U\r\n5ID8XrrE/UaNZ1CvLKtCgB24gj/m1Elkh7wA3gEcEo2JAgMBAAEwDQYJKoZIhvcN\r\nAQELBQADggEBACtgUp+FCmjWIkQUuWSdzKWdO+IH4v9wBIrF9mo0OLIakFyDYyM5\r\nLlkYZXbplGXd4cfn3ruIqJNzlIb4xa5CU0bM4TMbD4oOSlLMKM/EamKPHI3bzr++\r\nzi7mQDFxmAE6FWSMBgKKUb4tqLc5oBap8e12tPEZl/UR6d9iUB2ltvrm3T3vrjjl\r\n2Worm0eYBNqnagXmX5+wS11AQqeJemGqRy5e1yXRlTgB0IJhH0dCsFNwifEigutp\r\nFNvGFVBn4r5qCiChEoq+rCXHRjPi/eCfbW21XeLFDiLxapcZyc85JIcA7znUYoFe\r\nP7Y/ekMscwWhLbF91OaQlcWpRtEMyde/DaI=\r\n-----END CERTIFICATE-----"},{"id":"calendar","categories":["organization"],"userDocs":"https://docs.nextcloud.com/server/10/user_manual/pim/calendar.html","adminDocs":"","developerDocs":"","issueTracker":"https://github.com/nextcloud/calendar/issues","website":"https://github.com/nextcloud/calendar/","created":"2016-10-01T12:40:39.060903Z","lastModified":"2016-11-22T20:31:13.029921Z","releases":[{"version":"1.4.1","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/calendar/releases/download/v1.4.1/calendar.tar.gz","created":"2016-11-22T20:31:13.020268Z","licenses":["agpl"],"lastModified":"2016-11-22T20:31:13.087340Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"nThwe9CJBCan9nuDLdhfBiQyPhmum6Aa0UcYsIDdhGMw+C2acf81KhEmBJuTTWxo\nWGby6WcrcJJmeuCW+ePU91ju7Pd76RirprhVXIEceIDzSCxin+K0oZCZ1IGVIJjP\nIkVehTsLuCeTBbjvz1b3k5QFyhUhvd32Xt7k5d7VARyI4OqnqYYNBtH9vvgeRrFw\nAxsQr4o4axof6i3iykLg6WfWarYArY4dIuu5DkPuGPWf2bbgjwWEra4sQejhOs7G\nsk1xcsfYv2NpArIbpw/wnATdjiax+Gjz1URMD3NgL5ky0ecuZmNvN25QErg3nlVr\nhh1FBfA5pvCJbkJ6nr5bU4bKaffwDX1nr5h77FS5zzn0Pyd7ZIExmVmNtaeJfnfV\n5vnclapzXMNU+R6t/ATJQd1srvSJhyljQapzsqnrjNMEUojOEvqqygJp0KwNVPqs\n3g9XGSoOnO+WULWBeISW7UVOg8BOF8pwvHIU2++bSzOdpypW0Eq6p2DPWO6qL/H1\neFLKrUg3EvnTjvknbBxMB55h9jNJr0SAlkrmyEVm6+CE3BwRWpKB+cJMBuGiwPwv\nr/ASRiJrkDThbNWAUtX70rUmCqDV6/MujLXViqOc/Q2OHvcXd1oGDccJSQT92/1z\n7nonnedyYQIDqUt7u68WL8JRxp7pFsEqKLVuWSgxW3c=","translations":{}},{"version":"1.4.0","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/calendar/releases/download/v1.4.0/calendar.tar.gz","created":"2016-10-06T19:58:12.724588Z","licenses":["agpl"],"lastModified":"2016-10-06T19:58:12.790604Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"b//hJbICFMLR0Va1BGMzpLpaPREOo9QhjgfrHvDOfXVpddhvCM8ocz74X1s5hKyy\nGg67EE0pOp0dBf6RyJjduI+Dz1wQX55My7J9G1vXGCN30C/8zAcKSJoA218IWcub\nICavLkz2PkiitIOSZyBCAfEiSAeHPop/JGkq3KxQDC7QwFC78BnE9/adD9tO55c/\nDGLhvP/uTJIeH8RUifikTqVMmPH+aP3uPbZzl+AxhUezRiNCpEtZPA5QGqtQdJU4\nFc6x3d9y4IWbJV4TEIAP8jdfqtLVUQ6szFVnN8Oi1wtN9e8LIylBSYbmIZRj0+qh\nZcgntzEq6U843ZwXcAnL5jNYV0m+KNI+EkXFeWHkjvbwfCdvGPBvgFVbhc0YPzXU\nqHOe4Lvcx9X20ALG/MacV9zX69GzNnWgbBp9RnIHuaSRPFEKrNXUeXl2THuKsTyQ\nF9QtTwS5U5DcMyTO2RAN45NrRxIh8IL4stoIg5rmF7/ZaOm/Jza2gnUquOTarDE/\ntiWnNW5kWUAWyYYHvQgQix/of9qXvc2hhZaw0y623WDNrEwA+rngnjDMLA/vNv3B\nhgwQ6NbCOuHWsRK3S8DcJFpB9Kj/i7CDvDLEuJYnjSTvQ/q1XqawbJPDoRlydX43\n3/L0LvHvKVakYybv2OE5gy6bQ2Dw8e7D27DtZ6XTaBY=","translations":{}}],"screenshots":[{"url":"https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/1.png"},{"url":"https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/2.png"},{"url":"https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/3.png"},{"url":"https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/4.png"}],"translations":{"en":{"name":"Calendar","summary":"Calendar GUI for Nextcloud's CalDAV server","description":"The Nextcloud calendar app is a user interface for Nextcloud's CalDAV server.\n\nIt integrates with other apps, allows you to manage calendars and events, display external calendars and invite attendees to your events"}},"isFeatured":true,"authors":[{"name":"Georg Ehrke","mail":"","homepage":"https://georg.coffee"},{"name":"Raghu Nayyar","mail":"","homepage":"http://raghunayyar.com"},{"name":"Thomas Citharel","mail":"","homepage":"https://tcit.fr"}],"ratingRecent":0.944444444444444,"ratingOverall":0.944444444444444,"ratingNumRecent":9,"ratingNumOverall":9,"certificate":"-----BEGIN CERTIFICATE-----\r\nMIIEAzCCAusCAhARMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\r\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\r\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\r\ndXRob3JpdHkwHhcNMTYxMDAzMTMyNjQwWhcNMjcwMTA5MTMyNjQwWjATMREwDwYD\r\nVQQDEwhjYWxlbmRhcjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMm6\r\nFTeqgzCXprkU83VM4/DrZWn3kqtfaR/edkC4gYT3ug7RHa/Uv1C/S++vr7pvgpnk\r\nYzQoavl/0Qlh5sKEYX+0ud/LQDoiidwBRDckFUQ1bRfVLxAD9UAVvDRHxDqJMOx2\r\ngZArbeQ3ztdSHZp4ThzBFWq2FILsJD86weG7LwHjzhW6SWgLb/YTLbuuW6tRCDVV\r\nbtB0I/a0vCwj2u91Chw3u6pWWjPakc9DQrIDH4HCIBKQ4zVrYDxAmJDRFGDvVVWx\r\nuIAeux8sd8drqSMqAhX+XMcZPRD71NQTWbCupSwWO8kgjmZnBpIiBNpzvMQzJf3A\r\nQloZtjZ2RDXAQG88eTeT8pp8yEOCEoDLpGdraKxJrh/z2Dsk30JP3lOiNYJ9vBaB\r\nC8NJbJ3oAlG7THwUaFF9fsdAKoTwzs5Xms04TI7W/v4Z/GClOzMymnR1T4sR72Oy\r\n3WaMNHv/1QGffvQn2/TtZt23Ou3P083xWx2vn5FgTcac8+x85vRgWsVCA4hq9v6m\r\nAlktB0+UWDEXpDTKD9BdFNWM8Ig9jQf7EJrvTLNnS7FIJZMB4GK8lpvPxyvACWnh\r\nR2hQOe987Zvl3B1JZNO5RvtSeYld9Y9UfMgW1aPRweDNjSuZYAKlugx1ZoyI5HyA\r\nQjfzAwicIMwZsCJDV/P5ZO8FE+23rdWaoJczpBqDAgMBAAEwDQYJKoZIhvcNAQEL\r\nBQADggEBAHQXwvj8q5khWR/ilg3JGYpmMNBYHE9OeDaOcNArkKaGMd478SDPOXeu\r\nyW7hCvNEpiTk5g0h3g3yleZFws0xH8fPsQgZANgvQXb3RCcD61NL77d0cMTr7Xzr\r\nN3Lq/ML1YLc/WwL4uV1XvpMQMwALFL1p63BU2c0ysO31zbLOjMKAJi0hHFDYz5ZQ\r\nD3xxtc17ll3B5IqrMnMHRqmOQ39Sbe56Y7T4agaIz/sUWpseo85D5kt7UAIOR+Mr\r\nQ0Bl/QinETk72afGR46Qvc7tC1t9JjQQD3AUbEGuJdGvXjJJ9GREYu01XoODmPdT\r\njXXOI8XIOK6kxXhPHUc3iWu9b4KqGm0=\r\n-----END CERTIFICATE-----"},{"id":"gpxpod","categories":["multimedia","tools"],"userDocs":"https://gitlab.com/eneiluj/gpxpod-oc/wikis/userdoc","adminDocs":"https://gitlab.com/eneiluj/gpxpod-oc/wikis/admindoc","developerDocs":"https://gitlab.com/eneiluj/gpxpod-oc/wikis/devdoc","issueTracker":"https://gitlab.com/eneiluj/gpxpod-oc/issues","website":"https://gitlab.com/eneiluj/gpxpod-oc","created":"2016-10-31T10:57:44.387319Z","lastModified":"2016-11-23T17:27:37.793159Z","releases":[{"version":"1.0.8","phpExtensions":[],"databases":[{"id":"pgsql","versionSpec":">=9.4.0","rawVersionSpec":">=9.4"},{"id":"sqlite","versionSpec":"*","rawVersionSpec":"*"},{"id":"mysql","versionSpec":">=5.5.0","rawVersionSpec":">=5.5"}],"shellCommands":[],"phpVersionSpec":">=5.6.0","platformVersionSpec":">=9.0.0","minIntSize":32,"download":"https://gitlab.com/eneiluj/gpxpod-oc/uploads/963bbf246412bcbe8979bccadb3b8d03/gpxpod-1.0.8.tar.gz","created":"2016-11-23T17:27:37.783365Z","licenses":["agpl"],"lastModified":"2016-11-23T17:27:37.862469Z","isNightly":false,"rawPhpVersionSpec":">=5.6","rawPlatformVersionSpec":">=9.0","signature":"hqhMh1l/mnwbYf4uPzEjjLFtZWHidzgR57X471OuXv2K/s87T5WhIkTSKk+2r8sp\nS7CtrF5+Pc5AgCCHvwzawN3e2+4eO4cK0+HD9CCzygzzHZEbSjufNHMMQucVoSD8\nPqR6MV9azzUpwHa/5d8fp3cFLVAle+aG0o4v5eHky9c7eaKxVJcgfjw3pjDE73N6\ngJVdtw1jf1kOFYk5pZQxDfBKFDrO5BRo5ZfZGuOuP2u/SmTwj42oTZiT7oTVWhqd\nLvJw+2TPv7B8s0Gin+J5e9K1Rs6CEWQ6WBxM+NhS5KgWB5Ig3pwm0QvMgza2cvoh\nlwVobOotfKLUBJzg0+wR7B2YH9Ao+m94h93vg7H0OKPReoTKhlDj2UExoTyeurV8\nhJdQv8sKVAxjC7/xrVaGSjM4YxFdBpzq8Zl8z4zq1o2voH5+u4ko3c62C1loDpsC\n8KrL1t6A7QpMk/XAMrPqwEPmFqlLEdv6FhzpOGyt4IEVnv6vdMTShcYw3tPvU/mD\njPtiVwpo8gWbGVIfpmwBg4wPaTrWK8V3+/1iTahIQHZfu4Lebb5mzht80HLQIcd8\n+oB4cGDEX4Rix1WxnCmE5ZzURY8xQXcvqYN+mTrUDh/3OtxQPSm5yC945SGoFNpr\nBYxfEyQcwulZrOMBdY0Ssj1AB5NOeC9OHwjJrnVe7dQ=","translations":{"en":{"changelog":"### Added\n- save/restore options for logged user\n- option to choose picture style (popup/small/big marker)\n [#25](https://gitlab.com/eneiluj/gpxpod-oc/issues/25) @eneiluj\n- add average speed and average moving speed in comparison table\n\n### Changed\n\n### Fixed\n- bug when python PIL is not available\n- deletion of bad parameter given to getGeoPicsFromFolder() in controller\n [#20](https://gitlab.com/eneiluj/gpxpod-oc/issues/20) @eneiluj\n- bug in file cleaning, bad use of array\\_unique\n [#22](https://gitlab.com/eneiluj/gpxpod-oc/issues/22) @eneiluj\n- python script do not need to be exectuable now\n [#23](https://gitlab.com/eneiluj/gpxpod-oc/issues/23) @eneiluj\n- jquery.colorbox was brought by \"First run wizard\" app, now included\n [#21](https://gitlab.com/eneiluj/gpxpod-oc/issues/21) @eneiluj\n- avoid JS error when failed to get options values by ajax"}}},{"version":"1.0.8","phpExtensions":[],"databases":[{"id":"pgsql","versionSpec":">=9.4.0","rawVersionSpec":">=9.4"},{"id":"sqlite","versionSpec":"*","rawVersionSpec":"*"},{"id":"mysql","versionSpec":">=5.5.0","rawVersionSpec":">=5.5"}],"shellCommands":[],"phpVersionSpec":">=5.6.0","platformVersionSpec":">=9.0.0","minIntSize":32,"download":"https://pluton.cassio.pe/~julien/gpxpod-nightly.tar.gz","created":"2016-11-16T14:06:33.937534Z","licenses":["agpl"],"lastModified":"2016-11-16T14:06:33.971502Z","isNightly":true,"rawPhpVersionSpec":">=5.6","rawPlatformVersionSpec":">=9.0","signature":"JtUhKRDFGYDx9xtHjdfEUFOb0O4idexUYw6ixlBhKPP8Dn7NfyBfV6KH6MJTIVLU\nQ5Jw6tv/Nr1YDOvVikcWPG0p23mQdn1+7w8DzzIGKmknxCat9/vKr83oJZdWYxS7\nTJ4I7qTvWNlbMfK8OEdl13VJXgc6ftX+1isluLYqLjEm3aBFCS+/awYNMmXO55a1\nyG0NgJRu3pw1CBCMhDaRLsunhpRNDVLsamZj1SPmeT8qy0I/arFaG6hQnAo6JosE\ndi1XkvK6TEt9g16L6eizd+JpGE7xiWFP9ZEmMmmQSOLQYwU5Sk1YWcrW3EX4vtz5\nWnEIC0SENyyAyzBO6YJfu/EP2lLnlbNJiuc4zzKLqRw/zyz3j+imJLcXHIA78ZkQ\nuyUOBkkk3xeyBGeUcYfDuBqYQOQs+F/7+cNMsIBKJhx9ef3OPURBc7X16upk3mxV\n6GsOktbHkgUwWk3WiXRriBIqbAZocvDp0+PN++PAEZVWFEZEJzztd4Fxaeo+QSN5\n5Pz/9yXYRsoSPZv82Tlh7dx5tIPUvYb+UsANh5eGWUGufTSwgYBN0H2KT/iO35D7\nkDzNyh1qNakfBhAgPjrC2p4mBKBJJjlM0D9erDwr5D4GSTW2fp92vlRHeD0X8sqo\n3kBbwGuWnmhdJhbd7zYy0jVM6tVX/zgbhycimNALG0I=","translations":{"en":{"changelog":"### Added\n- save/restore options for logged user\n- option to choose picture style (popup/small/big marker)\n [#25](https://gitlab.com/eneiluj/gpxpod-oc/issues/25) @eneiluj\n\n### Changed\n\n### Fixed\n- bug when python PIL is not available\n- deletion of bad parameter given to getGeoPicsFromFolder() in controller\n [#20](https://gitlab.com/eneiluj/gpxpod-oc/issues/20) @eneiluj\n- bug in file cleaning, bad use of array\\_unique\n [#22](https://gitlab.com/eneiluj/gpxpod-oc/issues/22) @eneiluj\n- python script do not need to be exectuable now\n [#23](https://gitlab.com/eneiluj/gpxpod-oc/issues/23) @eneiluj\n- jquery.colorbox was brought by \"First run wizard\" app, now included\n [#21](https://gitlab.com/eneiluj/gpxpod-oc/issues/21) @eneiluj"}}},{"version":"1.0.7","phpExtensions":[],"databases":[{"id":"pgsql","versionSpec":">=9.4.0","rawVersionSpec":">=9.4"},{"id":"sqlite","versionSpec":"*","rawVersionSpec":"*"},{"id":"mysql","versionSpec":">=5.5.0","rawVersionSpec":">=5.5"}],"shellCommands":[],"phpVersionSpec":">=5.6.0","platformVersionSpec":">=9.0.0","minIntSize":32,"download":"https://pluton.cassio.pe/~julien/gpxpod-1.0.7.tar.gz","created":"2016-11-14T00:57:37.521001Z","licenses":["agpl"],"lastModified":"2016-11-14T20:35:45.363487Z","isNightly":false,"rawPhpVersionSpec":">=5.6","rawPlatformVersionSpec":">=9.0","signature":"SigBof6QJZ9IMZyFgc+B3LO2+EXaAPvnxUHjJQjIl3jLzomocpDGR6WjO6gtvB81\nzXUHjJ8+huc+P9TvgjUGRTmn9a/29HZ4IKTXnYBKIUY7wSLcJNMbJSp2Zd3OFHAG\nJwRaEdh/cIRk2X6NE1VT6dFCxB+LhTM4BXOEwuNYQvU1lZDVQgTz/r68zFLWBt6R\nqhBCNJHrVp87ecS4+XaGq/CfT4k1ihiOv+f4eX9iaPzUhxBJ71iYKF7wHpDoVmIk\nNrzWFUJH3BLBuW9oiC0PApli6Xu5RXrWUsOV7OAmxXgylRCPuTFwe09hw16JMbiS\nii8WFiUtp4qW53+7eoS7Fllm7CRi/Dg6Jvjtp3msrf1m+OiYM7dLyoKw22/S4P/a\nBIErZpSCHaCfrZ+DBXrAYcas27GWE7HizzG3yXk3aDJMa0Otcsq56bSPo01JDfNx\nm1y9iuwmlon8zKKoxsJCwxaFDnQpqazaLcUO0ATHUk8LdomTA7MCXVvNFPaO86Ea\n16iyw7Cfs0k3GrvN71+SdpvWss359CEEwBMpDwJZqwSFbLRyHtogUgbRWLIJqR4n\n5uVvJqirxWkr/EtXw6UkDWAI3ZoMhMRtjn4H4ekANP5mC8R0yp+UuFs2RkEC5uA0\nKzzh73WmxmpeUl6jcMZ49gXn3PTCC2fJNrdmSYch5Dc=","translations":{"en":{"changelog":"### Added\n- option to choose waypoint style\n- show elevation, lat, lng in waypoint popup\n- ability to display geotagged jpg pictures on the map\n- pictures slideshow with colorbox\n- pictures work in public dir link\n- use NC/OC thumbnails to display pictures on the map\n- options block hidden by default\n\n### Fixed\n- fix bug in geojson generation for waypoint-only files"}}},{"version":"1.0.6","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":">=5.6.0","platformVersionSpec":">=9.0.0","minIntSize":32,"download":"https://pluton.cassio.pe/~julien/gpxpod-1.0.6.tar.gz","created":"2016-11-07T12:11:00.619161Z","licenses":["agpl"],"lastModified":"2016-11-07T12:11:00.699921Z","isNightly":false,"rawPhpVersionSpec":">=5.6","rawPlatformVersionSpec":">=9.0","signature":"WBts2fm2rW/7LMHYjcx9a0k0WTXV6PnGRxTl+158cjfV7ruMpNvhK58iTjrox69k\nFWAoIi1wNAlLBu9Xet1j7HKi4TC9q61IEN+lPlnwBCu0uHawiqS2gqB4i8A019Ei\noLsgAPWh8ndy6+gyUtPhVLVduLH76aT6KTwAiHPknV0zPtxsUy1P6nbbNOS5A5rG\nSQBqljy0TbcjOctTudEPp1IqjJIwcd12eZ9MLG4CEIO13n53pMAsuXJf4jnKSCm0\ngimvsFOwFRjBab3ZPwtOqeVw6aIh/lYF3U3/k8YBpaDN74m30nDtkp8teXBgshSY\nVYvX3yOAYe0PIR419IX0eoHb61K0VfZYvPT4FsOqjDr0zlVB8Rjq+6SiK4vMD2+6\neGE0aHbjR9HV5jymUnFYdm/hlhcZGaKrAiQKfBY6Vh0SWKfIv7bdGfQYauePAdZt\njlsV8lIwOy7FGAeP81CcjzWWfDeBgYr+MSzfoDNoTi41MvUaT14iWPIU/s5P1/Qv\nALGxgsbmB19wEgNbdh1UtTUY3xARLpWPYdUqU7yDcsddX9vCoCG2G5wCcbYJRj8o\nC+H7wdgPJoiMY/p4Go/lyWkvmzhfXrOeXytZIFXjb3ERVd1vD9WSt1DSy/7gsFYt\nxzzOPgqMvL3BbeluNuzNv366oT872s3OuFKa1ZOYY7A=","translations":{}},{"version":"1.0.5","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":">=5.6.0","platformVersionSpec":">=9.0.0","minIntSize":32,"download":"https://pluton.cassio.pe/~julien/gpxpod-1.0.5.tar.gz","created":"2016-10-31T11:08:41.017766Z","licenses":["agpl"],"lastModified":"2016-10-31T11:08:41.068782Z","isNightly":false,"rawPhpVersionSpec":">=5.6","rawPlatformVersionSpec":">=9.0","signature":"UXeZVh5f0/WZE+r/dHWc1pu9q4qr/zACX6XraMhhIuKIp7vNCwUESeqJtVc99QZw\nw9kJp0isvib6l0zbQBRS1vI7xwKKBQyeaEhIciEs1JjsaCiato1Gyi26N+fY2N0Z\nFWlTwCsF3DdlwERXTYfeCpsOWCoxLxHKhnJIjUc0PVme/Ste4zxYj+5Su1RpadSw\n4vGnkW8zy/0tzua50NQCrOg+B4jXzH9kMWAP47w3sdP5CYalHSHl8EX0D1RjgGU5\n7vZYX3wF853FvQDbL4JXXCJupj3wZe8py8McWpQIcgz1p3KmE7A7d/rdNWExT+T+\nDxtStJ56qTRMz4aFwoSFxJrrEfgHIsE9Gv+Vo7nshCUYA8gkfHeckiaUtH1EiFTh\nVNeO6mTIqGpRosFvfUrZMKcuF5j74vGQjNM1o+M5N31gtLoPSkU605f/U4v+j2oC\n3/N1rYF2SEDFO0EgAGXaXVhB0ltSDkHJw6vZJ1L8Qz6tooUMDxaMri8vycA6LHvE\nqN+z+S6TXMfLvN/6ATYPGhicrWmkMT/k7v1az/hcnfH+zRyLZyFx94s88JWF7Jf+\nI+tgDbfqTMAIcytJUC+KfdQW1ueXh5F0owrOYM6jgBRvhqj1T8s+Twgw8orGmRPe\n9h8G9Z3wZAooQvmC0KdVhLuOeIkqt/S5krELNFFBRnk=","translations":{}}],"screenshots":[{"url":"https://gitlab.com/eneiluj/gpxpod-oc/uploads/db5af6ba7ae1cd4d22ea81d418f5c762/screen1.jpg"},{"url":"https://gitlab.com/eneiluj/gpxpod-oc/uploads/123588561a8067185572a8d1887ef906/screen2.jpg"},{"url":"https://gitlab.com/eneiluj/gpxpod-oc/uploads/427688b80bf8428dd45bd15d69b19075/screen3.jpg"}],"translations":{"en":{"name":"GpxPod","summary":"Display, analyse, compare and share gpx tracks","description":"\n# GpxPod owncloud/nextcloud application\n\nIf you want to help to translate this app in your language, take the english=>french files in \"l10n\" directory as examples.\n\nThis app's purpose is to display gpx, kml and tcx files collections,\nview elevation profiles and tracks stats, filter tracks,\n color tracks by speed, slope, elevation and compare divergent parts of similar tracks.\n\nIt's compatible with SQLite, MySQL and PostgreSQL databases.\n\nIt works with gpx/kml/tcx files anywhere in your files, files shared with you, files in folders shared with you.\nkml and tcx files will be displayed only if GpsBabel is found on the server system.\nElevations can be corrected for entire folders or specific track if SRTM.py (gpxelevations) is found.\nPersonal map tile servers can be added.\nIt works with encrypted data folder (server side encryption).\nA public link pointing to a specific track/folder can be shared if the corresponding gpx file/folder is already shared by public link.\n!!! GpxPod now uses the owncloud database to store meta-information. If you want to get rid of the .geojson, .geojson.colored and .markers produced by previous gpxpod versions, there are two buttons at the bottom of the \"Settings\" tab in user interface. !!!\nGeolocated pictures can be displayed if python PIL is installed on the server.\n\nGpxPod proudly uses Leaflet with lots of plugins to display the map.\n\nThis app is tested under Owncloud/Nextcloud 9.0/10 with Firefox and Chromium.\nThis app is under development.\n\nLink to Owncloud application website : https://apps.owncloud.com/content/show.php/GpxPod?content=174248\n\n## Install\n\nNo special installation instruction except :\n!! Server needs python2.x or 3.x \"gpxpy\" and \"geojson\" module to work !!\nThey may be installed with pip.\n\nFor example, on Debian-like systems :\n\n```\nsudo apt-get install python-pip\nsudo pip install gpxpy geojson\n```\nor on Redhat-like systems :\n```\nsudo yum install python-pip\nsudo pip install gpxpy geojson\n```\n\nThen put gpxpod directory in the Owncloud/Nextcloud apps to install.\nThere are several ways to do that.\n\n### Clone the git repository\n\n```\ncd /path/to/owncloud/apps\ngit clone https://gitlab.com/eneiluj/gpxpod-oc.git gpxpod\n```\n\n### Download from apps.owncloud.org\n\nExtract gpxpod archive you just downloaded from apps.owncloud.org :\n```\ncd /path/to/owncloud/apps\ntar xvf 174733-gpxpod-1.0.0.tar.gz\n```\n\n### Post install precautions\n\nJust in case, make python scripts executables :\n```\ncd /path/to/owncloud/apps\nchmod +x gpxpod/*.py\n```\n\n## Known issues\n\n* bad management of file names including simple or double quotes\n* _WARNING_, kml conversion will NOT work with recent kml files using the proprietary \"gx:track\" extension tag.\n\nAny feedback will be appreciated.\n\n "}},"isFeatured":false,"authors":[{"name":"Julien Veyssier","mail":"","homepage":""},{"name":"Fritz Kleinschroth","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\nMIIEATCCAukCAhAaMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\ndXRob3JpdHkwHhcNMTYxMDMxMTA1MTI2WhcNMjcwMjA2MTA1MTI2WjARMQ8wDQYD\nVQQDDAZncHhwb2QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCq9p5l\nzNzR98l/xPgrplWrGQBhF6aQSLpnIyCdLAYKk+CmXn47W1pHh5CRYyCCyB8YPBBG\nTwbpP69pP1updfK2vUt+ShYmCXLxOLB3qEdhnwgqFfwpC48Ocev9d6XcacYp7jwu\nRNtv0ocMkm5o0TWWupcutQWkmqzCVq+OkrqM0xrf3mfPymuM6edEREshukoL86Ei\ngTuMMGT0XO99LikszvdceNQYEATix1MHzSVhkE7jHCNBXb95H6nQGr0v7R1MIbrI\nGFlgqxwwNNKwBFNfPMWZVnKwz9hoIwW6WOuu7ntwVcPqwB/gUsRZJTu7EjIW0trX\nnhA6xLlc4X66W1sdUCkJOxsV+Y21akz6wynI0SzIfjALLI2Ls4QWrPM8GOX8nPVM\nm+Y5WXzqLJScdWYoefFJKS7kxwUJRewREB9ykCG5OdDubV+Iu/6jh6HWx3h4p3ih\nqkDypPWoxpfLgA8VZkLD1RRKGkRa858QBGdF/RHbYT3JfLEp9l9gJVKZE/yw7HKk\nwsZ/T6CMpLyorpd1XWtp2wLX8lr3pp9ecVDOdAMSqD2thDMDsZA82JrJ/vITwkCF\nBlqtDZmT0UnpxYNYTfYBam5Cd00jsqCt+Hr+QkODNe8Yae9c/D0zE3h2Vt7g9H+W\n7Ei+rF5nDYTBAApoETxK7+aUZpycBf3THAJOcwIDAQABMA0GCSqGSIb3DQEBCwUA\nA4IBAQBbCGAEwg3M5QJDMnZgu0zNOH2f9bamAS9ksyCZqzLoeQic1W7GYYe9NqAi\n7lO5jXRZpTN4L133IUQPtxCxuDooD2vFmCne92tLxJbc7uqlSVfhL8uMVOlnrA99\nKTAhySTZU5so8/OibrngnBmcdWwbhaWoCQ671M8aXM1wg2FVYDqB2GP3RvbpW11L\nOc+4tfh4mO4TwXygf7KYMOJyJW8mNNY7PZ+XW2Qe3vSXR3DuN8H8fgMh5wppXPJf\nE0+yNs42hwFjSojtI8BCb0s5DTleaakpDo8HQGNzEXP8tBlUYudtjzdP0jxFXbFa\nsT9pcMdeJ0/t5HqJSx1EjUCLYS4y\n-----END CERTIFICATE-----"},{"id":"ownpad","categories":["tools"],"userDocs":"https://github.com/otetard/ownpad/blob/master/README.md#mimetype-detection","adminDocs":"","developerDocs":"","issueTracker":"https://github.com/otetard/ownpad/issues","website":"","created":"2016-09-29T15:58:52.814912Z","lastModified":"2016-11-19T17:37:52.278497Z","releases":[{"version":"0.5.6","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/otetard/ownpad/releases/download/v0.5.6/ownpad.tar.gz","created":"2016-11-19T17:37:52.234684Z","licenses":["agpl"],"lastModified":"2016-11-19T17:37:52.423930Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"dh+Txg1iVfqXr8+cxplNQuBZGErSnXUo0ewGwnybNMJqp8/EjEo72+zPpW3dVnhY\n67YCvhrm2bo+VRdFFymEfymzSJu9nWVFkGJhEwvTxPyIdAtuD5YAVrzmnR6L+H7m\n7Q1nXE63ICPCAQpHkxIfIXLh25OhWeyofBB8AVsjDUNn58FEYJ8fFkr6dCgPriZS\nsM2J+xtZMDYufy+xFMsVf/Q3WopjFuBjMC3qOecW76ZTwtREaswOC2RtpzUku2r1\nsogrfFlFer3Ii9/CWgOktnLfjB1DzbTwdEkM2xNVBRJgdMXt2VLA9FsxFFkjmr5A\nl7x9cNLWA8RLpOIpIMBbaef75u5HgRBvSvq114UsA9GCu/EYbIgD8YxEt7xuKd4t\nenksJB5gJ2IQNdHrPbsil59AsJ/dismDN6ktYgWQEk5dINzvm9EAvucueW0Gt+Jr\nqEC5WBgJucsFxSvkHh52v43M8jgPYBfHWEL/M/+377z3+mbuIh+BcQ+vcDdiqxTF\no3n0+gw3QYIhLEe75sUhxG6ynVUdW25AKKju1kVj3KJnZTBH1R8t8/zy4DnJG8d4\nuRGqyU4BXpZjEC3nVlsC7vCncWWhxl0WZQ/MWKqsfjVAU4I88E518D6NioqMnPEJ\niCZ2x+69UCDEQyfCSKajgAYT17r3OhZei8F9KSCH8Vw=","translations":{}},{"version":"0.5.5","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <11.0.0","minIntSize":32,"download":"https://github.com/otetard/ownpad/releases/download/v0.5.5/ownpad.tar.gz","created":"2016-10-06T07:51:05.278637Z","licenses":["agpl"],"lastModified":"2016-10-06T07:51:05.348825Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=10","signature":"nYsQ9U5r7uXwtcquaWGm2XMJBNYCcA95aUx9gLZ/wEmjCHqId7+MzcCdBnom33+j\nat2XR2a4R96UAUP78bfSC4Yb7nPepFT51Y8CSpV3mDT85/+SgJdq500fXldq+qGY\nffXLneadAztyOfZO9TXljaCLdREYI0LJIGVENsxBQVKM/eyGIuZO7fF70cH5vbfS\ns37+BXB+fxcDTlP2Xuulra8HsNoS81bzjsdVMLM7B7QwwO6rZ1zd5c3UzQ1LmY5g\npQUBNd0KjfHfZ6+Fd64XZO6NGfgucGNmL3lgxdsfUqKiLtikvFxK39dYW5MckV8p\nvLoS2nZ7cgETQmAW9Ahn3ro7gXWcPxzL41oWtZOOHRRC2Yz5zlZ3Bky1o+bF9g5a\nYdDF13zV6utUkhlplZhWbjKaXa04rzOvmut8Iqhx/tmDtZRYtaQXJZWutVJYtPC3\nH86uJJnUHHNFHeoT560mp1Hq0dTeR+G+yWsPacPD1rTYgZOUVEtj3Y+YdbTODR2o\nOdGzeYFl+6CL/OcY4wPGRUCTFwvc31lIUd4DK5SPfN+IGtuuXhAqVhwy6lpkcKRs\ncj8sBoVXbMvEtMnt5uARBvA4tyVffUL4oyoIsUnvXz4u+q4WVt3T17swLm6HjGVC\nNVqU0srHN7EeBRhHlXP1CrKQWGQlS4k9j9Li4Iw+X8s=","translations":{}}],"screenshots":[],"translations":{"en":{"name":"Ownpad","summary":"\n Create and open Etherpad and Ethercalc documents.\n ","description":"\n Ownpad is an ownCloud application that allows to create and open\n Etherpad and Ethercalc documents.\n\n This application requires to have access to an instance of\n Etherpad and/or Ethercalc to work properly.\n "}},"isFeatured":false,"authors":[{"name":"Olivier Tétard","mail":"[email protected]","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\nMIIEATCCAukCAhAPMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\ndXRob3JpdHkwHhcNMTYwOTI5MTU1NDA3WhcNMjcwMTA1MTU1NDA3WjARMQ8wDQYD\nVQQDDAZvd25wYWQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC6CY7I\nHRJTaqDu376vt+kruX+QOL864joScxRuh3IOVcQktCvxasuA0EtrX7TCAQrV1tBK\nfkqJxU9uOV54RTgyh30yH/ZtnF2bYQwViGM06Snc0riqWydFrN5fxK52dpZWs63o\nUFCNhHxrX4aUGyfXu5nQMISLm4QHoZ3LDLofk1ZsiK62fM/Jz8N2PM8qeHzf1ATo\nSKcAOd3UeaS9C8bv2DuiZM7unkSO/tjrBzkMiq8ds9sIzBBsyk6BRh2HQjHPOtmO\ned+pS9mIZmc2xhssXoHL4IfZwTqwhktpsaTl7v0ROw2dwDATz/QoKMkUpboQ5lkz\nwgLQhoIZw6uAZ1R/Qjze59I3iU8zIo9quDarHBotZNXboYCmg9FRfE4mHtegVaa8\nv1a1JvFQ5gvsWEsKSV6Bzb65GTp4KG4q7YnUrzh6HJyDCGLvLlWm5OWsFj6sNzXX\nwLOv6JLORMbF4ZIo2iybb3x7gdfCu9JxMZ4JtOUC8KSJ6+ub15C1Aia3lN68dNts\nY6KwUF1Ted0o4OQPAulq5pUc+g6dTYmIKsavIiPKhMtl86AbUK50vRTeuGdFsT7X\nav73IanPdFI9bKth+tajgvB6dxcVnvBXbrsLUyEcsxsxtBJvQcMYS4aZ6ZJYLTep\n7AdK0Zt1iMdXB8+4PCps4rcG6bYB/uJeEAVm7QIDAQABMA0GCSqGSIb3DQEBCwUA\nA4IBAQCM10O+sCYhIExnx01vGzKlnRS7MSQNx8ZMmbR5Elfz4AVJAEJ96ytS2DXH\n2c+hcD0wAenXQEFk920AEqFQBT8DP34p0FmF83aMHW08ovzFiu4MdlhcqrLnko0h\ncZTXHVyS/8JZh+o6SVm8R0/BBLF1MQQ5TqRkJehbmk6gL0+MSYxehUDKWTjJITkR\nifneTw/Ba1d0AXBOq0c0HFyGxMPIlWe4qn5LtxH5t0wyVGeSj4jyv4nvd3ZGuAgY\nEUa2uYht/z475k4+vf0YhV98iQH07GnmlfD2TDZgmOCQGKlNfJh1v88OZyLLa3dz\ngRHzGwKbAiJ8T8bbpZ3e2ozXxADr\n-----END CERTIFICATE-----"},{"id":"announcementcenter","categories":["organization"],"userDocs":"","adminDocs":"","developerDocs":"","issueTracker":"https://github.com/nextcloud/announcementcenter/issues","website":"https://github.com/nextcloud/announcementcenter","created":"2016-09-14T10:38:53.939634Z","lastModified":"2016-11-24T11:21:50.324839Z","releases":[{"version":"2.0.1","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=10.0.0 <11.0.0","minIntSize":32,"download":"https://github.com/nextcloud/announcementcenter/releases/download/v2.0.1/announcementcenter-2.0.1.tar.gz","created":"2016-11-24T11:21:50.317635Z","licenses":["agpl"],"lastModified":"2016-11-24T11:21:50.386203Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=10 <=10","signature":"lmqeE6xBqUJfhuXPbjCfuWiIP0FEB4V/SsF/OvYar6rLpvDpJVf3DJoeIoxXurRP\nE9/xCcNN44P8PreRRDnFLCa0XsKOtwoGa56Lxk7IKvtiQG6xu4J6PKM+q/tIeF9K\nakw0LQXtjZB5InPhnCDDbY5YS9jgGEBylSHsgNgrElipcW+BzOBu1Amw4FECVlQw\ncQ83bio+YPZvsnE5+v3/bAx0m6QNxfyN9Sn6rMEqRkY3jfA3vejXGQH/XkputfV+\n5hOz48KbOVg7cKxg+ieJlSwC0aYjb+RXiopjc3icCoIF1llltOOeSsVYSflOb080\nupociPgQ6qIab/VNNXa2YQ==","translations":{}},{"version":"2.0.0","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=10.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/announcementcenter/releases/download/v2.0.0/announcementcenter-2.0.0.tar.gz","created":"2016-10-06T12:41:56.195206Z","licenses":["agpl"],"lastModified":"2016-10-06T12:41:56.263124Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=10 <=11","signature":"NVWYz73KtuoZ7ti2sluztJO5aFUc7PzhlDcg0VWyAQd1H7sk5wjw7i0bhrjw8O7M\nLsrb+PegnsL9eMlYM2WrRom+RF1PDP482xymZf1T8vh8qcTCm3TK89xSuiSm8yoA\niWUb/Uv/ODj74wVDWqWxAFKaAG/FestCB3InOOZQqQZLzlAV0U9ziYDGNzBjFqof\n9rLNxJ2IOqZOA7hhMIKhSrpA0KkSfNhBsVf8CWClYnVkZQiq0LoYkHkHIlXmXUr3\nOfQFKEjtsx+bNLa6CkAaocHGHJXAofX3GQZ9cjBsjZqiTfbXfcVk0kRfz7pwL92L\nI1McfJYvgMxDQG5bjRpNJw==","translations":{}}],"screenshots":[{"url":"https://github.com/nextcloud/announcementcenter/raw/stable10/docs/AnnouncementCenterFrontpage.png"}],"translations":{"en":{"name":"Announcement Center","summary":"An announcement center for Nextcloud","description":"An announcement center for Nextcloud"}},"isFeatured":true,"authors":[{"name":"Joas Schilling","mail":"","homepage":""}],"ratingRecent":0.75,"ratingOverall":0.75,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\r\nMIIDDTCCAfUCAhABMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\r\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\r\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\r\ndXRob3JpdHkwHhcNMTYwODIzMDkyNTQ0WhcNMjYxMTI5MDkyNTQ0WjAdMRswGQYD\r\nVQQDDBJhbm5vdW5jZW1lbnRjZW50ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\r\nggEKAoIBAQDPx4Hp1HdBo5v7bDEiVcv2UrVjNW+fPPKS/5rwbagtPcE/1v3WDcwX\r\nvFwaXk8qCn2UpPSQ2b1rTuTDm51G1ZmEZhNiio+rBfEe9F+3tLsq9lElqIPKhkAq\r\nEUVI6dcN+jSqvLmLhuwloEoQQSYaLrX75mY3lGqTb83h1l2Pk/brVixuVf4vJW31\r\nTgeieuGKnC+keLzKOrvTHffJakU8ktwB2Nuu1o+jN5a7u1bxKkP3LjEWPjq236hk\r\nAoOcW/wi1dUEyUKUZsZQeJyvTJh1UXdLHKwYywtUu1/VLZ1IUtNyPBfiQ8ukPp3T\r\nTnSSmG3ZnvsfM6DmAvLZ8bBQkMBzEcTLAgMBAAEwDQYJKoZIhvcNAQELBQADggEB\r\nAAB3i2NgiZ4rpNag7cXYdaFxAxdDWnke1+LX2V2R3hzGmx73/W6cKLpo3JBn9+zT\r\n1aEjlqkt0yHu4aAPVYQzOa5zIV8mjP84p3ODSyV9J8lfjFNXT7wdA8+9PVx3lVki\r\n2ONoCNBh1kOxnxI4+BsMlQfF00ZbBSuGcMm3Ep3lTFWXzuUn3MQITzPwkL5LkW6a\r\nsli/yAYQRTVDsXD8A3ACYT7BG31jGxyXtIHzqCci0MhZFdKKayMYkwfjZchIUtGN\r\nJJoU8LQoHwGRtp3wutk0GlFzpEQEvSsn/Lsvvot5IfIe46tnzA6MVj5s64s5G8+Q\r\nphhXFlzXqO/VxquPdbfYjvU=\r\n-----END CERTIFICATE-----"},{"id":"ocsms","categories":["tools"],"userDocs":"","adminDocs":"","developerDocs":"","issueTracker":"https://github.com/nerzhul/ocsms/issues","website":"https://github.com/nerzhul/ocsms","created":"2016-09-19T21:56:04.745481Z","lastModified":"2016-11-11T16:29:55.864273Z","releases":[{"version":"1.10.1","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0","minIntSize":32,"download":"https://ftp.unix-experience.fr/owncloud-sms/v1.10.1.tar.gz","created":"2016-11-11T16:29:55.856768Z","licenses":["agpl"],"lastModified":"2016-11-11T16:29:55.947926Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9.0","signature":"hVzbkmmtJCtiOkZGe1mkWElqS3IPQ8wLtSzikVvoKmcg+Zq3YLQjpQWzy0t3UVjo\n9I/BfnL0bF+kjtGc9xF6M8IQaFqPrfJmN+lNT8WYIKLI97TTsLmJGg8Q8PAux3nY\n8/NxMjWdByMw9nVBClKo0o9eSW4+EnaUSJ62Gl/XWjq728kbB16WZm+iesk8LjJJ\nqqAgczWGwz6lkZTCN5o9n0a/YoLJTf4iT+OItHZyS609Cqaxx9CAmZPj/Xn5g1fm\n8hqO2ITAXLoBj4rYS/QsZTMcubtGkJ8fq3XYKVSv2UXZfvGsNWbbGV7puKN33uWJ\n5MrdoMlJ8XnJRPDlCBcb00LY+AB+hAMooLnNy765/Ew6ztp4KNLEPWGG+Ut8/Lkk\n0jIULl1RF/FjlW8P26NfwH36K30RCJFY06OFcWnxGBkkQaNFORDIsKcqTAxkl4x5\nnfKBkNdQZppCVfOSKOZj4NkWfWx75Ouq1S0QksmOsMZoOcjy1TbBKR8h6dt9DQub\nWpYBL0QwyQShGp0Vb1qCKkP69ZQAHVUJNzIFPz9LyoguvFyv8iZmAPLYDnFBvlf2\nnSHtA19rnJmZ4H7RJ02r6BdkstxISvEiHU7RLjNQxcb+DptIWX5C03wH87HTNIhr\nvptPorEoSY1KwW9fqUvvLE/c+vfkr5cvIEwZlyVKVXU=","translations":{}}],"screenshots":[],"translations":{"en":{"name":"ownCloud SMS","summary":"A app to sync SMS with your ownCloud","description":"A app to sync SMS with your ownCloud"}},"isFeatured":false,"authors":[{"name":"Loic Blot","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\r\nMIIEADCCAugCAhALMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\r\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\r\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\r\ndXRob3JpdHkwHhcNMTYwOTE5MjE1MzU5WhcNMjYxMjI2MjE1MzU5WjAQMQ4wDAYD\r\nVQQDDAVvY3NtczCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANqZVIzM\r\nwBJuacuvgYKr2KnXuYhjKjZ58nfspSebsaGLr0ifBbo8L+NH5eaynnLCNhpegmu0\r\nO8D+KrbM1LtIkcdg1/eFpN5dTc6G2OAc9H9stmHs9nroF6MNhszgdZCz8Q8xkSoD\r\nGdSm8hdPg5GcfLrH27UilGtzdQlWJ1DralLMt3l+SfGJo152c/dc+e6SuT8+EbY2\r\nCeLdH5ImasXNpUgY+tAoEt2ZvhBrUghykBJTJVOjwL1jGLT37ybMtV4FBKo6hpeg\r\ntq/YzEk1ijBAC4pmoNWixDKCdolpVJVz0fijI9mlda3llurcp8eMhxfYJ9soXLHp\r\njvLX02YY6RfPcyy48uWVk4IEt9BvZWEVAAp7hCGA2yXrVSsR37E6sDbLsBcKav9A\r\n6dkGAgfmGkr2WT6O1/EhK/MakmnYO4WD1B+E7PnxtP/wOa+aQBmntQcd7igDiwzG\r\n6h05NYAWcRhqfZ4KWYsq0t0SezMbuHOhwzzi22q8wijC5YZbmhKSh+b3N8XwYKDi\r\nZaw+fSahPbRWaLyR3wn9zh7vKCwqrG3ugrNo6CtyoACAnmxKZ97ROFJIQTe3ndLL\r\nmv7Wy8iCZLhRYUaW/GKrF11AFwBVec9xmvkgU+PIKq2HSjwi9sCF+pFyhVjmq29C\r\nmZEPKUV7ySIpNHXpsXm8kTJJfqjSdb2ECbLfAgMBAAEwDQYJKoZIhvcNAQELBQAD\r\nggEBABvn97e8Nw8KAscf6FX/nZ99rEX+3IrZxTC8fmBgNwAvlbF2A+QZQcFI4G9/\r\n85nHK117+u7XDuwWl4QG3flWlI0hDE59Ud9Bd4AiTQ12VoXlNdYoTg/mXARxVozb\r\nKYqZ+1xRQclZKb2AqW8YiGo18okIKovn9VVRAFYPYx4O3Ve1FjgfsaMlIZLiXUFm\r\nkk+2qWo6kYsdU9FABLo6izx7RFOMbnYNre5FmDrWP1Dga/U7ErK/Dilh8g9b3HrP\r\nwP8OIZhdtFWw21wDTfyqrb9EhC/tsjPVP9u+bqyognHeiMhjbVYRbSvz5o8T7Mhj\r\nbxalCt4/LnMIfMwVyIvye7Uy2GY=\r\n-----END CERTIFICATE-----"},{"id":"rainloop","categories":["social","tools"],"userDocs":"","adminDocs":"","developerDocs":"","issueTracker":"https://github.com/RainLoop/rainloop-webmail/issues","website":"http://www.rainloop.net/","created":"2016-10-20T04:17:37.217555Z","lastModified":"2016-11-18T11:36:04.309739Z","releases":[{"version":"4.26.0","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":">=5.4.0","platformVersionSpec":">=10.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/pierre-alain-b/rainloop-nextcloud/releases/download/v4.26.0/rainloop-4.26.0.tar.gz","created":"2016-10-20T04:28:21.491747Z","licenses":["agpl"],"lastModified":"2016-11-18T11:36:04.619927Z","isNightly":false,"rawPhpVersionSpec":">=5.4","rawPlatformVersionSpec":">=10 <=11","signature":"nTYIVSB6mIwKtXIrKoVGsOGFflpLjed8jFem1VLQNtXQj4bztnNrdc4YaPIn0yzM\nyLpMSqRDNzdYNFuOeDiyKLPJPTA++MotLCNjEe7kxUekek+m+qzgnGBdcT7RQT6R\np9xWGecnVx94d6aA55uiRhgQRyHpdDMMLCOz1be+HvpwHy69DRFZ1+SPmGUt6eW0\nu5yS0vHCu1K22cbrVNXFKjxAOlGcIDm61oQuz7ycl3uAujZO4rZbWt55jilgKGak\new559A5gTp9W+j+TWKIcg6LIZ9zLRlGjcQrWJrsc+OBZQcqiYimSFyO6HhfT9TPS\nPof//I+dSsd+H0SRGGeL8DvSnK+NKZL1q5EX5pziqsv6nZFITpCDwmAN+I8AnXXL\nSNkFi53M8RZTOABpD2x7YPYP1cEvwrRweqV/C/oHcYnpfh7D2DjFeWwXsjeAXrHY\nhgFhPrg+7rf7g6UmJFOCp0dC9sBdyQ3KtJkv7bGqPr854r2cdA7xW0QHWQ2in9qQ\nLhIczc32ECi3ZVVgyF8zyT4Y/3MRS05oX3FHvHyt88mjni6bVaO78F7ZRSha8gHh\nNOAkku7AMXPvUCHaZP2iVCCoAViEso8GeR3O8xh2G42Ai61RLYwx8LB1+23EoJTr\nmfFuRYNSg+qAKCokXNnh+lDlwu4AkaQo3vtKGPXvU7A=","translations":{}}],"screenshots":[{"url":"https://raw.githubusercontent.com/pierre-alain-b/rainloop-nextcloud/master/screenshots/2016.10.20-screenshot.jpg"}],"translations":{"en":{"name":"RainLoop","summary":"RainLoop Webmail","description":"Simple, modern and fast web-based email client."}},"isFeatured":false,"authors":[{"name":"RainLoop Team","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\nMIIEAzCCAusCAhAXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\ndXRob3JpdHkwHhcNMTYxMDE5MTkzNDEwWhcNMjcwMTI1MTkzNDEwWjATMREwDwYD\nVQQDDAhyYWlubG9vcDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANqB\n5jnF9qZ/qjckt0kRjpHCOMtJumW/KiQoMeNP5nGv4ad0DS3KemOapUef8Zn7qCYb\nMnODhK7HBwPifFzI1j8bnT2hP6E0geFLb0MdN59d2NF0n4CCs1+BnepQPJ1kFbPK\n35wQRi0RDeTf/GQ+/owEVCU9a9W1P/VUXk8Z0vMoQxCXEdRqnB63SgsKl7DB9G/C\n4SYrgGor+OHVGl4ntMZhJujiM996DttrNK3iZRGkQ07L+lfUIwQ52XOhQNRdic4p\nB03lw7PpChwPGMv/EEvdR5HpCJQBJniqJbbu3Jh8bMBKTE/8fCzN3vMXICB2g3Bq\nlKkZW6fnJRGsrZ79fsQnl+WBPNSrWRLOxOfe1fyCFV1ljFB4nTH7uF3pC8ZRgJes\nkHIESHz3GJm28hn4+17ESMGHBCbs7L9FK2GY31cobU0VRntLxpSG+d9njbIAgMG1\nS7U+oKVFQhSVpdXNOaUNqhcQ3HkbQTLEP0k53A/lhLQb2+KPd8nntaELjwNyrmZg\nsVMgHj/zdlvrbguZjZFzUzDBFvkuv/5M58lNT/D1C6ufVp/R6eLsYI+nnk1ojAjz\nl7N6U8X5SXpD+Bm7+Kn1PH+bHl7cViCx8oXJXO2RhP+COXckw7BDZKtjItYHNG7M\npFwgYqWpvCu9LN6IN5a/eLqSI76dOOP3iYbaTH+NAgMBAAEwDQYJKoZIhvcNAQEL\nBQADggEBAGB0Vq0l6ndGTgNbZxSEFyBR3u3tiR3pWK81DYjsui7qBoO6P/BaGmf+\nraSwHPaBOwA9XNS8jcGLh5xdqY2p/m0dTS64xNjVL9nweWsG+FwVnPANo8C4nXdm\n9ajJ4cdg54stQK8qn1uh/xPcd23GKfYJazjYSwYmZ3pXXdzlGN9NxkeYJQxJ6B+5\npzAeVGiABI/e5URpxzz2UayRX7EE+vtpe3B84hzkLqsq0N39ZN6KLfaTyEBGLzqE\niLYeXQTV0XSRs8xVt+iyGlj7nPkv2DR0oCqRpWUFWeSBI//niDG5WxS3qg8kacSW\nfDSYhSN+IjrnIkwNtc8V9t7/GeQB5FE=\n-----END CERTIFICATE-----"},{"id":"richdocuments","categories":["integration","office"],"userDocs":"https://nextcloud.com/collaboraonline/","adminDocs":"https://nextcloud.com/collaboraonline/","developerDocs":"","issueTracker":"https://github.com/owncloud/richdocuments/issues","website":"","created":"2016-10-31T08:55:45.631429Z","lastModified":"2016-11-24T12:13:53.905352Z","releases":[{"version":"1.1.3","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=8.2.0 <9.3.0","minIntSize":32,"download":"https://github.com/owncloud/richdocuments/releases/download/1.1.3/richdocuments.tar.gz","created":"2016-10-31T09:03:40.389355Z","licenses":["agpl"],"lastModified":"2016-10-31T09:03:40.439510Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=8.2 <=9.2","signature":"s5giQeiU2zwV5X6FmxWXiG9LtNDeKBlFqK+hfvGNbGZ+nic77Y+AnXHodV4lb3Ko\n0C0ThFLuafaZRdp9rBIN2K/acCfCYKJewGuYErb7FlEl+P9J4OQbb9pva0htZJw6\niuG5eyeTufi5MKB4vuj4+jo9zhepOFAtZMa7o+ZCfJkt8vDBuq5AXxomEiZRtW+n\nf9PPUnq0z7DJVwINhHvvBZJlSLjkpJ6VIHAr+/ElWr8O/mDKq5S5ohbvpDcPqR7b\njnsBckFDLFUz1FX9dA0JCJEKMMfkcfGqZcjH17NdjKAxRW2soN5cEKluu5MkOhz9\nFEPKfshzbrfUIm5MaFGv6w==","translations":{}},{"version":"1.1.14","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/owncloud/richdocuments/releases/download/1.1.14/richdocuments.tar.gz","created":"2016-11-24T12:10:13.337165Z","licenses":["agpl"],"lastModified":"2016-11-24T12:13:53.963638Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"prDGlfRPxqT6LP0BsAFPwGww7P4Bngha2N4u5B6+F02N+RVOjGtTcXKqvM1KjZb1\nCo7qJvgJmjpvIvDmB+rup02i8ObfwP2ct6UdsD7ouzOWJG2sJANXK31bHyvOmQ2h\nvKu5eNcOkf+WFyFKYi51TbsfWn2+1Wge3WWujKAVcEvqtcOOz+uMWNtqzBptEupk\nE1aaRnQfTx488YB8Ubul06LIY0PNCHgGCWPgy817tOVT7JA+V0P0FFonl/PXE0dr\nWgtxRJmvGaNiFzYq+kQmdKMfayZTm3kdVgP0W52t5wp878K0i4s2KPg5lANvjTz7\nDCT+VV2IGIE52o4RpMUGyQ==","translations":{}}],"screenshots":[{"url":"https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-document.png"},{"url":"https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-app.png"},{"url":"https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-presentation.png"},{"url":"https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-spreadsheet.png"}],"translations":{"en":{"name":"Collabora Online","summary":"Edit office documents directly in your browser.","description":"Collabora Online allows you to to work with all kinds of office documents directly in your browser. This application requires Collabora Cloudsuite to be installed on one of your servers, please read the documentation to learn more about that."}},"isFeatured":false,"authors":[{"name":"Collabora Productivity based on work of Frank Karlitschek, Victor Dubiniuk","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\nMIIDCDCCAfACAhAZMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\ndXRob3JpdHkwHhcNMTYxMDMxMDg1NDExWhcNMjcwMjA2MDg1NDExWjAYMRYwFAYD\nVQQDEw1yaWNoZG9jdW1lbnRzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC\nAQEA1jk29m6JykcJ2Ld0YEpjPMYh6kwxY6GysNJnfkA/th7tPWL3+vBJ9oTYyVnZ\njwAE1Cqwfa9MyBKMZ2IdfIqtT8PeWzuFP7Ib942EdxUpwwh9F3lykeGsj0h4zQwX\nF9OooiS99PfLX+JpkKm15Ujb00iLB6xQmq0+3NeOT1CTD1ziJ1ueOcxBKMwaFp2a\nPuz3F5ywqCvpmxG/OBuOs0LI3/zStXhBNbUMxBrWblr7zaVNJXl/I2JCKj8Wah/H\nXUEEGbW15fAUP1f+90eQSxpEoCZDBHXOQCTJYzySGv+BjU+qlI9/gS0QbrsiyzUf\nO5lyvi8LvUZBzpBw+yg1U75rqQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQA9jU3m\nZmD0ywO3MUsG/GLigFtcWi/p7zp2BliR+NpuY2qNFYDcsIb8ZUudmUc/cJRRctzy\nAPaLLj/d+h5RFaxjTVvim1PSe6M7urK/IMSvyUVYCeQRYpG8ZJixKTCOVIBaWHMz\nxTfc51tm9EPlpJpK6JtaWrYYoWGE3k9sINdJ4JkvKkE2CBAqVhX6ZGyEQ0bnEhtk\nRu1DXn+LW7TJ4NZ8VtLWvmW/6Kfmi7dQ1V++Kmn0lO5ntRt5altePbStCHC8bhGp\nmyBOrjhrJgLIwvgH26MYZhdiSkFzoE38nMPZdrUmUDxcPCwucWJqgzDPudguFthj\nWCVZ3TTG/2z3+tWM\n-----END CERTIFICATE-----"},{"id":"ocr","categories":["files","tools"],"userDocs":"https://janis91.github.io/ocr/","adminDocs":"https://github.com/janis91/ocr/wiki","developerDocs":"https://github.com/janis91/ocr/wiki","issueTracker":"https://github.com/janis91/ocr/issues","website":"https://janis91.github.io/ocr/","created":"2016-09-19T12:07:49.220376Z","lastModified":"2016-11-21T11:22:21.024501Z","releases":[{"version":"1.0.0","phpExtensions":[],"databases":[{"id":"pgsql","versionSpec":"*","rawVersionSpec":"*"},{"id":"mysql","versionSpec":"*","rawVersionSpec":"*"},{"id":"sqlite","versionSpec":"*","rawVersionSpec":"*"}],"shellCommands":["ocrmypdf","tesseract"],"phpVersionSpec":">=5.6.0 <8.0.0","platformVersionSpec":">=10.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/janis91/ocr/releases/download/v1.0.0/ocr.tar.gz","created":"2016-10-24T06:50:43.283900Z","licenses":["agpl"],"lastModified":"2016-11-21T11:22:21.269108Z","isNightly":false,"rawPhpVersionSpec":">=5.6 <=7","rawPlatformVersionSpec":">=10 <=11","signature":"CBJkCIiUKyf2NuWfz2zJ3grhf8p7wJes7DPV/OxUzhlxIH0Fh7K54+U5A9JOOi6f\nWPhjXG1ylkyIVY1glr/B8svWNsD4jAclpnUi1/9ZW5UPT8LnRBfTbtF9Uoj0OgNs\ntsGQYbpuREoHnjbJWTRe0kq1OsOfX44xuf8PuX43B+lpQPW4iRSSz3ZIhdPcDGq1\n7pyqQM7gdKhBQ6/tOiwd7Enyt5Hi4V6jhwhUOCYeTNiLD2V3yKL+qA9DzpXUfNNw\nLGTjcaMrifibHQIZBZWbPPMmCfMJZ7GO9oR4gWHwkhWqt0yVWAJXAHJBLd5vXC5I\njtRTXRpHO/k6Dtqem8tZCVoDE5MAC7fDZ/0XzoFiXHciP6MenVasVcXo6xJOJc5y\nGsrecNftUEhP/ngxA6lMBVkLmmdpiexVisvsavPi64i34OUA6qOuxjgNVBDwg56i\n2lOEVvHa3nn0UX7ZZoQ/Nu6Mz7J3Hx/VDlttPuWe42eeJAphyDGubT1M62gW8dVB\nD3tJOF7spnK6I3BhVLviou/zs30AIRVBDTU0Orzx78cbInwy6/vyJib2a1olAaHz\nv05SzlQRnBWM4jYBe0mA/2ds9AO6VrXGrT/iLlHemj6JYoGBM185TGewA7OJyX3a\nHSlSDqaremmi+aS3onx3AKhXykDxTRkMVarePwTzzFs=","translations":{}},{"version":"0.8.8","phpExtensions":[],"databases":[{"id":"pgsql","versionSpec":"*","rawVersionSpec":"*"},{"id":"mysql","versionSpec":"*","rawVersionSpec":"*"},{"id":"sqlite","versionSpec":"*","rawVersionSpec":"*"}],"shellCommands":["ocrmypdf","tesseract"],"phpVersionSpec":">=5.6.0 <8.0.0","platformVersionSpec":">=10.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/janis91/ocr/releases/download/v0.8.8-beta/ocr-0.8.8-beta.tar.gz","created":"2016-10-10T18:01:16.076330Z","licenses":["agpl"],"lastModified":"2016-10-10T18:01:16.169733Z","isNightly":false,"rawPhpVersionSpec":">=5.6 <=7","rawPlatformVersionSpec":">=10 <=11","signature":"uEvhHfQCrzb6z+QuOoO8rYXiMsZFkrFWEqDvTyOTSgFKvo7dVoj3EfDfaApgcKEB\nIM/SqjLSO0lNhrp8F2mST3twbvLDprKsfrDWKFE6eiH0yKl2aNB+cHWE27utARaX\n/QZBD114vbWeDnbaBa4b9OwtBXDqKJrnO1LmqSLFP8guAlVTkU1jSPkRTpmwAcAZ\nJA/aiN/D2LSGfiNp/YdeTuzU+gPINIs9dCb6+PPkyam8PCBaXUSSaW+c0lAQHln+\ntb3EXxZ5YXdjPWrpEyHvFLk1N8s/w615QoMxr5fEs1M8D29aGbcL/wu7LXH4X0Yn\noiWwIFbpfrpJQlrIFumxWZR74JXiNr9J7ijnQ7SjxdHCcrLxMdnZ2cwq4iD6PnYm\nnIojhlhPOqUIzsWYCYutLWDQbUQz9eyWbj/+7XL+5KjetUUr/MnCu6xJ27IqFbAX\nHc8KRCO+9I0/qMQ2/rCZXBMeo39MGhhkgkVl5YAKwC1IEN/jlfyVNXZwYlfcHLKj\n6aNQ4zN6gGOerWWZ8qXtOeNJN+qv0nmXUKrZdnZUAhxOdB4G9Ym+JujxJZ9yNIWV\nsiqAI9J+OIzCwv/dzZhaHadONoo/RTF+Fl6Hy56HyBtMehb8w9p8ksVediqf33yt\nFAE/tzKtNK5NiRd+8MZkq/GbocaFUv3C7Y6pLMpTE1c=","translations":{}}],"screenshots":[{"url":"https://raw.githubusercontent.com/janis91/ocr/master/screenshots/sc1.png"},{"url":"https://raw.githubusercontent.com/janis91/ocr/master/screenshots/sc2.png"},{"url":"https://raw.githubusercontent.com/janis91/ocr/master/screenshots/sc3.png"}],"translations":{"en":{"name":"OCR","summary":"Character recoginition for your images and pdf files.","description":"# Description\n\nNextcloud OCR (optical character recoginition) processing for images and PDF with tesseract-ocr and OCRmyPDF brings OCR capability to your Nextcloud 10.\nThe app uses tesseract-ocr, OCRmyPDF and a php internal message queueing service in order to process images (png, jpeg, tiff) and PDF (currently not all PDF-types are supported, for more information see [here](https://github.com/jbarlow83/OCRmyPDF)) asynchronously and save the output file to the same folder in nextcloud, so you are able to search in it.\nThe source data won't get lost. Instead:\n - in case of a PDF a copy will be saved with an extra layer of the processed text, so that you are able to search in it.\n - in case of a image the result of the OCR processing will be saved in a .txt file next to the image (same folder).\n\n**One big feature is the asynchronous ocr processing brought by the internal php message queueing system (Semaphore functions), which supports workers to handle tasks asynchronous from the rest of nextcloud.**\n\n## Prerequisites, Requirements and Dependencies\nThe OCR app has some prerequisites:\n - **[Nextcloud 10](https://nextcloud.com/)** or higher\n - **Linux** server as environment. (tested with Debian 8, Raspbian and Ubuntu 14.04 (Trusty))\n - **[OCRmyPDF](https://github.com/jbarlow83/OCRmyPDF)** >v2.x (tested with v4.1.3 (v4 is recommended))\n - **[tesseract-ocr](https://github.com/tesseract-ocr/tesseract)** >v3.02.02 with corresponding language files (e.g. tesseract-ocr-eng)\n\nFor further information see the homepage or the appropriate documentation."},"de":{"name":"OCR","summary":"Schrifterkennung für Bilder (mit Text) und PDF Dateien.","description":"# Beschreibung\n\nOCR (Automatische Texterkennung) für Bilder (mit Text) und PDF Dateien mithilfe von tesseract-ocr und OCRmyPDF ermöglicht Ihnen automatische Schrifterkennung direkt in Ihrer Nextcloud 10.\nDie App nutzt Tesseract-ocr, OCRmyPDF und den internen Message Queueing Service von PHP, um so asynchron (im Hintegrund) Bilder (PNG, JPEG, TIFF) und PDFs (aktuell werden nicht alle Typen unterstützt, näheres [hier](https://github.com/jbarlow83/OCRmyPDF)) zu verarbeiten. Das Ergebnis, welches jetzt durchsuchbar, kopierbar und ähnliches ist, wird anschließend im selben Ordner gespeichert, wie die Ursprungsdatei.\nDie Ursuprungsdatei geht dabei nicht verloren:\n - im Falle einer PDF wird eine Kopie mit einer zusätzlichen Textebene gespeichert, damit sie durchsuchbar und kopierbar wird.\n - im Falle eines Bildes wird das Resultat in einer txt-Datei gespeichert.\n\n**Ein großer Vorteil ist, dass das Ausführen und Verarbeiten asynchron im Hintergrund stattfindet. Dies geschieht mithilfe der PHP internernen Unterstützung einer Message Queue (Semaphore Funktionen). Die Aufgaben werden somit getrennt von der Nextcloud in einem eigenen Arbeits-Prozess (Worker) abgearbeitet.**\n\n## Anforderungen und Abhängigkeiten\nFür die OCR App müssen folgende Anforderungen erfüllt sein:\n - **[Nextcloud 10](https://nextcloud.com/)** oder höher\n - **Linux** server als Betriebssystem. (getestet mit Debian 8, Raspbian und Ubuntu 14.04 (Trusty))\n - **[OCRmyPDF](https://github.com/jbarlow83/OCRmyPDF)** >v2.x (getestet mit v4.1.3 (v4 empfohlen))\n - **[tesseract-ocr](https://github.com/tesseract-ocr/tesseract)** >v3.02.02 mit den dazugehörigen Übersetzungs- und Sprachdateien (z. B. tesseract-ocr-deu)\n\nFür weiter Informationen besuchen Sie die Homepage oder lesen Sie die zutreffende Dokumentation."}},"isFeatured":false,"authors":[{"name":"Janis Koehr","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\nMIID/jCCAuYCAhAKMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\ndXRob3JpdHkwHhcNMTYwOTE5MTEzNTAxWhcNMjYxMjI2MTEzNTAxWjAOMQwwCgYD\nVQQDDANvY3IwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDDpXiwec4f\nXAT//7YBPSb4z6ZsBJSMfBq0VTL/HagjJnQ7BL+WagzWlS69IStNDqlIlenamYRX\n4B40heJIUinzYKjTRbr5UAw6MX29HibZccm/qgrk36o1XTgIsoRhmvSxbXDVIo1k\nbDOJN8gc2Gvswa8X+uOe9pfcDgAdqGxOvFnoKW89GnB01pCNT+xakNErGAFqVLsr\n2AeademAZnbxJ1cB54tQn2Bygb/7DKKY8EmFfIq6/27n9Jbph1FG9HIlWRT4/M2H\nU2pG3cCScWMEBPsW7kpfpnzLk7Q30Oj6k/rEYjJgmNYgg6oVnn0D9uRmhBYBnGyx\nMab1ilsK53lyuzQY0pmU8V5ULqpnNFAK6DVFfofEamDUhBPO+TZXEA5cZmuULRpf\nQQXmGpUQSyV6pS9WirMIqXFp9wmQ4vtjMdhu/6CP7cmtYZdq9uOhWEHbQM0mZUkb\n8hMjeItPx9XITI7Cge1JUOI8ZIwiB3USnQXcMd3v82l++/VgqHB7s5OaKPhygsWI\nM6RCoBcGiuQB5/fEUOg5ACOpGVyJiBda0Mi57AdoxdJmfnr7Bxcf2tAWIJL9Y7T3\nE1+V2BMxJOWwvVz26Cq83F41yXK2hJS+SbfQTqNUR8Cfh50CS9POvgRxNrJK9yvI\nkKle3ITRtGVM1XU0njWjnsdGg3D3O2mmjQIDAQABMA0GCSqGSIb3DQEBCwUAA4IB\nAQAbFddMbgfPI1szT57V1FKZrOrdYqQ7qjewlIQOzshGydbMtqS/9XL5hYocJCMt\nY6w+C/i6iEzO2Jx8D/k4rcZMXoVR6y3ZvO0Ke0gzSRsU+5eYj2FK1VV+cNIQW5Iu\nCYYIVa7pVPVHdeQH2Bba680bLV0HMF6b1fI9IwkfdCAinvCYZLjyEXZlmB7YjyA8\nHR7qPCNz4uG2Va7mlUHE3UYUYnlv8JFOV3YdbVL0nxhWwIdzSri5sxFIhdlabpzY\nyA1z/MCBEyTRo80jxFmL+MpwbsdbUJi7Qxlnd56zb6HHDGrLHXZTh9LXgyVbnhWL\nkxomWjIXQh4aMHQL4QF7U4EK\n-----END CERTIFICATE-----"},{"id":"spreedme","categories":["tools"],"userDocs":"https://github.com/strukturag/nextcloud-spreedme/blob/master/README.md","adminDocs":"https://github.com/strukturag/nextcloud-spreedme/blob/master/README.md","developerDocs":"","issueTracker":"https://github.com/strukturag/nextcloud-spreedme/issues","website":"","created":"2016-09-27T08:43:07.835196Z","lastModified":"2016-11-21T16:51:23.703819Z","releases":[{"version":"0.3.4","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://apps.owncloud.com/CONTENT/content-files/174436-spreedme.tar.gz","created":"2016-11-21T16:51:23.689599Z","licenses":["agpl"],"lastModified":"2016-11-21T16:51:23.826509Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"Mhy3hXeGWlIujx1Op39MMRdqHYOo360BCwr4FPWoTNNggH3aS0gWlh48DAfGYK9W\netNiOqIuRyA0NrVlsqR2vDILgFtODJSbKPyHd3PQn3hcGsjogjQ+dkKciLNLinw7\nOhbv6aDdRFLBeRHpX/7wOnWL5W3ko/gyn0Awvi88M9+nC5aARtqncQqPy2SxDGzH\nKlOZHSNDnEQCGMhA8hNWWKdVwNUJHod/wmBWpW5QVNSJq5DqrKZcNwpGM2UUJoql\nEqUMwDXk5uVH5r5k62Tr9kguDWoUEG1OqQSyeMY24AmA64tq/HSlAdZ+CX32bc4E\nZvm+n8poJBrdSVmWEaa4ZfYaLFdOc6Kcuid1B1Sv9kPhD9WD6T1sicdzjDzcorBK\n/MLReCuSb2E8aPTnFWRoAZ4xCUGs1IXzX5fmxI8VdzwR42R6RhGJ/rqMuZRFenZF\nbOks45K5gE1da4QpkYOUQa3GVMNPqPiT3CqjmJ8tjxq7bGpb6v+YoCLACjjPpPZL\n2Y28qLxwHVaINDFUUxD75WWdrlulRbqHwiSw8jolP9qrpXhDuLAqYam9tRwV5K5R\n8uNawnFwWkicBEYkN/WtBTouWzehOPn38tHXov6SyEyD6lkuxUBZrsGQ2ru+t33U\nk0kKCbV0GFw43I+3Ji5DiB4TUVNZYVoPG1B7Qve+UfA=","translations":{}},{"version":"0.3.3","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <11.0.0","minIntSize":32,"download":"https://apps.owncloud.com/CONTENT/content-files/174436-spreedme.tar.gz","created":"2016-10-20T09:09:26.520692Z","licenses":["agpl"],"lastModified":"2016-10-20T09:09:26.666738Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=10","signature":"D62Ck7JUnrYbrfFlX7xXVaYUMZIh2acmykIKapqfemD/tuX5Bvb08GYGTeFG61MA\nQzsqcIylDfGnC1UJbf8yWEX7PbyJD5w/R4WlbFv34njDvM8rBs4HpzSjkqQoykOF\nZpYAjH2ydfKqtZadgoIRm7et5B8X2AeoGg11ec52DId5t1wAEBcDIv824CDBUt8t\n0pVY8Z8n1MUYwU7DCjCbPy23br2+EBODFCHp+cFfMBLg3F0BJI5nY3Q8ku+0tqMR\n0NDxQcscNZ2Ck/wpVDWylfhpS+ICIxSMiyq7urP593mRrK3399SUyaMqDfgl/pxo\nqTzdBxHLaAqcnKZYglbqp+Gxbyj4teqCod8TiSMlp90VaxhC72ACuVQQRWQKuTNI\nZeW3YweWB5d7VErqBNmQR1tGnX5YFFHiKo41fVDQFsrOqHx4zP6AeU3nkl2ol/r/\n3pg553so1MOxMkyLEhGYGMfrdQqVEtajNWHUdj3B73LS+M3jcjBFIdOD+AGXPtDX\njCRymt07c1znhkL+aT8yY5SHMVbKBZj9mExL49hcLjAYYc4U++60uq9MFH5r9g4T\ndph+yT6VVEM/UH2HjvKsHv2wm937sNgG3EXQdh79JU8nCXIz7cVrJ8f5/9r6n1VP\nBbjtfDAPEjmfVCXX2gmgLuZHV+GMhLBS9bTh+61AhhE=","translations":{}},{"version":"0.3.2","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <11.0.0","minIntSize":32,"download":"https://apps.owncloud.com/CONTENT/content-files/174436-spreedme.tar.gz","created":"2016-10-06T08:14:05.212553Z","licenses":["agpl"],"lastModified":"2016-10-06T08:14:05.278533Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=10","signature":"X9zXDyMBPoXPMpZ+XXWK3MLufjY2MG8lJ+93LiW3rv0iq9yd8PafK4IvP9czO6o9\nf/vNilq+1mfl6mjTvL6QF5+sySlzbRGbT3uTBwYXyYL07HVYgl1ZLrwe0kxvxqaW\nxTvPem7+HzwClI3VnWc7ylQfzGrcYIaSIg7nNq1GOHocsgZVNyj/nVW/eQx24MjZ\nuLzZs9SJqYoBGq+mo63vRswhqv5OzGebo+G6dHm0hvRSOw9qsWCDWBugiSRU8zU4\nD9PQ0e8WbyrIrQhBoUvvkuijO3zCySx606S1HUyaHmbJzMc4Fbpwz6ggmi6IRBbT\nFBKB1DWJDwN/7mY4fhS4KhircVnAHDqiBVCTu5i3pSfMPrwFymcmbn9OBuFHAFuZ\nd9PZvWQg4v32w+Q/NNvZVW5lRi+l0w5DEqNREaj79hljk2reZMaB65lvtV9NCYw+\nHmwWqsGqZ1SgGZuhYkOzEIkCfJ2fF/VpyavJ4X6bHP9yYdkt1pxnSSoZ2HC8mkG4\nBnPf28mEXRcY8EJv0rEePqKSBIhAt8yfEW+joH/8nupe1qOdfPvP08ifLad5m76s\nt23UzlSljzq9kVO+d16z2uagKomN9USZaNnJcUDVblfjvCPpdiHLfRPEJnRsDZCm\nNffFWEMcz+TWmwBboZgTRO9v0bPDEuwfCCEW0zy8rT0=","translations":{}}],"screenshots":[{"url":"https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/conference.gif"},{"url":"https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/presentation.png"},{"url":"https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/import.png"},{"url":"https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/users.png"}],"translations":{"en":{"name":"Spreed.ME","summary":"Audio-, video- and text chat for your Nextcloud","description":"Securely communicate with your friends and family using rich audio-, video- and text chat, and much more right from your Nextcloud – in your browser"}},"isFeatured":false,"authors":[{"name":"struktur AG","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\r\nMIIEAzCCAusCAhANMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\r\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\r\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\r\ndXRob3JpdHkwHhcNMTYwOTI2MTYxNzMzWhcNMjcwMTAyMTYxNzMzWjATMREwDwYD\r\nVQQDEwhzcHJlZWRtZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKLx\r\n2dCPBLIgX948BnOdLij0YyI2+FKD6uZOvzxMaoi3rlxNf8MJgraNMzTBWEXtxT5b\r\n7ZISNp89WEXhaQ1dwwCocodd/xow4Ek63m5nUvTZXsm+YSbMgrFbxzsBhYU7KuIE\r\nT/jhKdzYgemzErwwN/gtwkLMfPo3jkgg6c8NPPohYv6k7V4VnsqtJ0JS0kX19FqM\r\nMiNz9XkcncBHy9x0BSxy4+YnwbFcgIx/MtYKlBL8NkPuuJaB/6C1O+IPYhdEdnpX\r\n+RaIue71nSStOYOqT4YDqHAIw7EmqgA1my09mmK+0Pn92GJVEAEN7JGBSQ+F32RI\r\ndB3ivGAOVtUtVvJlepWdbHxj1xqeP+LCjWzHMLQjm0TyH8VqU4Cg/wxwAEFnBATH\r\naOaWwrggzY2d9KBo1mp0k71NArLbBdlHykFU4bgiSDWrXXMz0fZzLQVwGI0Eqcxc\r\nouf6t0kvrK8oKjrnso+FjBoT7lHV/H6ny4ufxIEDAJ/FEBV/gMizt5fDZ+DvmMw4\r\nq+a088/lXoiI/vWPoGfOa77H5BQOt3y70Pmwv2uVYp46dtU8oat+ZvyW9iMmgP1h\r\nJSEHj1WGGGlp45d10l4OghwfTB0OSuPUYwWR+lZnV8sukGvQzC9iRV1DGl/rREMC\r\ncQ5ajRAtO5NPnThvN5/Zuh4n8JoDc0GK4jEZsIivAgMBAAEwDQYJKoZIhvcNAQEL\r\nBQADggEBAGHMRbPV0WTI9r1w6m2iJRrMbZtbBb+mQr8NtOoXQwvSXWT1lXMP2N8u\r\nLQ1a8U5UaUjeg7TnoUWTEOqU05HpwA8GZtdWZqPPQpe691kMNvfqF64g0le2kzOL\r\nhuMP9kpDGzSD8pEKf1ihxvEWNUBmwewrZTC3+b4gM+MJ3BBCfb5SCzMURLirfFST\r\naxCNzc7veb2M98hS73w5ZE6vO+C/wz0GTsxuK0AoLitApT5naQnjvxSvSsjFPEGD\r\nsUNUEU2Decyp0jxLVnrrpz6Y5UupfBR0V8yAv1t5Od/mCKLc5DxHsDWiKOpsob9U\r\nJN+bdzJil2NNftihD4Dm7Ha7OS3O8W0=\r\n-----END CERTIFICATE-----"},{"id":"nextant","categories":["files","tools"],"userDocs":"","adminDocs":"https://github.com/nextcloud/nextant/wiki","developerDocs":"","issueTracker":"https://github.com/nextcloud/nextant/issues","website":"https://github.com/nextcloud/nextant/wiki","created":"2016-09-14T14:34:35.977699Z","lastModified":"2016-11-22T16:02:57.758477Z","releases":[{"version":"0.6.6","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/nextant/releases/download/v0.6.6/nextant-0.6.6.tar.gz","created":"2016-11-16T15:11:14.344704Z","licenses":["agpl"],"lastModified":"2016-11-16T20:39:59.030384Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"aOZeEeThyZ0V/vXBcn6c+Z0vyCsZcN6nfSJ8oWEea4zXh4g705Si+MFZESqix3M2\nOPCnA/U8eASwdRTAEwQJrW5ECmu1THXSIsrzQzc9kFycvyOGzCgAWtuu0ayzZD2/\nU5aDWlzpLHC1Czg9QJ5UnfZR0AfChWQ402N1YzGqMShdJv6AHXFrVE+uYnIyxuYI\noPJQBUYbQwthVUjpYwFwSxw50YU17gmx5RZ0Y0OPz3i/EiuEUrxopXtfDVYAuCML\npDw37LOTRQ2JqxSU3teALh8LcrwJbTeOP0n4bTeV+vU3jvtiaEoRrwfVrK41F701\nQymGXy1/EFG0kxPGS2dRNPBAXYLZfeoWlROl3D5BWlbsCcXKU1S+22yn0TEdS7x1\nY44x8jRKnBddDE7qkn+QoQYHNNcxOREsFFLmIoyCUpdNOdDX2PvTFUYkIqdnXaJy\noAKv2GkvWPQ0aiiBtA1i4oXuzvHW/M2wOrK7v7DCpNfILrD/sjxpljxcX082nRCd\n9P3iPd2hQ6yOM9fG21LVN74b6wggI81BzFf/xJPd4ZqYLjfeG/yqd0zaiMOzMm1W\nse+kc/a4iB3BoCNX3E942pBBzew4ya8LkCXdCHUUsuelDf1va1ikTh/G7D84ll9/\n2avNqQnUh3hgOnxFCLI/5VrbqxfSTVdO6O/LTuAmwgw=","translations":{}},{"version":"0.6.5","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/nextant/releases/download/v0.6.5/nextant-0.6.5.tar.gz","created":"2016-11-09T16:58:06.856332Z","licenses":["agpl"],"lastModified":"2016-11-09T16:58:07.139404Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"DVOIbLEVggiLkNkuPW+pXqu8WYT15unUsMoqHSw81NiU6HF0Nuf3XiwnHJJDDqo5\nyX+QyHADO4ZiQpvXhGigvwD2eS1jVLatAztyxE0tEQv5eBU/7R0jQYxI8YCnC/jE\nZDa0qs+TI58EkDek0LBzueVQqrLubKgGU9P+E9H8gbWi1JHvl/2LdY7CplPqaJ+J\nMRokobPntzgx9m4DZC1RsCoXzSON7o2gp2cmunPJiXVHPhMUfIfolGEbNGJ1/xdp\nra7Y7XkPnDx4po98a38UpUh1x/2m5goOV54em35bWbh4ShNDykiE5ttz6tOywlYN\ngxceSsStTKyqscVaOV2Xu6Ive0pY9CInvrSfRnRktIWBYDyWdbK9sJuqs/s69kqn\nKQ/SjzE2smw0zwOUMnSaz0Jzr1vdPFgNu2xDYAVQO5G03V+wQ5AhxuhBz5Xp5Fll\nLaOhymZLCC7lq0DUqkeTeQ2QCfiG23hvG2VUPsIqW7xFe2YzKHZVXi9JuH//Gwym\nDmJmcyZDMvNwNiObx3ZRKsZNH2XwbldFZ9nTpb9AafyoSR/qbwd473NewaDLRTiY\nLrOP5Wx1xx6DOkRmDF2l2iT1bSJ6eoAoWQU2I0aYRH9NAr2Ugd4f2Um4o61EJaL+\nRHT9cERRySEloU/NdgmZEOi+CG0rEu+9LC5G/jGlHE8=","translations":{}},{"version":"0.6.4","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/nextant/releases/download/v0.6.4/nextant-0.6.4.tar.gz","created":"2016-11-05T18:17:47.622023Z","licenses":["agpl"],"lastModified":"2016-11-05T18:17:47.678445Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"RdkvnhNjw+kAnT6Or3+N9FzAv9DjJ9BAlmgANMwZZcaqo1gZRFewsGD2Rx1KEb9X\numSC28tl2B5/3r/+dprVJmOnYJny/7+kDmI/d+vigKfnaQJOUZ0ya5+f72pFgow7\nth8fw9rX/3+zIBs2IeEN66cis8ioFq97BJDsnDMBDr7wl7CnFJjYe6eviWuiFTnC\n4sBXlYjHoaIRRu561nwAooV+WXmWsparYPVhj2cXdyP/CnWo5HSF5jA51WCsz7Up\n7a0URXdh85xmxEbZtnjUymTW2BIegdxj9Erbfiuy/m3ApgnP+DiEQRcM13J7pXqg\n4cgFOBSzKDZgim599WBW2uNO1ztnDYOzz47GXDfJhcdvKiZZoQpUF9W4LMRtheMz\nxD9YArO3j3d+VOInSYU2Rpvhugwo1LExhwnRdT4+cOZfEeq0VojiM7yBZLDdEjIb\nGdYUJtNWSU0F6cPab2Au8FgZymLrHL9EpGvxuA1oAwtRxHAgMElJG2O6Jp89gGl9\nh/AptypeTvzNEc9/Kg24ueBKqmSUd5a45pZ3gM2pNATJhUK7fzLb/K6cq/kEzZtj\nOPra1ZfP0/20u8VP32Rgw1cFmIjqt8DFzUmOMpMfyoJkdldtTwQtGk+yIvtN1zp6\nT2zDknAKA2N/rZ/0SJl8KxVVNLhQWtYBJ+rFAdapuxI=","translations":{}},{"version":"0.6.3","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/nextant/releases/download/v0.6.3/nextant-0.6.3.tar.gz","created":"2016-11-03T21:51:27.654342Z","licenses":["agpl"],"lastModified":"2016-11-04T18:25:35.697130Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"Hf5GB4xd+rVXzWvVpGbbF5tqmnI+DGHlNHdLYPImFLS/Z4K5wKeNp80E5sd/RkAi\nhyuEsdWHlGDVMT6s7oeCmH/ClyWqLNSz9VH4KYqyFgD4+usHZp9PrEeEKbvPDPKv\nD3eB7Ats34cWcpf4E1oR5wsPicgmdgIgb2uMXzc/1G9xUBRWzocwCstzjEEAB/VJ\nvJuHvhDTGG294P4gOb82MxKCQ8LZ4i1QXzOf/mLETOubiUbZtJgTReYvpdAo2Wct\nbdfDFw13LYZkCf71r9jIQ3PSPlIpD+0BwAlE1fi0Br9dP2JjIfiKN6CGVaki6O0v\nKR42jtcE9xXiAop0Ym1FYMWJvQUy5PFLMwYDfEd6CvfEFJl+fi+RjXNDNZcTyw00\nHa48sACoGzxwts2JknWMU57mwvi0Z4uwpE0cFp/PRzBsXmSlCzWHjJhu7+2qambE\nAabdP9nH2NvqJHUJyPsxtDSrSWCBY4CoL3wYu36UrIA4NepyudMPNe9fhKTEU0bg\n8DLclw6hYdj5p9Zj3OUuwOZLz6r85KwnooTsUjOYkBXvdUuHWkgONqqZlPMApS4i\nChRQ7ysHAinPyyzsvr0PR9g6J52CSCO/7qwSJy6yqSzuSWrbZUa4FVTcKIwWJJPu\nJ2XzB4rWVG1wWjzMM6MIvFbO2HY9upzh651OdOwsYvk=","translations":{}},{"version":"0.6.2","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/nextant/releases/download/v0.6.2/nextant-0.6.2.tar.gz","created":"2016-11-01T11:24:58.054892Z","licenses":["agpl"],"lastModified":"2016-11-01T11:24:58.151609Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"h8KgwMh2RGGIp7q/II23VSfE5Ibkha7p/C1kvIfG6QIIc2Zu/Mm3Oekynnysh5ZJ\nZuMTaeWbejbBAmlnxW+AwBWa/s2PoMhv7foVvdtg76l9/qr+9jGvUM7D1LbbBvAy\n/XW6JSrhhBZHOohdU7kwV5Xnwsn/NC/zUe0G4eZ+9fc9uSntkob9wnWvUs2daAeD\nY6Mi7Xt/XAIX65OIVTKfC6ah1SlbXgtJ2i2j4G32I9jRhmbkpt/UJEangn90fHnY\nQXNJ85OyV0aNMafNHoMSL3uLscdvjp0Hy8w4iBeavsRlCs0GiUoG1+YdwTwmC9EM\n4CjbMfRJ0DYK7u697TOmS8MQzk8O7f5THtjeokZlrom2YnV9t6gLvjnxl/+gXPdJ\nmgLixnA8P6tPsff9pquHKQZsvxjv6vVa2DVJc8VpcqJRih7yj/3V7rxesEP7MUnP\nznIOcwzTsKXHuAnvujpCwyQj3QtpQK2XJPQ5WkKgwbTdvriVJfnzPironhcHo1vC\nbuUDOdhL59aySChw2cZGD9lCWaxYR7I1BDDzWKNl9Qg0AZ2auyGUGTv8P2vi5qUB\n0CmnkzkZurR5ju6Nb9/2lcZvda7QJdIdMtm2Wnn+Ak/Z3Y4IehB5PPDP5/MMAhQY\nXE8Jqe0mGtiU/O2346L5IThkS58JlRmep4kYv+II9zE=","translations":{}},{"version":"0.6.1","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/nextant/releases/download/v0.6.1/nextant-0.6.1.tar.gz","created":"2016-10-27T21:16:47.066097Z","licenses":["agpl"],"lastModified":"2016-10-27T21:16:47.125641Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"axSX4Kz2P4PbKU676DibjPZsxk8hCIG3lLOmeMXoiBhp3ka4wJ8u5tNwTzgY8/MV\n3mjXe5DNttD66SqmiRNSPKbotYHVFFW3wFK+Dgh/++n/KTomGYUeIwt88Z9ecbuG\nNT6U46jFrfZBYzRHWzbgiJ4c7MCoid9cfmoB7HDuQSyw+E0S2vbLL8+jzMcIzF+5\nTh/sJEterXCyrWSciw/9x98F+4svNbskdEIvrOox3+K6UIhpsojqJR2+bQhG3rsM\nPerOb6J+bzHdLV1ZL/4nWEz1F30T7B08QxY/4pHD68JFQcdtzmHMIhXfCoRvWhN2\nVRnizx3IXBALY4F49Ql6bjsnr6BCp+LroM5RSQ3eupDcqejDJLbjPz8xfOMOwlx7\nz84Xd0MUyqaEkxg1ihsWLbPlYACUZ2aoDkSQUIbfZTTiov7eqTM8UBc/UqVID/LU\nyEW4gjFZzQy6kX76XRAGq1vebKFjCU63asCnVyJhF/YQVTu1hPGbFslkRKnYuh8W\ne4MeaNfbdjcSEX+7oTcPJz6V09pOPvukXL0M1m7lS9PhTisI6oGj8c33GPYp/DSK\n6SGk+ukbt1mwFuFKdTvAMxo1lk96D+pKUv4MX/ralaaoIAmwPTGsSQ04RyL454ae\nU6q8PApwrVyPHYwMBPtXGoQMyb2ZV9rylazYbKCQ8I0=","translations":{}},{"version":"0.6.0","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/nextant/releases/download/v0.6.0/nextant-0.6.0.tar.gz","created":"2016-10-26T01:46:48.419025Z","licenses":["agpl"],"lastModified":"2016-10-26T01:46:48.521063Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"W2TmbX/NbbfPPjIJLalO0kCDhhQF1pEohH/CxO9bY+yR+a5NKiTbpAhG2McqpTSj\nmgC4J8/thmwGlWGC+VW+KlpXzzjc7wCgMGMKViOpGD3pIy8p8U5MXTqVgjjrEb9g\nKgr9uErXzxJ5oDfkx8Uh1bUeBJTsAAivGJqMlhBYFGxw8BSB09sfOZytNxo4wbwZ\nNAcYP1qvkUQ8CVR0nInSTRfLvAp5+e/8xxyYZwJIWrdNgpoP0CxiwzKP/VSjBk/U\nsPU4R72UQnVZB0InRCeh/KNTwu1YiPkUKm+mNmt2hCfN7Fm6bY2rUMH7oa8KTkqn\nh52FhbaYRSAR1OPdC5RnHiQWlPh71gq+4Xqgp19Eawnl/QiVteVifSjNQZ+Ban8M\nRyw/PxHnzIWg/OAjx81Jx9mXjUIHSeUxMTJTKTp+lEqIAzjku0iHeU5UPGCfE+VM\nwmopZfnlfk2nLkUwjQXLCIcnZD1ME1m0h/H4Ad0Q/qXpBScUp47npkxg2b8zPIhk\n3aXUmNPLgwyXPWvAuaBK/WwpNefUnqWFns8t2Alpzg/EpC2PrZqciCNDcRFEycoa\nX+JsFyD7eYA7Dc9iIf09gXZX+tZ+Jinb+iPDwYrl1u/7IIBoBlUGCgo+cF7/dL9S\nc3vYeWw6MCH8Sv+ckgS2g726BfdN5EjB/8cb071b4lE=","translations":{}},{"version":"0.5.1","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/daita/nextant/releases/download/0.5.1/nextant-0.5.1.tar.gz","created":"2016-10-17T15:23:04.515057Z","licenses":["agpl"],"lastModified":"2016-10-17T15:23:04.576640Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"Pp3rC/9RmAYURneGpGit4HZ2t1qH9A9nwsUnGDgRuJ0akIii7CtJC+n8l1b9k73/\nhxMYnp2JOBu2HWKgFp9a3yeo1xphI5hOUdVQ1UZAWxIQyDI1FZVYDr81l7GCdkqm\n2lMxgviFADSYURCgEnAsj9Nt0NZ6LDcJZiJg3iPAjkDI0U+KnEBjtx/XRFqGUnfp\nCUZ/XLHh/hvoEitSHepTBDCMKkTNjbDEwBYfA2rAoz4zbMR5zKLU+1r1DIUgWSRe\nbk2i8TaTDVL4cbb6MhkGKwkujb+Atikvkpi45o7+fyQMs84c6fjjh/TZJaC+dMyG\n1GCikMPwwtEPjXtnLzynERAxJOd5mP4Ee4sD8ZrnzNUehpyFR88pwWU6r+dmiebb\nnsYlGkhIu2aIO2O4HZ4sUTsO5sfjZ9me7jsafhgJl6iG4IBeHa/L1MsSbhsh6mvH\nYsz4Xsluwr0QcFLmSDDQQYynyogKfJZG2xQsadM0GETWgXE44dVeRvMUsILfB4uZ\nmfKgd23SgaOhYC8m4bg5Hxnkl+xHJnyGZ6jhqg7bhuKwsoLymc18Vmjmb7a45HGV\nXbL5CTmw9yaPOBS3v7v91TnlB+0lhlzbKzZ0xIhY55qsTC76uScbTLwndPqNGaF7\n2koxRbJ3jcmf/Z2MLymdRi2BTZbZkPkxgVrSf9plaR0=","translations":{}},{"version":"0.5.0","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/daita/nextant/releases/download/0.5.0/nextant-0.5.0.tar.gz","created":"2016-10-11T11:47:46.191539Z","licenses":["agpl"],"lastModified":"2016-10-11T11:55:40.393000Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"qzQJSLK8nkrQedwwxUdhxL8bq3aXyppAlWJo+n3GqSvqA8uNTzl3Wsci0LsnBV0E\nDvDNW8K0enhl563F/bywQrDhgKl8jTX/CA5KCxqO9P+tvE80zAfMqiRnQayVcWuY\nSWX6RqfI/kqiWyN1SsFp2EDlas6eb+xfIoiJamlfsN0qzHYOFt5W77wmw2Bn9dB5\n9nwHHyC0z60Pf2pPduc/KuZ/971WrDFaIapL7Gm+z9XoaKSwUT575VtS+RNJkOKy\niBrwnHdc8x/62HPFOXsUYjCt2aEmLzPCQN8Ke5pd3596hm5wbAVzTHuxf2H35tb3\nljfGqAZ5AJX2Xd13d4aHXFdSEILwv6IFq2fx0hO3vkvFEoKF5oQ2t3hi++Mw/h8R\n15OKZCOC1bFH3gTwdshmnHSTSr3LxDeTF60aH16wpXcehQuJHagpb/aG8mPD1w+v\n759/mekqa4LYlqT9TLWTqX3UPeQXYIwcPijG84IvW1BDK1M4Mj2Vqsld4jXwG6CP\nORIL8xoQbA52dQI1Y19JXcU9zxIb6GaHYgpV0wejatsZRfhPv2Yd0CBShF4HY7aw\nnfcm88pqzOKNvjnLZjTFQwuJ0AUUSOsWhgZzYt8tATJ2KDZ+lxz+WAMGXJAC/ciY\ntrrglY7YxwJNLbYp+arE0sowZx+IOVaSZBvmUGHiEBY=","translations":{}},{"version":"0.4.2","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/daita/nextant/releases/download/0.4.2/nextant-0.4.2.tar.gz","created":"2016-10-06T10:31:12.482416Z","licenses":["agpl"],"lastModified":"2016-10-06T10:31:12.551117Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"QHJhYcBMi5HyPofshZ7EdcXsOfRrl7o48Y3BBBq8CkmYtFDbekghdJqjFbwwZa5u\n8FtgMVwssql/RSDNP6M2Zc/MpQ3K9gDm+DyxE5KRmtMEpzHB+oD+1DxP7kAoyW8/\nnBr5iiQSdLCelddMcTwbdxskLFUXIs3cFuLGhMvr8pdQOAgfxte5lolrj4/8EsJ0\n0yUImgIYG4NlgmvCygGApdpVaOcK7XVtv4oH+x43JmX9YZ3Ce0DQPYPUbFTCf4ZS\nS075j1vcnPx2cRFGxc+YpKzYVVYoy7ZdB75Hq+kaei/atxrTyV5+gcCrVPnH1RkX\n6G8rgu5l8FoGJYopi8/9dd8LsGLFx53CHMdEVob3tFR0WeK4TJAGJa403zE6S3hM\nxr86WCedmjuti0uOhSQr5AEVAoXZ/JUWQMMsPAUMuKEYVjKfmve6TlcNMC2oM5XT\nXcOf4OP3pcQq4ViN53o4Pj6NGSci6IzD6xLeAxKZUoTX37ArVKH6RHS5Najc193H\nRhYRnfE7D5YOr1u10HaZCFCVJif2MgMP0/uH2759NoRjXFowrh7Z6dW7JQG5lbHN\ne0jjJH1Y8m8H1peGGcmM0YxFiOVZ0ER7P+AxT4Cbau/cVhaS8vnPF2a2a6YFRiFS\nVH4aqazvvXrtifDr3lfvlyPCrP/570nwvOJgZGk+K/Y=","translations":{}},{"version":"0.10.0-alpha","phpExtensions":[],"databases":[],"shellCommands":[],"phpVersionSpec":"*","platformVersionSpec":">=9.0.0 <12.0.0","minIntSize":32,"download":"https://github.com/nextcloud/nextant/releases/download/0.10.0/nextant-master-0.10.0.tar.gz","created":"2016-11-22T16:02:57.740378Z","licenses":["agpl"],"lastModified":"2016-11-22T16:02:57.900805Z","isNightly":false,"rawPhpVersionSpec":"*","rawPlatformVersionSpec":">=9 <=11","signature":"kDO3xbPpoUdl2qo362tXfJIqKeiKE12M8FkMXbdKiRNzuQyvDOehQq3dErALZDOr\nLG47Tpez/Kn9Fsx1y4dQDx0w9SD3pyoqvjj1O6KkTYN6srpitQcj9EzEItCY+MZd\ngRSc7Px9MzxpFpgwtuThGVlSt5kLMd0vjWFLVcv7k07rZfWEsTwXd24INIDtlr1A\nC7hyLB777nEOGa7oAzx8nr+FJcIbmu9opVZk8AL40FOFDNBgfAy2AS9hGZreUmRV\ndV9Zh7UAR+RsEeO51xcU/CKqC8Jb0jL1gkYyUaQy16oe1HF9bRs1PWuNL5mYwsmy\nZNn0ay/a7mb7hxJbza1F3lbgBtodvbgUm7+So/QvaR29CSAqqoUXeQy6FfSBVWhZ\nYlTxdQfKcBcUPFO14BBk/O5p5iQaG8JCLJ/EZGDPDIVDMn7crGQ4oLZJv80eqTeB\n7ueDmWaD3gQ9j2XKsMk1uLSyY4unt9AaTofBylsKD1SjLhyxofGZym4jc2+M1GnQ\nyLcoEMSexnKuextu4nzrA0y5k3z9tvO07R29lwT1GFp6oGAakMLob/6XrGsm3YQY\nRQXgfXKFw8XmXBumqG8ayEIyvQ/O8nO6r4R1H8a7ooj6oWa3PhPsen+gLE0SpJPZ\nz3e2TLliwC4VtZp69H7u3px5Qn1Fc6RMDTh571edCr8=","translations":{}}],"screenshots":[{"url":"https://raw.githubusercontent.com/nextcloud/nextant/master/screenshots/displayResult.jpg"},{"url":"https://raw.githubusercontent.com/nextcloud/nextant/master/screenshots/admin.jpg"}],"translations":{"en":{"name":"Nextant","summary":"Navigate through your cloud using Solr","description":"\n\t Navigate through your cloud using Solr\n\n\n**Nextant** performs fast and concise _Full-Text Search_ within:\n\n- your own files,\n- shared files,\n- external storage,\n- bookmarks\n\n\n### Recognized file format:\n- plain text,\n- rtf,\n- pdf,\n- html,\n- openoffice,\n- microsoft office,\n- image JPEG and TIFF (will requiert Tesseract installed)\n- pdf with no text layer (will also requiert Tesseract) _[work in progress]_\n\n\n\n## Installation\n\n- [You first need to install a Solr servlet](https://github.com/nextcloud/nextant/wiki)\n- Download the .zip from the appstore, unzip and place this app in **nextcloud/apps/** (or clone the github and build the app yourself)\n- Enable the app in the app list,\n- Edit the settings in the administration page.\n- Extract the current files from your cloud using the **./occ nextant:index** commands\n- Have a look to this [explanation on how Nextant works](https://github.com/nextcloud/nextant/wiki/Extracting,-Live-Update)\n- _(Optional)_ [Installing Tesseract](https://github.com/tesseract-ocr/tesseract/wiki) ([Optical Character Recognition](https://en.wikipedia.org/wiki/Optical_character_recognition) (OCR) Engine) will allow Nextant to extract text from images and pdfs without text layer.\n\n\n\t"}},"isFeatured":false,"authors":[{"name":"Maxence Lange","mail":"","homepage":""}],"ratingRecent":0.5,"ratingOverall":0.5,"ratingNumRecent":0,"ratingNumOverall":0,"certificate":"-----BEGIN CERTIFICATE-----\nMIIEAjCCAuoCAhAFMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD\nVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI\nMTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB\ndXRob3JpdHkwHhcNMTYwOTE0MTI1NDQwWhcNMjYxMjIxMTI1NDQwWjASMRAwDgYD\nVQQDDAduZXh0YW50MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsbnQ\n+9acjKHfcrUj4yqBpD++GmQ5z2Sp8C8uOz4ZbLyM9bUXEYHo4a4u3CdC49kGUkb3\np5MkEAEzslTWDi1eh5MZgPWpbPgItsDsXY1o55O3jtxNkzSG5/yYcPQcuKtIOm9S\n7DY0K+UQt3nK+RrXEZfARMNrzFbEzpE3b7w901Yl5n+m/B8rhW4pqg8uSfx3u04J\nwduV1fHwoHUB0Ox5HyWib4Pq1XppNh7xdc2Fg93JxshwuCPJyOOzrFTnxC7s1yzQ\nUvaqkjPW5QeQRunQjZ2XtpYH8f8v01W18bNEiHwqtFwuDEyCVx1rvEMgUDVXdPkP\ngZrlB5TzGmz0U3HzYvf6205WuzfHxz7kPj502wP51PoZBKpniggKzmuXkx6BpsZC\nZX45VpDHdiATLwRj1t2bMs3C01nzpIWO5ZwFtkepH3Y+mvwX5lDh/XDsqJC2Yo8o\nWMmniWNW7dspufYOsBUqqYGP7rkailgVT4oYk6D1j6oFZ5SSpfPF5lsyYedDSM6y\nbIGVkSF+sjLK6R9BenBijKceAKsS//WwRYCBPC+JHlsYpXKW12bL+C47Kj2/N6d4\nrYryzV6ofVSF6pwIq0oEjoyfBfNpYavf3xrRkSSmIIlPSnMY7DT1xkGD5retxSm6\n+WIfkWKRZpv2S6PhMHGLspYc4H5Dj8c48rG5Co8CAwEAATANBgkqhkiG9w0BAQsF\nAAOCAQEAOZUwyPaUi+1BOUgQJMWqYRoTVZUyBshTXSC7jSwa97b7qADV9ooA6TYF\nzgsPcE41k7jRkUbnjcY45RGtL3vqsgZbx5TjPa5fGMxlqJ6eYBOY61Q6VIHEVm3u\nxnPEO9dsMoDBijvo5D7KtE+Ccs907Rq70kCsbrdgPHkyb5tDSnCKogN1LiQrg1EP\nmy7Z1C7jG9/h57vx0+QBMDCYnTmqLsvMKqo27uHskzAiB7VXLEdSZ2FtMGHkLUQO\n0bfhnvTZ2VhMmK83t7ovo71An4ycmsolGD/MA0vNI78VrVISrdI8rRh2WntUnCBU\nEJL3BaQAQaASSsvFrcozYxrQG4VzEg==\n-----END CERTIFICATE-----"}] |
| 47 | 47 | EOD; |
| 48 | - public static $expectedResponse = [ |
|
| 49 | - 'data' |
|
| 50 | - => [ |
|
| 51 | - 0 |
|
| 52 | - => [ |
|
| 53 | - 'id' => 'direct_menu', |
|
| 54 | - 'categories' |
|
| 55 | - => [ |
|
| 56 | - 0 => 'customization', |
|
| 57 | - ], |
|
| 58 | - 'userDocs' => '', |
|
| 59 | - 'adminDocs' => '', |
|
| 60 | - 'developerDocs' => '', |
|
| 61 | - 'issueTracker' => 'https://github.com/juliushaertl/direct_menu/issues', |
|
| 62 | - 'website' => '', |
|
| 63 | - 'created' => '2016-10-01T09:16:06.030994Z', |
|
| 64 | - 'lastModified' => '2016-10-06T14:01:05.584192Z', |
|
| 65 | - 'releases' |
|
| 66 | - => [ |
|
| 67 | - 0 |
|
| 68 | - => [ |
|
| 69 | - 'version' => '0.9.2', |
|
| 70 | - 'phpExtensions' |
|
| 71 | - => [ |
|
| 72 | - ], |
|
| 73 | - 'databases' |
|
| 74 | - => [ |
|
| 75 | - ], |
|
| 76 | - 'shellCommands' |
|
| 77 | - => [ |
|
| 78 | - ], |
|
| 79 | - 'phpVersionSpec' => '*', |
|
| 80 | - 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
| 81 | - 'minIntSize' => 32, |
|
| 82 | - 'download' => 'https://github.com/juliushaertl/direct_menu/releases/download/v0.9.2/direct_menu.tar.gz', |
|
| 83 | - 'created' => '2016-10-06T14:01:05.578297Z', |
|
| 84 | - 'licenses' |
|
| 85 | - => [ |
|
| 86 | - 0 => 'agpl', |
|
| 87 | - ], |
|
| 88 | - 'lastModified' => '2016-10-06T14:01:05.643813Z', |
|
| 89 | - 'isNightly' => false, |
|
| 90 | - 'rawPhpVersionSpec' => '*', |
|
| 91 | - 'rawPlatformVersionSpec' => '>=9 <=11', |
|
| 92 | - 'signature' => 'ERBS9G5bZ3vwCizz2Ht5DehsVJmb63bzF3aYcH7xjbDVMPagOFWdUAiLDwTeZR1n |
|
| 48 | + public static $expectedResponse = [ |
|
| 49 | + 'data' |
|
| 50 | + => [ |
|
| 51 | + 0 |
|
| 52 | + => [ |
|
| 53 | + 'id' => 'direct_menu', |
|
| 54 | + 'categories' |
|
| 55 | + => [ |
|
| 56 | + 0 => 'customization', |
|
| 57 | + ], |
|
| 58 | + 'userDocs' => '', |
|
| 59 | + 'adminDocs' => '', |
|
| 60 | + 'developerDocs' => '', |
|
| 61 | + 'issueTracker' => 'https://github.com/juliushaertl/direct_menu/issues', |
|
| 62 | + 'website' => '', |
|
| 63 | + 'created' => '2016-10-01T09:16:06.030994Z', |
|
| 64 | + 'lastModified' => '2016-10-06T14:01:05.584192Z', |
|
| 65 | + 'releases' |
|
| 66 | + => [ |
|
| 67 | + 0 |
|
| 68 | + => [ |
|
| 69 | + 'version' => '0.9.2', |
|
| 70 | + 'phpExtensions' |
|
| 71 | + => [ |
|
| 72 | + ], |
|
| 73 | + 'databases' |
|
| 74 | + => [ |
|
| 75 | + ], |
|
| 76 | + 'shellCommands' |
|
| 77 | + => [ |
|
| 78 | + ], |
|
| 79 | + 'phpVersionSpec' => '*', |
|
| 80 | + 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
| 81 | + 'minIntSize' => 32, |
|
| 82 | + 'download' => 'https://github.com/juliushaertl/direct_menu/releases/download/v0.9.2/direct_menu.tar.gz', |
|
| 83 | + 'created' => '2016-10-06T14:01:05.578297Z', |
|
| 84 | + 'licenses' |
|
| 85 | + => [ |
|
| 86 | + 0 => 'agpl', |
|
| 87 | + ], |
|
| 88 | + 'lastModified' => '2016-10-06T14:01:05.643813Z', |
|
| 89 | + 'isNightly' => false, |
|
| 90 | + 'rawPhpVersionSpec' => '*', |
|
| 91 | + 'rawPlatformVersionSpec' => '>=9 <=11', |
|
| 92 | + 'signature' => 'ERBS9G5bZ3vwCizz2Ht5DehsVJmb63bzF3aYcH7xjbDVMPagOFWdUAiLDwTeZR1n |
|
| 93 | 93 | i4gdZ73J/IjHQQJoOPwtCjgbZgLPFqL5x13CLUO9mb/33dZe/+gqEDc/3AuJ4TlA |
| 94 | 94 | XUdLxHRb1bwIlJOwuSr/E24452VG20WUhLXBoM0Zm7WcMxvJWo2zAWnuqnLX3dy9 |
| 95 | 95 | cPB4PX+6JU2lUMINj8OYQmM1QnqvjG8YV0cYHbBbnSicOGwXEnni7mojsC8T0cn7 |
@@ -100,42 +100,42 @@ discard block |
||
| 100 | 100 | bkR1DTBCyDjdpNBidpa3/26675dz5IT5Zedp4BBBREQzX08cIhJx5mgqDdX3CU09 |
| 101 | 101 | uWtzoaLi71/1BWTFAN+Y9VyfZ8/Z3Pg3vKedRJ565mztIj0geL3riEsC5YnPS0+C |
| 102 | 102 | +a3B9sDiiOa101EORzX3lrPqL7reEPdCxrIwN+hKFBQ=', |
| 103 | - 'translations' |
|
| 104 | - => [ |
|
| 105 | - ], |
|
| 106 | - ], |
|
| 107 | - ], |
|
| 108 | - 'screenshots' |
|
| 109 | - => [ |
|
| 110 | - 0 |
|
| 111 | - => [ |
|
| 112 | - 'url' => 'https://bitgrid.net/~jus/direct_menu_nc.png', |
|
| 113 | - ], |
|
| 114 | - ], |
|
| 115 | - 'translations' |
|
| 116 | - => [ |
|
| 117 | - 'en' |
|
| 118 | - => [ |
|
| 119 | - 'name' => 'Direct Menu', |
|
| 120 | - 'summary' => 'Provide easy access to all apps in the header.', |
|
| 121 | - 'description' => 'Provide easy access to all apps in the header.', |
|
| 122 | - ], |
|
| 123 | - ], |
|
| 124 | - 'isFeatured' => false, |
|
| 125 | - 'authors' |
|
| 126 | - => [ |
|
| 127 | - 0 |
|
| 128 | - => [ |
|
| 129 | - 'name' => 'Julius Härtl', |
|
| 130 | - 'mail' => '', |
|
| 131 | - 'homepage' => '', |
|
| 132 | - ], |
|
| 133 | - ], |
|
| 134 | - 'ratingRecent' => 0.5, |
|
| 135 | - 'ratingOverall' => 0.5, |
|
| 136 | - 'ratingNumRecent' => 0, |
|
| 137 | - 'ratingNumOverall' => 0, |
|
| 138 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 103 | + 'translations' |
|
| 104 | + => [ |
|
| 105 | + ], |
|
| 106 | + ], |
|
| 107 | + ], |
|
| 108 | + 'screenshots' |
|
| 109 | + => [ |
|
| 110 | + 0 |
|
| 111 | + => [ |
|
| 112 | + 'url' => 'https://bitgrid.net/~jus/direct_menu_nc.png', |
|
| 113 | + ], |
|
| 114 | + ], |
|
| 115 | + 'translations' |
|
| 116 | + => [ |
|
| 117 | + 'en' |
|
| 118 | + => [ |
|
| 119 | + 'name' => 'Direct Menu', |
|
| 120 | + 'summary' => 'Provide easy access to all apps in the header.', |
|
| 121 | + 'description' => 'Provide easy access to all apps in the header.', |
|
| 122 | + ], |
|
| 123 | + ], |
|
| 124 | + 'isFeatured' => false, |
|
| 125 | + 'authors' |
|
| 126 | + => [ |
|
| 127 | + 0 |
|
| 128 | + => [ |
|
| 129 | + 'name' => 'Julius Härtl', |
|
| 130 | + 'mail' => '', |
|
| 131 | + 'homepage' => '', |
|
| 132 | + ], |
|
| 133 | + ], |
|
| 134 | + 'ratingRecent' => 0.5, |
|
| 135 | + 'ratingOverall' => 0.5, |
|
| 136 | + 'ratingNumRecent' => 0, |
|
| 137 | + 'ratingNumOverall' => 0, |
|
| 138 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 139 | 139 | MIIEBjCCAu4CAhADMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
| 140 | 140 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
| 141 | 141 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -159,68 +159,68 @@ discard block |
||
| 159 | 159 | G2dF9Gtu4GiQ5fuaJknaxlgXHovfqeZwZJX9o4M+Ug81AqiY7XjdiaCPdh0Tthcx |
| 160 | 160 | 2OmWZo7UBREWenjKyFZZ/iKoqH5sdenBtpo= |
| 161 | 161 | -----END CERTIFICATE-----', |
| 162 | - ], |
|
| 163 | - 1 |
|
| 164 | - => [ |
|
| 165 | - 'id' => 'apporder', |
|
| 166 | - 'categories' |
|
| 167 | - => [ |
|
| 168 | - 0 => 'customization', |
|
| 169 | - ], |
|
| 170 | - 'userDocs' => '', |
|
| 171 | - 'adminDocs' => '', |
|
| 172 | - 'developerDocs' => '', |
|
| 173 | - 'issueTracker' => 'https://github.com/juliushaertl/apporder/issues', |
|
| 174 | - 'website' => '', |
|
| 175 | - 'created' => '2016-10-01T09:16:47.111889Z', |
|
| 176 | - 'lastModified' => '2016-10-12T19:50:16.038821Z', |
|
| 177 | - 'releases' |
|
| 178 | - => [ |
|
| 179 | - 0 |
|
| 180 | - => [ |
|
| 181 | - 'version' => '0.3.3', |
|
| 182 | - 'phpExtensions' |
|
| 183 | - => [ |
|
| 184 | - ], |
|
| 185 | - 'databases' |
|
| 186 | - => [ |
|
| 187 | - ], |
|
| 188 | - 'shellCommands' |
|
| 189 | - => [ |
|
| 190 | - ], |
|
| 191 | - 'phpVersionSpec' => '*', |
|
| 192 | - 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
| 193 | - 'minIntSize' => 32, |
|
| 194 | - 'download' => 'https://github.com/juliushaertl/apporder/releases/download/0.3.3/apporder.tar.gz', |
|
| 195 | - 'created' => '2016-10-12T19:14:10.802359Z', |
|
| 196 | - 'licenses' |
|
| 197 | - => [ |
|
| 198 | - 0 => 'agpl', |
|
| 199 | - ], |
|
| 200 | - 'lastModified' => '2016-10-12T19:50:16.104357Z', |
|
| 201 | - 'isNightly' => false, |
|
| 202 | - 'rawPhpVersionSpec' => '*', |
|
| 203 | - 'rawPlatformVersionSpec' => '>=9 <=11', |
|
| 204 | - 'signature' => 'nhlT9lhrmBxIsqh/e3RLm2NDw/U8ZvvoMyYQTLMM3H19DQmVcPYPYC9QWVTsowUzXblVaOXVGylbpKma9yOlOAqJtF3qyXecLl4+tA/Awb6BBhKPgHFdcLDAL5yy1K7/uei3SgEojMlJoI9vEK5I1C5YTh43yNH+//Im6MAuNYFUTlMXK426zdOe6ogpCI5GlYdXopqYANxcpT+WXWET6DDSM5Ev+MYwMcSAY4r8+tvARRU4ZAenRgjkBT6R5z6cD76emRax14tbV6vkjjwRcO+dQtM0tFPbd+5fsNInbauv50VzIMgjA6RnKTOI17gRsSdGlsV4vZn2aIxEPWauu6T/UohMvAE9HMn13vtbpPBSFwJAktj6yHASYGzupNQLprA0+OdyALoLZPpQAKNEXA42a4EVISBKu0EmduHJlUPeqhnIGkkGgVNWS8AWqzP2nFoPdXBgUWateiMcBTHxgEKDac5YmNc9lsXpzf1OxBaXHBhGYKuXPwIfyH3jTWb1OdwixJEuRe9dl63T9qOTRre8QWns/bMqKLibGfMtFhVB21ARJayBuX70eVvabG/2N7Y5t1zUlFygIKu51tvo3AVCRDdRrFWDvkAjxzIz5FIdALVZ+DReFYu/r4WF/w3V9rInFuEDSwb/OH4r8sQycs07tSlMyA74Y3FpjKTBxso=', |
|
| 205 | - 'translations' |
|
| 206 | - => [ |
|
| 207 | - ], |
|
| 208 | - ], |
|
| 209 | - ], |
|
| 210 | - 'screenshots' |
|
| 211 | - => [ |
|
| 212 | - 0 |
|
| 213 | - => [ |
|
| 214 | - 'url' => 'https://bitgrid.net/~jus/apporder-nc.gif', |
|
| 215 | - ], |
|
| 216 | - ], |
|
| 217 | - 'translations' |
|
| 218 | - => [ |
|
| 219 | - 'en' |
|
| 220 | - => [ |
|
| 221 | - 'name' => 'AppOrder', |
|
| 222 | - 'summary' => 'Sort apps in the menu with drag and drop', |
|
| 223 | - 'description' => ' |
|
| 162 | + ], |
|
| 163 | + 1 |
|
| 164 | + => [ |
|
| 165 | + 'id' => 'apporder', |
|
| 166 | + 'categories' |
|
| 167 | + => [ |
|
| 168 | + 0 => 'customization', |
|
| 169 | + ], |
|
| 170 | + 'userDocs' => '', |
|
| 171 | + 'adminDocs' => '', |
|
| 172 | + 'developerDocs' => '', |
|
| 173 | + 'issueTracker' => 'https://github.com/juliushaertl/apporder/issues', |
|
| 174 | + 'website' => '', |
|
| 175 | + 'created' => '2016-10-01T09:16:47.111889Z', |
|
| 176 | + 'lastModified' => '2016-10-12T19:50:16.038821Z', |
|
| 177 | + 'releases' |
|
| 178 | + => [ |
|
| 179 | + 0 |
|
| 180 | + => [ |
|
| 181 | + 'version' => '0.3.3', |
|
| 182 | + 'phpExtensions' |
|
| 183 | + => [ |
|
| 184 | + ], |
|
| 185 | + 'databases' |
|
| 186 | + => [ |
|
| 187 | + ], |
|
| 188 | + 'shellCommands' |
|
| 189 | + => [ |
|
| 190 | + ], |
|
| 191 | + 'phpVersionSpec' => '*', |
|
| 192 | + 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
| 193 | + 'minIntSize' => 32, |
|
| 194 | + 'download' => 'https://github.com/juliushaertl/apporder/releases/download/0.3.3/apporder.tar.gz', |
|
| 195 | + 'created' => '2016-10-12T19:14:10.802359Z', |
|
| 196 | + 'licenses' |
|
| 197 | + => [ |
|
| 198 | + 0 => 'agpl', |
|
| 199 | + ], |
|
| 200 | + 'lastModified' => '2016-10-12T19:50:16.104357Z', |
|
| 201 | + 'isNightly' => false, |
|
| 202 | + 'rawPhpVersionSpec' => '*', |
|
| 203 | + 'rawPlatformVersionSpec' => '>=9 <=11', |
|
| 204 | + 'signature' => 'nhlT9lhrmBxIsqh/e3RLm2NDw/U8ZvvoMyYQTLMM3H19DQmVcPYPYC9QWVTsowUzXblVaOXVGylbpKma9yOlOAqJtF3qyXecLl4+tA/Awb6BBhKPgHFdcLDAL5yy1K7/uei3SgEojMlJoI9vEK5I1C5YTh43yNH+//Im6MAuNYFUTlMXK426zdOe6ogpCI5GlYdXopqYANxcpT+WXWET6DDSM5Ev+MYwMcSAY4r8+tvARRU4ZAenRgjkBT6R5z6cD76emRax14tbV6vkjjwRcO+dQtM0tFPbd+5fsNInbauv50VzIMgjA6RnKTOI17gRsSdGlsV4vZn2aIxEPWauu6T/UohMvAE9HMn13vtbpPBSFwJAktj6yHASYGzupNQLprA0+OdyALoLZPpQAKNEXA42a4EVISBKu0EmduHJlUPeqhnIGkkGgVNWS8AWqzP2nFoPdXBgUWateiMcBTHxgEKDac5YmNc9lsXpzf1OxBaXHBhGYKuXPwIfyH3jTWb1OdwixJEuRe9dl63T9qOTRre8QWns/bMqKLibGfMtFhVB21ARJayBuX70eVvabG/2N7Y5t1zUlFygIKu51tvo3AVCRDdRrFWDvkAjxzIz5FIdALVZ+DReFYu/r4WF/w3V9rInFuEDSwb/OH4r8sQycs07tSlMyA74Y3FpjKTBxso=', |
|
| 205 | + 'translations' |
|
| 206 | + => [ |
|
| 207 | + ], |
|
| 208 | + ], |
|
| 209 | + ], |
|
| 210 | + 'screenshots' |
|
| 211 | + => [ |
|
| 212 | + 0 |
|
| 213 | + => [ |
|
| 214 | + 'url' => 'https://bitgrid.net/~jus/apporder-nc.gif', |
|
| 215 | + ], |
|
| 216 | + ], |
|
| 217 | + 'translations' |
|
| 218 | + => [ |
|
| 219 | + 'en' |
|
| 220 | + => [ |
|
| 221 | + 'name' => 'AppOrder', |
|
| 222 | + 'summary' => 'Sort apps in the menu with drag and drop', |
|
| 223 | + 'description' => ' |
|
| 224 | 224 | Enable sorting for icons inside the app menu. The order will be saved for each |
| 225 | 225 | user individually. Administrators can define a custom default order. |
| 226 | 226 | AppOrder works with the default owncloud menu as well as with the direct_menu |
@@ -240,23 +240,23 @@ discard block |
||
| 240 | 240 | Users will now get redirected to the first app of the default order or to the |
| 241 | 241 | first app of the user order. |
| 242 | 242 | ', |
| 243 | - ], |
|
| 244 | - ], |
|
| 245 | - 'isFeatured' => false, |
|
| 246 | - 'authors' |
|
| 247 | - => [ |
|
| 248 | - 0 |
|
| 249 | - => [ |
|
| 250 | - 'name' => 'Julius Härtl', |
|
| 251 | - 'mail' => '[email protected]', |
|
| 252 | - 'homepage' => '', |
|
| 253 | - ], |
|
| 254 | - ], |
|
| 255 | - 'ratingRecent' => 0.5, |
|
| 256 | - 'ratingOverall' => 0.5, |
|
| 257 | - 'ratingNumRecent' => 0, |
|
| 258 | - 'ratingNumOverall' => 0, |
|
| 259 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 243 | + ], |
|
| 244 | + ], |
|
| 245 | + 'isFeatured' => false, |
|
| 246 | + 'authors' |
|
| 247 | + => [ |
|
| 248 | + 0 |
|
| 249 | + => [ |
|
| 250 | + 'name' => 'Julius Härtl', |
|
| 251 | + 'mail' => '[email protected]', |
|
| 252 | + 'homepage' => '', |
|
| 253 | + ], |
|
| 254 | + ], |
|
| 255 | + 'ratingRecent' => 0.5, |
|
| 256 | + 'ratingOverall' => 0.5, |
|
| 257 | + 'ratingNumRecent' => 0, |
|
| 258 | + 'ratingNumOverall' => 0, |
|
| 259 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 260 | 260 | MIIEAzCCAusCAhAEMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
| 261 | 261 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
| 262 | 262 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -280,49 +280,49 @@ discard block |
||
| 280 | 280 | Tu+WGOL2Ee5U4k4XFdzeSLODWby08iU+Gx3bXTR6WIvXCYeIVsCPKK/luvfGkiSR |
| 281 | 281 | CpW1GUIA1cyulT4uyHf9g6BMdYVOsFQ= |
| 282 | 282 | -----END CERTIFICATE-----', |
| 283 | - ], |
|
| 284 | - 2 |
|
| 285 | - => [ |
|
| 286 | - 'id' => 'twofactor_totp', |
|
| 287 | - 'categories' |
|
| 288 | - => [ |
|
| 289 | - 0 => 'tools', |
|
| 290 | - ], |
|
| 291 | - 'userDocs' => '', |
|
| 292 | - 'adminDocs' => '', |
|
| 293 | - 'developerDocs' => '', |
|
| 294 | - 'issueTracker' => '', |
|
| 295 | - 'website' => '', |
|
| 296 | - 'created' => '2016-10-08T14:13:54.356716Z', |
|
| 297 | - 'lastModified' => '2016-10-12T14:38:56.186269Z', |
|
| 298 | - 'releases' |
|
| 299 | - => [ |
|
| 300 | - 0 |
|
| 301 | - => [ |
|
| 302 | - 'version' => '0.4.1', |
|
| 303 | - 'phpExtensions' |
|
| 304 | - => [ |
|
| 305 | - ], |
|
| 306 | - 'databases' |
|
| 307 | - => [ |
|
| 308 | - ], |
|
| 309 | - 'shellCommands' |
|
| 310 | - => [ |
|
| 311 | - ], |
|
| 312 | - 'phpVersionSpec' => '>=5.4.0 <7.1.0', |
|
| 313 | - 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
| 314 | - 'minIntSize' => 32, |
|
| 315 | - 'download' => 'https://github.com/ChristophWurst/twofactor_totp/releases/download/0.4.1/twofactor_totp.tar.gz', |
|
| 316 | - 'created' => '2016-10-12T14:38:56.174612Z', |
|
| 317 | - 'licenses' |
|
| 318 | - => [ |
|
| 319 | - 0 => 'agpl', |
|
| 320 | - ], |
|
| 321 | - 'lastModified' => '2016-10-12T14:38:56.248223Z', |
|
| 322 | - 'isNightly' => false, |
|
| 323 | - 'rawPhpVersionSpec' => '>=5.4 <=7.0', |
|
| 324 | - 'rawPlatformVersionSpec' => '>=10 <=11', |
|
| 325 | - 'signature' => 'bnwWxmHEn8xkoWbtwhC1kIrJ0dQfAI3PUtU62k+Tru/BHt1G2aVxqO8bCdghojZ7 |
|
| 283 | + ], |
|
| 284 | + 2 |
|
| 285 | + => [ |
|
| 286 | + 'id' => 'twofactor_totp', |
|
| 287 | + 'categories' |
|
| 288 | + => [ |
|
| 289 | + 0 => 'tools', |
|
| 290 | + ], |
|
| 291 | + 'userDocs' => '', |
|
| 292 | + 'adminDocs' => '', |
|
| 293 | + 'developerDocs' => '', |
|
| 294 | + 'issueTracker' => '', |
|
| 295 | + 'website' => '', |
|
| 296 | + 'created' => '2016-10-08T14:13:54.356716Z', |
|
| 297 | + 'lastModified' => '2016-10-12T14:38:56.186269Z', |
|
| 298 | + 'releases' |
|
| 299 | + => [ |
|
| 300 | + 0 |
|
| 301 | + => [ |
|
| 302 | + 'version' => '0.4.1', |
|
| 303 | + 'phpExtensions' |
|
| 304 | + => [ |
|
| 305 | + ], |
|
| 306 | + 'databases' |
|
| 307 | + => [ |
|
| 308 | + ], |
|
| 309 | + 'shellCommands' |
|
| 310 | + => [ |
|
| 311 | + ], |
|
| 312 | + 'phpVersionSpec' => '>=5.4.0 <7.1.0', |
|
| 313 | + 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
| 314 | + 'minIntSize' => 32, |
|
| 315 | + 'download' => 'https://github.com/ChristophWurst/twofactor_totp/releases/download/0.4.1/twofactor_totp.tar.gz', |
|
| 316 | + 'created' => '2016-10-12T14:38:56.174612Z', |
|
| 317 | + 'licenses' |
|
| 318 | + => [ |
|
| 319 | + 0 => 'agpl', |
|
| 320 | + ], |
|
| 321 | + 'lastModified' => '2016-10-12T14:38:56.248223Z', |
|
| 322 | + 'isNightly' => false, |
|
| 323 | + 'rawPhpVersionSpec' => '>=5.4 <=7.0', |
|
| 324 | + 'rawPlatformVersionSpec' => '>=10 <=11', |
|
| 325 | + 'signature' => 'bnwWxmHEn8xkoWbtwhC1kIrJ0dQfAI3PUtU62k+Tru/BHt1G2aVxqO8bCdghojZ7 |
|
| 326 | 326 | zdFMlIJw4kekYFsVfLk8jzjUTZKVbNVKCdkHrVTQ0bUUryMAMLqGQ3PSRI5NX6D5 |
| 327 | 327 | FpkvwO1coYwU0XVWF8KAS0meX0ztSkT3Mv96LLrxr8F8SrB/MGmKIE4WTjt1fAIa |
| 328 | 328 | ZLAVEUo/3sNFTGLYBtL3wjctrkZvJltP8abeRfls9FkRHu+rN7R3uLFzk42uZn3X |
@@ -333,38 +333,38 @@ discard block |
||
| 333 | 333 | 3y+csRqpEJYd9fcVMPsTu7WBRRrpBsAqdAHJcZEwak2kz1kdOgSf8FIzP1z6Q71d |
| 334 | 334 | Ml2RKcPeutMHHSLiGIN/h7fM5aSs49wGgGZmfz28fHVd7/U0HFSMYmkT/GMq5tMP |
| 335 | 335 | Iyc+QZAN4qbX8G0k/QSTkK/L4lOT2hQiQqiSqmWItMk=', |
| 336 | - 'translations' |
|
| 337 | - => [ |
|
| 338 | - ], |
|
| 339 | - ], |
|
| 340 | - ], |
|
| 341 | - 'screenshots' |
|
| 342 | - => [ |
|
| 343 | - ], |
|
| 344 | - 'translations' |
|
| 345 | - => [ |
|
| 346 | - 'en' |
|
| 347 | - => [ |
|
| 348 | - 'name' => 'Two Factor TOTP Provider', |
|
| 349 | - 'summary' => 'A Two-Factor-Auth Provider for TOTP (e.g. Google Authenticator)', |
|
| 350 | - 'description' => 'A Two-Factor-Auth Provider for TOTP (e.g. Google Authenticator)', |
|
| 351 | - ], |
|
| 352 | - ], |
|
| 353 | - 'isFeatured' => true, |
|
| 354 | - 'authors' |
|
| 355 | - => [ |
|
| 356 | - 0 |
|
| 357 | - => [ |
|
| 358 | - 'name' => 'Christoph Wurst', |
|
| 359 | - 'mail' => '', |
|
| 360 | - 'homepage' => '', |
|
| 361 | - ], |
|
| 362 | - ], |
|
| 363 | - 'ratingRecent' => 0.5, |
|
| 364 | - 'ratingOverall' => 0.5, |
|
| 365 | - 'ratingNumRecent' => 0, |
|
| 366 | - 'ratingNumOverall' => 0, |
|
| 367 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 336 | + 'translations' |
|
| 337 | + => [ |
|
| 338 | + ], |
|
| 339 | + ], |
|
| 340 | + ], |
|
| 341 | + 'screenshots' |
|
| 342 | + => [ |
|
| 343 | + ], |
|
| 344 | + 'translations' |
|
| 345 | + => [ |
|
| 346 | + 'en' |
|
| 347 | + => [ |
|
| 348 | + 'name' => 'Two Factor TOTP Provider', |
|
| 349 | + 'summary' => 'A Two-Factor-Auth Provider for TOTP (e.g. Google Authenticator)', |
|
| 350 | + 'description' => 'A Two-Factor-Auth Provider for TOTP (e.g. Google Authenticator)', |
|
| 351 | + ], |
|
| 352 | + ], |
|
| 353 | + 'isFeatured' => true, |
|
| 354 | + 'authors' |
|
| 355 | + => [ |
|
| 356 | + 0 |
|
| 357 | + => [ |
|
| 358 | + 'name' => 'Christoph Wurst', |
|
| 359 | + 'mail' => '', |
|
| 360 | + 'homepage' => '', |
|
| 361 | + ], |
|
| 362 | + ], |
|
| 363 | + 'ratingRecent' => 0.5, |
|
| 364 | + 'ratingOverall' => 0.5, |
|
| 365 | + 'ratingNumRecent' => 0, |
|
| 366 | + 'ratingNumOverall' => 0, |
|
| 367 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 368 | 368 | MIIECTCCAvECAhASMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
| 369 | 369 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
| 370 | 370 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -388,51 +388,51 @@ discard block |
||
| 388 | 388 | VMgQ6yUWNuzOQMZpMIV7RMOUZHvxiX/ZWUFzXNYX0GYub6p4O2uh3LJE+xXyDf77 |
| 389 | 389 | RBO7PLY3m4TXCeKesxZlkoGke+lnq7B8tkADdPI= |
| 390 | 390 | -----END CERTIFICATE-----', |
| 391 | - ], |
|
| 392 | - 3 |
|
| 393 | - => [ |
|
| 394 | - 'id' => 'contacts', |
|
| 395 | - 'categories' |
|
| 396 | - => [ |
|
| 397 | - 0 => 'office', |
|
| 398 | - 1 => 'organization', |
|
| 399 | - 2 => 'social', |
|
| 400 | - ], |
|
| 401 | - 'userDocs' => 'https://docs.nextcloud.com/server/11/user_manual/pim/contacts.html', |
|
| 402 | - 'adminDocs' => 'https://docs.nextcloud.com/server/11/admin_manual/configuration_server/occ_command.html?highlight=occ%20commands#dav-label', |
|
| 403 | - 'developerDocs' => 'https://github.com/nextcloud/contacts#building-the-app', |
|
| 404 | - 'issueTracker' => 'https://github.com/nextcloud/contacts/issues', |
|
| 405 | - 'website' => 'https://github.com/nextcloud/contacts#readme', |
|
| 406 | - 'created' => '2016-10-30T14:00:58.922766Z', |
|
| 407 | - 'lastModified' => '2016-11-22T22:08:01.904319Z', |
|
| 408 | - 'releases' |
|
| 409 | - => [ |
|
| 410 | - 0 |
|
| 411 | - => [ |
|
| 412 | - 'version' => '1.5.0', |
|
| 413 | - 'phpExtensions' |
|
| 414 | - => [ |
|
| 415 | - ], |
|
| 416 | - 'databases' |
|
| 417 | - => [ |
|
| 418 | - ], |
|
| 419 | - 'shellCommands' |
|
| 420 | - => [ |
|
| 421 | - ], |
|
| 422 | - 'phpVersionSpec' => '*', |
|
| 423 | - 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
| 424 | - 'minIntSize' => 32, |
|
| 425 | - 'download' => 'https://github.com/nextcloud/contacts/releases/download/v1.5.0/contacts.tar.gz', |
|
| 426 | - 'created' => '2016-11-22T22:08:01.861942Z', |
|
| 427 | - 'licenses' |
|
| 428 | - => [ |
|
| 429 | - 0 => 'agpl', |
|
| 430 | - ], |
|
| 431 | - 'lastModified' => '2016-11-22T22:08:02.306939Z', |
|
| 432 | - 'isNightly' => false, |
|
| 433 | - 'rawPhpVersionSpec' => '*', |
|
| 434 | - 'rawPlatformVersionSpec' => '>=9 <=11', |
|
| 435 | - 'signature' => 'ZqqhqtbHcNB+rzGCQ7FDIjjvHjit+dhAE1UhFgiXApkx3tmPP4nJOBAGNjHe+2Ao |
|
| 391 | + ], |
|
| 392 | + 3 |
|
| 393 | + => [ |
|
| 394 | + 'id' => 'contacts', |
|
| 395 | + 'categories' |
|
| 396 | + => [ |
|
| 397 | + 0 => 'office', |
|
| 398 | + 1 => 'organization', |
|
| 399 | + 2 => 'social', |
|
| 400 | + ], |
|
| 401 | + 'userDocs' => 'https://docs.nextcloud.com/server/11/user_manual/pim/contacts.html', |
|
| 402 | + 'adminDocs' => 'https://docs.nextcloud.com/server/11/admin_manual/configuration_server/occ_command.html?highlight=occ%20commands#dav-label', |
|
| 403 | + 'developerDocs' => 'https://github.com/nextcloud/contacts#building-the-app', |
|
| 404 | + 'issueTracker' => 'https://github.com/nextcloud/contacts/issues', |
|
| 405 | + 'website' => 'https://github.com/nextcloud/contacts#readme', |
|
| 406 | + 'created' => '2016-10-30T14:00:58.922766Z', |
|
| 407 | + 'lastModified' => '2016-11-22T22:08:01.904319Z', |
|
| 408 | + 'releases' |
|
| 409 | + => [ |
|
| 410 | + 0 |
|
| 411 | + => [ |
|
| 412 | + 'version' => '1.5.0', |
|
| 413 | + 'phpExtensions' |
|
| 414 | + => [ |
|
| 415 | + ], |
|
| 416 | + 'databases' |
|
| 417 | + => [ |
|
| 418 | + ], |
|
| 419 | + 'shellCommands' |
|
| 420 | + => [ |
|
| 421 | + ], |
|
| 422 | + 'phpVersionSpec' => '*', |
|
| 423 | + 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
| 424 | + 'minIntSize' => 32, |
|
| 425 | + 'download' => 'https://github.com/nextcloud/contacts/releases/download/v1.5.0/contacts.tar.gz', |
|
| 426 | + 'created' => '2016-11-22T22:08:01.861942Z', |
|
| 427 | + 'licenses' |
|
| 428 | + => [ |
|
| 429 | + 0 => 'agpl', |
|
| 430 | + ], |
|
| 431 | + 'lastModified' => '2016-11-22T22:08:02.306939Z', |
|
| 432 | + 'isNightly' => false, |
|
| 433 | + 'rawPhpVersionSpec' => '*', |
|
| 434 | + 'rawPlatformVersionSpec' => '>=9 <=11', |
|
| 435 | + 'signature' => 'ZqqhqtbHcNB+rzGCQ7FDIjjvHjit+dhAE1UhFgiXApkx3tmPP4nJOBAGNjHe+2Ao |
|
| 436 | 436 | VcTIX2SrWEfieRrA4Gp+0k7pUPWag1Z0T1OVOwO4cmS1AVFyGIOE1bRvDhMfsWTU |
| 437 | 437 | 4CI4oXaKBFAY6mtnf7VJ7EeIdNqhImkohyWDQ88NiPRLM1XNkJJk6AvZBcT0fvCv |
| 438 | 438 | o145X4dLpbixSXsN99QFNJ/oXvK+9tBGwTd5i/WnNFY90vcNRLia8aRo7SA0YJRx |
@@ -443,54 +443,54 @@ discard block |
||
| 443 | 443 | H3aH8GljatAFjrwItw1JzR0THt0ukkOK+bw/pfCslk10sjHMitmz/GXa4qMS91DZ |
| 444 | 444 | BKLUd0dSfQUQzkfwcojImbzJRvca4/DYe3mfG7+RCH0tDL6t72dKL9joB++u5R1u |
| 445 | 445 | VZPgkToexlXcKWpiDB8H2/SEShKr4udAOjR5de9CYWM=', |
| 446 | - 'translations' |
|
| 447 | - => [ |
|
| 448 | - ], |
|
| 449 | - ], |
|
| 450 | - ], |
|
| 451 | - 'screenshots' |
|
| 452 | - => [ |
|
| 453 | - 0 |
|
| 454 | - => [ |
|
| 455 | - 'url' => 'https://raw.githubusercontent.com/nextcloud/screenshots/master/apps/Contacts/contacts.png', |
|
| 456 | - ], |
|
| 457 | - ], |
|
| 458 | - 'translations' |
|
| 459 | - => [ |
|
| 460 | - 'en' |
|
| 461 | - => [ |
|
| 462 | - 'name' => 'Contacts', |
|
| 463 | - 'summary' => 'The new and improved app for your Contacts.', |
|
| 464 | - 'description' => 'The new and improved app for your Contacts.', |
|
| 465 | - ], |
|
| 466 | - ], |
|
| 467 | - 'isFeatured' => true, |
|
| 468 | - 'authors' |
|
| 469 | - => [ |
|
| 470 | - 0 |
|
| 471 | - => [ |
|
| 472 | - 'name' => 'Alexander Weidinger', |
|
| 473 | - 'mail' => '', |
|
| 474 | - 'homepage' => '', |
|
| 475 | - ], |
|
| 476 | - 1 |
|
| 477 | - => [ |
|
| 478 | - 'name' => 'Jan-Christoph Borchardt', |
|
| 479 | - 'mail' => '', |
|
| 480 | - 'homepage' => '', |
|
| 481 | - ], |
|
| 482 | - 2 |
|
| 483 | - => [ |
|
| 484 | - 'name' => 'Hendrik Leppelsack', |
|
| 485 | - 'mail' => '', |
|
| 486 | - 'homepage' => '', |
|
| 487 | - ], |
|
| 488 | - ], |
|
| 489 | - 'ratingRecent' => 0.5, |
|
| 490 | - 'ratingOverall' => 0.5, |
|
| 491 | - 'ratingNumRecent' => 0, |
|
| 492 | - 'ratingNumOverall' => 0, |
|
| 493 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 446 | + 'translations' |
|
| 447 | + => [ |
|
| 448 | + ], |
|
| 449 | + ], |
|
| 450 | + ], |
|
| 451 | + 'screenshots' |
|
| 452 | + => [ |
|
| 453 | + 0 |
|
| 454 | + => [ |
|
| 455 | + 'url' => 'https://raw.githubusercontent.com/nextcloud/screenshots/master/apps/Contacts/contacts.png', |
|
| 456 | + ], |
|
| 457 | + ], |
|
| 458 | + 'translations' |
|
| 459 | + => [ |
|
| 460 | + 'en' |
|
| 461 | + => [ |
|
| 462 | + 'name' => 'Contacts', |
|
| 463 | + 'summary' => 'The new and improved app for your Contacts.', |
|
| 464 | + 'description' => 'The new and improved app for your Contacts.', |
|
| 465 | + ], |
|
| 466 | + ], |
|
| 467 | + 'isFeatured' => true, |
|
| 468 | + 'authors' |
|
| 469 | + => [ |
|
| 470 | + 0 |
|
| 471 | + => [ |
|
| 472 | + 'name' => 'Alexander Weidinger', |
|
| 473 | + 'mail' => '', |
|
| 474 | + 'homepage' => '', |
|
| 475 | + ], |
|
| 476 | + 1 |
|
| 477 | + => [ |
|
| 478 | + 'name' => 'Jan-Christoph Borchardt', |
|
| 479 | + 'mail' => '', |
|
| 480 | + 'homepage' => '', |
|
| 481 | + ], |
|
| 482 | + 2 |
|
| 483 | + => [ |
|
| 484 | + 'name' => 'Hendrik Leppelsack', |
|
| 485 | + 'mail' => '', |
|
| 486 | + 'homepage' => '', |
|
| 487 | + ], |
|
| 488 | + ], |
|
| 489 | + 'ratingRecent' => 0.5, |
|
| 490 | + 'ratingOverall' => 0.5, |
|
| 491 | + 'ratingNumRecent' => 0, |
|
| 492 | + 'ratingNumOverall' => 0, |
|
| 493 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 494 | 494 | MIIEAzCCAusCAhATMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
| 495 | 495 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
| 496 | 496 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -514,49 +514,49 @@ discard block |
||
| 514 | 514 | Gld7yCP47xNPaAZEC66odcClvNtJ2Clgp8739jD6uJJCqcKDejeef0VU1PG7AXId |
| 515 | 515 | 52bVrGMxJwOuL1393vKxGH0PHDzcB1M= |
| 516 | 516 | -----END CERTIFICATE-----', |
| 517 | - ], |
|
| 518 | - 4 |
|
| 519 | - => [ |
|
| 520 | - 'id' => 'mail', |
|
| 521 | - 'categories' |
|
| 522 | - => [ |
|
| 523 | - 0 => 'tools', |
|
| 524 | - ], |
|
| 525 | - 'userDocs' => '', |
|
| 526 | - 'adminDocs' => 'https://github.com/nextcloud/mail#readme', |
|
| 527 | - 'developerDocs' => '', |
|
| 528 | - 'issueTracker' => '', |
|
| 529 | - 'website' => '', |
|
| 530 | - 'created' => '2016-10-19T19:41:41.710285Z', |
|
| 531 | - 'lastModified' => '2016-10-19T19:57:33.689238Z', |
|
| 532 | - 'releases' |
|
| 533 | - => [ |
|
| 534 | - 0 |
|
| 535 | - => [ |
|
| 536 | - 'version' => '0.6.0', |
|
| 537 | - 'phpExtensions' |
|
| 538 | - => [ |
|
| 539 | - ], |
|
| 540 | - 'databases' |
|
| 541 | - => [ |
|
| 542 | - ], |
|
| 543 | - 'shellCommands' |
|
| 544 | - => [ |
|
| 545 | - ], |
|
| 546 | - 'phpVersionSpec' => '>=5.4.0 <7.1.0', |
|
| 547 | - 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
| 548 | - 'minIntSize' => 32, |
|
| 549 | - 'download' => 'https://github.com/nextcloud/mail/releases/download/v0.6.0/mail.tar.gz', |
|
| 550 | - 'created' => '2016-10-19T19:57:33.676730Z', |
|
| 551 | - 'licenses' |
|
| 552 | - => [ |
|
| 553 | - 0 => 'agpl', |
|
| 554 | - ], |
|
| 555 | - 'lastModified' => '2016-10-19T19:57:33.834580Z', |
|
| 556 | - 'isNightly' => false, |
|
| 557 | - 'rawPhpVersionSpec' => '>=5.4 <=7.0', |
|
| 558 | - 'rawPlatformVersionSpec' => '>=10 <=11', |
|
| 559 | - 'signature' => 'VbMsvDpt+gSPeFM8LrZXEK10rk8kkLlgCcblgqNdCSeGZeVpwDAYv3CccVSLa0+l |
|
| 517 | + ], |
|
| 518 | + 4 |
|
| 519 | + => [ |
|
| 520 | + 'id' => 'mail', |
|
| 521 | + 'categories' |
|
| 522 | + => [ |
|
| 523 | + 0 => 'tools', |
|
| 524 | + ], |
|
| 525 | + 'userDocs' => '', |
|
| 526 | + 'adminDocs' => 'https://github.com/nextcloud/mail#readme', |
|
| 527 | + 'developerDocs' => '', |
|
| 528 | + 'issueTracker' => '', |
|
| 529 | + 'website' => '', |
|
| 530 | + 'created' => '2016-10-19T19:41:41.710285Z', |
|
| 531 | + 'lastModified' => '2016-10-19T19:57:33.689238Z', |
|
| 532 | + 'releases' |
|
| 533 | + => [ |
|
| 534 | + 0 |
|
| 535 | + => [ |
|
| 536 | + 'version' => '0.6.0', |
|
| 537 | + 'phpExtensions' |
|
| 538 | + => [ |
|
| 539 | + ], |
|
| 540 | + 'databases' |
|
| 541 | + => [ |
|
| 542 | + ], |
|
| 543 | + 'shellCommands' |
|
| 544 | + => [ |
|
| 545 | + ], |
|
| 546 | + 'phpVersionSpec' => '>=5.4.0 <7.1.0', |
|
| 547 | + 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
| 548 | + 'minIntSize' => 32, |
|
| 549 | + 'download' => 'https://github.com/nextcloud/mail/releases/download/v0.6.0/mail.tar.gz', |
|
| 550 | + 'created' => '2016-10-19T19:57:33.676730Z', |
|
| 551 | + 'licenses' |
|
| 552 | + => [ |
|
| 553 | + 0 => 'agpl', |
|
| 554 | + ], |
|
| 555 | + 'lastModified' => '2016-10-19T19:57:33.834580Z', |
|
| 556 | + 'isNightly' => false, |
|
| 557 | + 'rawPhpVersionSpec' => '>=5.4 <=7.0', |
|
| 558 | + 'rawPlatformVersionSpec' => '>=10 <=11', |
|
| 559 | + 'signature' => 'VbMsvDpt+gSPeFM8LrZXEK10rk8kkLlgCcblgqNdCSeGZeVpwDAYv3CccVSLa0+l |
|
| 560 | 560 | lTSqQ0VIoH+OIU6vIQNBKHmSCzTplk7OrY0+L5FajXx8LnBaOh892GfGSlEt1neN |
| 561 | 561 | KyM0i0uOjO/xpCP/NoUlgkz6hnmYY5XEdN6DTsJtJ/XZhDQ45IYuIkMkHE/eFehS |
| 562 | 562 | 0JnOagIz+PSipeBY2Ry+tV8YbRa7bC1JAvZzlod0dyI015AHZESeitRUY+MwMWkt |
@@ -567,11 +567,11 @@ discard block |
||
| 567 | 567 | D4c6b+qYn68kx3CLaPPiz+tFAZQZQdj7+Kx/lohso8yTnVSiGYrMj4IvvCbpsQjg |
| 568 | 568 | WF3WSqF/K/tTnPYTWb9NUPSihTbVNv6AXOfTsPEp/ba2YSS5DjvjVjkr5vhR9eg1 |
| 569 | 569 | ikQ3Cw6lW3vaA4LVCC+hFkMRnI4N0bo5qQavP3PnZPc=', |
| 570 | - 'translations' |
|
| 571 | - => [ |
|
| 572 | - 'en' |
|
| 573 | - => [ |
|
| 574 | - 'changelog' => '### Added |
|
| 570 | + 'translations' |
|
| 571 | + => [ |
|
| 572 | + 'en' |
|
| 573 | + => [ |
|
| 574 | + 'changelog' => '### Added |
|
| 575 | 575 | - Alias support |
| 576 | 576 | [#1523](https://github.com/owncloud/mail/pull/1523) @tahaalibra |
| 577 | 577 | - New incoming messages are prefetched |
@@ -604,37 +604,37 @@ discard block |
||
| 604 | 604 | [#1603](https://github.com/owncloud/mail/pull/1603) @ChristophWurst |
| 605 | 605 | - Update folder counters when reading/deleting messages |
| 606 | 606 | [#1585](https://github.com/owncloud/mail/pull/1585)', |
| 607 | - ], |
|
| 608 | - ], |
|
| 609 | - ], |
|
| 610 | - ], |
|
| 611 | - 'screenshots' |
|
| 612 | - => [ |
|
| 613 | - ], |
|
| 614 | - 'translations' |
|
| 615 | - => [ |
|
| 616 | - 'en' |
|
| 617 | - => [ |
|
| 618 | - 'name' => 'Mail', |
|
| 619 | - 'summary' => 'Easy to use email client which connects to your mail server via IMAP and SMTP.', |
|
| 620 | - 'description' => 'Easy to use email client which connects to your mail server via IMAP and SMTP.', |
|
| 621 | - ], |
|
| 622 | - ], |
|
| 623 | - 'isFeatured' => false, |
|
| 624 | - 'authors' |
|
| 625 | - => [ |
|
| 626 | - 0 |
|
| 627 | - => [ |
|
| 628 | - 'name' => 'Christoph Wurst, Thomas Müller, Jan-Christoph Borchardt, Steffen Lindner & many more …', |
|
| 629 | - 'mail' => '', |
|
| 630 | - 'homepage' => '', |
|
| 631 | - ], |
|
| 632 | - ], |
|
| 633 | - 'ratingRecent' => 0.5, |
|
| 634 | - 'ratingOverall' => 0.5, |
|
| 635 | - 'ratingNumRecent' => 0, |
|
| 636 | - 'ratingNumOverall' => 0, |
|
| 637 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 607 | + ], |
|
| 608 | + ], |
|
| 609 | + ], |
|
| 610 | + ], |
|
| 611 | + 'screenshots' |
|
| 612 | + => [ |
|
| 613 | + ], |
|
| 614 | + 'translations' |
|
| 615 | + => [ |
|
| 616 | + 'en' |
|
| 617 | + => [ |
|
| 618 | + 'name' => 'Mail', |
|
| 619 | + 'summary' => 'Easy to use email client which connects to your mail server via IMAP and SMTP.', |
|
| 620 | + 'description' => 'Easy to use email client which connects to your mail server via IMAP and SMTP.', |
|
| 621 | + ], |
|
| 622 | + ], |
|
| 623 | + 'isFeatured' => false, |
|
| 624 | + 'authors' |
|
| 625 | + => [ |
|
| 626 | + 0 |
|
| 627 | + => [ |
|
| 628 | + 'name' => 'Christoph Wurst, Thomas Müller, Jan-Christoph Borchardt, Steffen Lindner & many more …', |
|
| 629 | + 'mail' => '', |
|
| 630 | + 'homepage' => '', |
|
| 631 | + ], |
|
| 632 | + ], |
|
| 633 | + 'ratingRecent' => 0.5, |
|
| 634 | + 'ratingOverall' => 0.5, |
|
| 635 | + 'ratingNumRecent' => 0, |
|
| 636 | + 'ratingNumOverall' => 0, |
|
| 637 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 638 | 638 | MIID/zCCAucCAhAVMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
| 639 | 639 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
| 640 | 640 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -658,99 +658,99 @@ discard block |
||
| 658 | 658 | xRS4JXbapjolkxyGSpP+iYSgItVnYzl6o9KZResR4yDsBv7G/8fpV4GQU9IS3zLD |
| 659 | 659 | PiZOosVHWJdpUKCw9V4P1prGTQ== |
| 660 | 660 | -----END CERTIFICATE-----', |
| 661 | - ], |
|
| 662 | - 5 |
|
| 663 | - => [ |
|
| 664 | - 'id' => 'audioplayer', |
|
| 665 | - 'categories' |
|
| 666 | - => [ |
|
| 667 | - 0 => 'multimedia', |
|
| 668 | - ], |
|
| 669 | - 'userDocs' => 'https://github.com/rello/audioplayer/wiki#user-documentation', |
|
| 670 | - 'adminDocs' => 'https://github.com/rello/audioplayer/wiki#admin-documentation', |
|
| 671 | - 'developerDocs' => '', |
|
| 672 | - 'issueTracker' => 'https://github.com/rello/audioplayer/issues', |
|
| 673 | - 'website' => 'https://github.com/rello/audioplayer', |
|
| 674 | - 'created' => '2016-09-16T05:44:24.857567Z', |
|
| 675 | - 'lastModified' => '2016-11-17T22:34:34.637028Z', |
|
| 676 | - 'releases' |
|
| 677 | - => [ |
|
| 678 | - 0 |
|
| 679 | - => [ |
|
| 680 | - 'version' => '1.3.1', |
|
| 681 | - 'phpExtensions' |
|
| 682 | - => [ |
|
| 683 | - ], |
|
| 684 | - 'databases' |
|
| 685 | - => [ |
|
| 686 | - ], |
|
| 687 | - 'shellCommands' |
|
| 688 | - => [ |
|
| 689 | - ], |
|
| 690 | - 'phpVersionSpec' => '>=5.4.0', |
|
| 691 | - 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
| 692 | - 'minIntSize' => 32, |
|
| 693 | - 'download' => 'https://github.com/Rello/audioplayer/releases/download/1.3.1/audioplayer-1.3.1.tar.gz', |
|
| 694 | - 'created' => '2016-11-17T22:34:34.215350Z', |
|
| 695 | - 'licenses' |
|
| 696 | - => [ |
|
| 697 | - 0 => 'agpl', |
|
| 698 | - ], |
|
| 699 | - 'lastModified' => '2016-11-17T22:34:34.867778Z', |
|
| 700 | - 'isNightly' => false, |
|
| 701 | - 'rawPhpVersionSpec' => '>=5.4', |
|
| 702 | - 'rawPlatformVersionSpec' => '>=9 <=11', |
|
| 703 | - 'signature' => 'p6Zz0IEFrxvw6y/3jHgGWWCxR6qpMzvU2HKfxcIVsK6sJnoRUhWLeAXwZ432fH2a S2llj+IGS9OvW+5VQElrXgPtEjDK1BT00DRJnp5RFCRlUv0LNoedJMzx6B6AHqPP JBufk3cG1O/CO0M0L1ITGSmSOzfKvWTRo3lxVGF792NyBaP/SyZCkH1N1TzBQzUi Ywl3+HiglPcXbHjtJm/arnKorbJWVKoaN93xFuaBapd2ozQSpi0fE0uGRsici+U7 HNa1M5WFE1rzUJoufE0E9246At07rFY1e+TdNEq8IlLgCXg5vGCKkEyuWpWno6aX LfRaIiT9x39UTAwNvuDKS0c+n4uWDYPsGfKhDx9N7CXpUrthfXVEWRzZEXG7as10 6ANvrRPJemSZH8FUSrdJhD7k12qa9R825y7mIG68Li8P71V92EOxFfo9tNXqXwBt VuDGxBqByFVPqSCj5I8hrzJzQl2Xt40g8+8ZcSF96RMg/pM+bwRMTv+mz0V+vQQ4 DWjqnWVPalaJ1PPD5/QFFErtXuNRbyxKZ6BMWxfJlLM9Kz66P75K+8fYaSwz+2KG NxY7I3svzS2K9LGH3fBLUy1t3Hl+c3zGFq/ll1MJrf9NswV4yxt2WmISfM/KDww8 yELkGs2cRzbw2tCvnmYlJJhIqRLkyFAbDzWRH/XdVx4=', |
|
| 704 | - 'translations' |
|
| 705 | - => [ |
|
| 706 | - 'en' |
|
| 707 | - => [ |
|
| 708 | - 'changelog' => '2016-11-17 |
|
| 661 | + ], |
|
| 662 | + 5 |
|
| 663 | + => [ |
|
| 664 | + 'id' => 'audioplayer', |
|
| 665 | + 'categories' |
|
| 666 | + => [ |
|
| 667 | + 0 => 'multimedia', |
|
| 668 | + ], |
|
| 669 | + 'userDocs' => 'https://github.com/rello/audioplayer/wiki#user-documentation', |
|
| 670 | + 'adminDocs' => 'https://github.com/rello/audioplayer/wiki#admin-documentation', |
|
| 671 | + 'developerDocs' => '', |
|
| 672 | + 'issueTracker' => 'https://github.com/rello/audioplayer/issues', |
|
| 673 | + 'website' => 'https://github.com/rello/audioplayer', |
|
| 674 | + 'created' => '2016-09-16T05:44:24.857567Z', |
|
| 675 | + 'lastModified' => '2016-11-17T22:34:34.637028Z', |
|
| 676 | + 'releases' |
|
| 677 | + => [ |
|
| 678 | + 0 |
|
| 679 | + => [ |
|
| 680 | + 'version' => '1.3.1', |
|
| 681 | + 'phpExtensions' |
|
| 682 | + => [ |
|
| 683 | + ], |
|
| 684 | + 'databases' |
|
| 685 | + => [ |
|
| 686 | + ], |
|
| 687 | + 'shellCommands' |
|
| 688 | + => [ |
|
| 689 | + ], |
|
| 690 | + 'phpVersionSpec' => '>=5.4.0', |
|
| 691 | + 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
| 692 | + 'minIntSize' => 32, |
|
| 693 | + 'download' => 'https://github.com/Rello/audioplayer/releases/download/1.3.1/audioplayer-1.3.1.tar.gz', |
|
| 694 | + 'created' => '2016-11-17T22:34:34.215350Z', |
|
| 695 | + 'licenses' |
|
| 696 | + => [ |
|
| 697 | + 0 => 'agpl', |
|
| 698 | + ], |
|
| 699 | + 'lastModified' => '2016-11-17T22:34:34.867778Z', |
|
| 700 | + 'isNightly' => false, |
|
| 701 | + 'rawPhpVersionSpec' => '>=5.4', |
|
| 702 | + 'rawPlatformVersionSpec' => '>=9 <=11', |
|
| 703 | + 'signature' => 'p6Zz0IEFrxvw6y/3jHgGWWCxR6qpMzvU2HKfxcIVsK6sJnoRUhWLeAXwZ432fH2a S2llj+IGS9OvW+5VQElrXgPtEjDK1BT00DRJnp5RFCRlUv0LNoedJMzx6B6AHqPP JBufk3cG1O/CO0M0L1ITGSmSOzfKvWTRo3lxVGF792NyBaP/SyZCkH1N1TzBQzUi Ywl3+HiglPcXbHjtJm/arnKorbJWVKoaN93xFuaBapd2ozQSpi0fE0uGRsici+U7 HNa1M5WFE1rzUJoufE0E9246At07rFY1e+TdNEq8IlLgCXg5vGCKkEyuWpWno6aX LfRaIiT9x39UTAwNvuDKS0c+n4uWDYPsGfKhDx9N7CXpUrthfXVEWRzZEXG7as10 6ANvrRPJemSZH8FUSrdJhD7k12qa9R825y7mIG68Li8P71V92EOxFfo9tNXqXwBt VuDGxBqByFVPqSCj5I8hrzJzQl2Xt40g8+8ZcSF96RMg/pM+bwRMTv+mz0V+vQQ4 DWjqnWVPalaJ1PPD5/QFFErtXuNRbyxKZ6BMWxfJlLM9Kz66P75K+8fYaSwz+2KG NxY7I3svzS2K9LGH3fBLUy1t3Hl+c3zGFq/ll1MJrf9NswV4yxt2WmISfM/KDww8 yELkGs2cRzbw2tCvnmYlJJhIqRLkyFAbDzWRH/XdVx4=', |
|
| 704 | + 'translations' |
|
| 705 | + => [ |
|
| 706 | + 'en' |
|
| 707 | + => [ |
|
| 708 | + 'changelog' => '2016-11-17 |
|
| 709 | 709 | - fix: one-click-play for wav not working |
| 710 | 710 | - fix: wrong sql statement for PostgreSQL [#90](https://github.com/rello/audioplayer/issues/90)', |
| 711 | - ], |
|
| 712 | - ], |
|
| 713 | - ], |
|
| 714 | - ], |
|
| 715 | - 'screenshots' |
|
| 716 | - => [ |
|
| 717 | - 0 |
|
| 718 | - => [ |
|
| 719 | - 'url' => 'https://github.com/rello/screenshots/raw/master/audioplayer_main.png', |
|
| 720 | - ], |
|
| 721 | - 1 |
|
| 722 | - => [ |
|
| 723 | - 'url' => 'https://github.com/rello/screenshots/raw/master/audioplayer_lists.png', |
|
| 724 | - ], |
|
| 725 | - 2 |
|
| 726 | - => [ |
|
| 727 | - 'url' => 'https://github.com/rello/screenshots/raw/master/audioplayer_share.png', |
|
| 728 | - ], |
|
| 729 | - ], |
|
| 730 | - 'translations' |
|
| 731 | - => [ |
|
| 732 | - 'en' |
|
| 733 | - => [ |
|
| 734 | - 'name' => 'Audio Player', |
|
| 735 | - 'summary' => 'Audio Player for ownCloud and Nextcloud', |
|
| 736 | - 'description' => 'Audio Player for MP3, MP4, Ogg, and Wave with a lot of flexibility for all your needs.', |
|
| 737 | - ], |
|
| 738 | - ], |
|
| 739 | - 'isFeatured' => false, |
|
| 740 | - 'authors' |
|
| 741 | - => [ |
|
| 742 | - 0 |
|
| 743 | - => [ |
|
| 744 | - 'name' => 'Marcel Scherello', |
|
| 745 | - 'mail' => '', |
|
| 746 | - 'homepage' => '', |
|
| 747 | - ], |
|
| 748 | - ], |
|
| 749 | - 'ratingRecent' => 0.5, |
|
| 750 | - 'ratingOverall' => 0.5, |
|
| 751 | - 'ratingNumRecent' => 0, |
|
| 752 | - 'ratingNumOverall' => 0, |
|
| 753 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 711 | + ], |
|
| 712 | + ], |
|
| 713 | + ], |
|
| 714 | + ], |
|
| 715 | + 'screenshots' |
|
| 716 | + => [ |
|
| 717 | + 0 |
|
| 718 | + => [ |
|
| 719 | + 'url' => 'https://github.com/rello/screenshots/raw/master/audioplayer_main.png', |
|
| 720 | + ], |
|
| 721 | + 1 |
|
| 722 | + => [ |
|
| 723 | + 'url' => 'https://github.com/rello/screenshots/raw/master/audioplayer_lists.png', |
|
| 724 | + ], |
|
| 725 | + 2 |
|
| 726 | + => [ |
|
| 727 | + 'url' => 'https://github.com/rello/screenshots/raw/master/audioplayer_share.png', |
|
| 728 | + ], |
|
| 729 | + ], |
|
| 730 | + 'translations' |
|
| 731 | + => [ |
|
| 732 | + 'en' |
|
| 733 | + => [ |
|
| 734 | + 'name' => 'Audio Player', |
|
| 735 | + 'summary' => 'Audio Player for ownCloud and Nextcloud', |
|
| 736 | + 'description' => 'Audio Player for MP3, MP4, Ogg, and Wave with a lot of flexibility for all your needs.', |
|
| 737 | + ], |
|
| 738 | + ], |
|
| 739 | + 'isFeatured' => false, |
|
| 740 | + 'authors' |
|
| 741 | + => [ |
|
| 742 | + 0 |
|
| 743 | + => [ |
|
| 744 | + 'name' => 'Marcel Scherello', |
|
| 745 | + 'mail' => '', |
|
| 746 | + 'homepage' => '', |
|
| 747 | + ], |
|
| 748 | + ], |
|
| 749 | + 'ratingRecent' => 0.5, |
|
| 750 | + 'ratingOverall' => 0.5, |
|
| 751 | + 'ratingNumRecent' => 0, |
|
| 752 | + 'ratingNumOverall' => 0, |
|
| 753 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 754 | 754 | MIIEBjCCAu4CAhAIMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
| 755 | 755 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
| 756 | 756 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -774,49 +774,49 @@ discard block |
||
| 774 | 774 | FNvGFVBn4r5qCiChEoq+rCXHRjPi/eCfbW21XeLFDiLxapcZyc85JIcA7znUYoFe |
| 775 | 775 | P7Y/ekMscwWhLbF91OaQlcWpRtEMyde/DaI= |
| 776 | 776 | -----END CERTIFICATE-----', |
| 777 | - ], |
|
| 778 | - 6 |
|
| 779 | - => [ |
|
| 780 | - 'id' => 'calendar', |
|
| 781 | - 'categories' |
|
| 782 | - => [ |
|
| 783 | - 0 => 'organization', |
|
| 784 | - ], |
|
| 785 | - 'userDocs' => 'https://docs.nextcloud.com/server/10/user_manual/pim/calendar.html', |
|
| 786 | - 'adminDocs' => '', |
|
| 787 | - 'developerDocs' => '', |
|
| 788 | - 'issueTracker' => 'https://github.com/nextcloud/calendar/issues', |
|
| 789 | - 'website' => 'https://github.com/nextcloud/calendar/', |
|
| 790 | - 'created' => '2016-10-01T12:40:39.060903Z', |
|
| 791 | - 'lastModified' => '2016-11-22T20:31:13.029921Z', |
|
| 792 | - 'releases' |
|
| 793 | - => [ |
|
| 794 | - 0 |
|
| 795 | - => [ |
|
| 796 | - 'version' => '1.4.1', |
|
| 797 | - 'phpExtensions' |
|
| 798 | - => [ |
|
| 799 | - ], |
|
| 800 | - 'databases' |
|
| 801 | - => [ |
|
| 802 | - ], |
|
| 803 | - 'shellCommands' |
|
| 804 | - => [ |
|
| 805 | - ], |
|
| 806 | - 'phpVersionSpec' => '*', |
|
| 807 | - 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
| 808 | - 'minIntSize' => 32, |
|
| 809 | - 'download' => 'https://github.com/nextcloud/calendar/releases/download/v1.4.1/calendar.tar.gz', |
|
| 810 | - 'created' => '2016-11-22T20:31:13.020268Z', |
|
| 811 | - 'licenses' |
|
| 812 | - => [ |
|
| 813 | - 0 => 'agpl', |
|
| 814 | - ], |
|
| 815 | - 'lastModified' => '2016-11-22T20:31:13.087340Z', |
|
| 816 | - 'isNightly' => false, |
|
| 817 | - 'rawPhpVersionSpec' => '*', |
|
| 818 | - 'rawPlatformVersionSpec' => '>=9 <=11', |
|
| 819 | - 'signature' => 'nThwe9CJBCan9nuDLdhfBiQyPhmum6Aa0UcYsIDdhGMw+C2acf81KhEmBJuTTWxo |
|
| 777 | + ], |
|
| 778 | + 6 |
|
| 779 | + => [ |
|
| 780 | + 'id' => 'calendar', |
|
| 781 | + 'categories' |
|
| 782 | + => [ |
|
| 783 | + 0 => 'organization', |
|
| 784 | + ], |
|
| 785 | + 'userDocs' => 'https://docs.nextcloud.com/server/10/user_manual/pim/calendar.html', |
|
| 786 | + 'adminDocs' => '', |
|
| 787 | + 'developerDocs' => '', |
|
| 788 | + 'issueTracker' => 'https://github.com/nextcloud/calendar/issues', |
|
| 789 | + 'website' => 'https://github.com/nextcloud/calendar/', |
|
| 790 | + 'created' => '2016-10-01T12:40:39.060903Z', |
|
| 791 | + 'lastModified' => '2016-11-22T20:31:13.029921Z', |
|
| 792 | + 'releases' |
|
| 793 | + => [ |
|
| 794 | + 0 |
|
| 795 | + => [ |
|
| 796 | + 'version' => '1.4.1', |
|
| 797 | + 'phpExtensions' |
|
| 798 | + => [ |
|
| 799 | + ], |
|
| 800 | + 'databases' |
|
| 801 | + => [ |
|
| 802 | + ], |
|
| 803 | + 'shellCommands' |
|
| 804 | + => [ |
|
| 805 | + ], |
|
| 806 | + 'phpVersionSpec' => '*', |
|
| 807 | + 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
| 808 | + 'minIntSize' => 32, |
|
| 809 | + 'download' => 'https://github.com/nextcloud/calendar/releases/download/v1.4.1/calendar.tar.gz', |
|
| 810 | + 'created' => '2016-11-22T20:31:13.020268Z', |
|
| 811 | + 'licenses' |
|
| 812 | + => [ |
|
| 813 | + 0 => 'agpl', |
|
| 814 | + ], |
|
| 815 | + 'lastModified' => '2016-11-22T20:31:13.087340Z', |
|
| 816 | + 'isNightly' => false, |
|
| 817 | + 'rawPhpVersionSpec' => '*', |
|
| 818 | + 'rawPlatformVersionSpec' => '>=9 <=11', |
|
| 819 | + 'signature' => 'nThwe9CJBCan9nuDLdhfBiQyPhmum6Aa0UcYsIDdhGMw+C2acf81KhEmBJuTTWxo |
|
| 820 | 820 | WGby6WcrcJJmeuCW+ePU91ju7Pd76RirprhVXIEceIDzSCxin+K0oZCZ1IGVIJjP |
| 821 | 821 | IkVehTsLuCeTBbjvz1b3k5QFyhUhvd32Xt7k5d7VARyI4OqnqYYNBtH9vvgeRrFw |
| 822 | 822 | AxsQr4o4axof6i3iykLg6WfWarYArY4dIuu5DkPuGPWf2bbgjwWEra4sQejhOs7G |
@@ -827,68 +827,68 @@ discard block |
||
| 827 | 827 | eFLKrUg3EvnTjvknbBxMB55h9jNJr0SAlkrmyEVm6+CE3BwRWpKB+cJMBuGiwPwv |
| 828 | 828 | r/ASRiJrkDThbNWAUtX70rUmCqDV6/MujLXViqOc/Q2OHvcXd1oGDccJSQT92/1z |
| 829 | 829 | 7nonnedyYQIDqUt7u68WL8JRxp7pFsEqKLVuWSgxW3c=', |
| 830 | - 'translations' |
|
| 831 | - => [ |
|
| 832 | - ], |
|
| 833 | - ], |
|
| 834 | - ], |
|
| 835 | - 'screenshots' |
|
| 836 | - => [ |
|
| 837 | - 0 |
|
| 838 | - => [ |
|
| 839 | - 'url' => 'https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/1.png', |
|
| 840 | - ], |
|
| 841 | - 1 |
|
| 842 | - => [ |
|
| 843 | - 'url' => 'https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/2.png', |
|
| 844 | - ], |
|
| 845 | - 2 |
|
| 846 | - => [ |
|
| 847 | - 'url' => 'https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/3.png', |
|
| 848 | - ], |
|
| 849 | - 3 |
|
| 850 | - => [ |
|
| 851 | - 'url' => 'https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/4.png', |
|
| 852 | - ], |
|
| 853 | - ], |
|
| 854 | - 'translations' |
|
| 855 | - => [ |
|
| 856 | - 'en' |
|
| 857 | - => [ |
|
| 858 | - 'name' => 'Calendar', |
|
| 859 | - 'summary' => 'Calendar GUI for Nextcloud\'s CalDAV server', |
|
| 860 | - 'description' => 'The Nextcloud calendar app is a user interface for Nextcloud\'s CalDAV server. |
|
| 830 | + 'translations' |
|
| 831 | + => [ |
|
| 832 | + ], |
|
| 833 | + ], |
|
| 834 | + ], |
|
| 835 | + 'screenshots' |
|
| 836 | + => [ |
|
| 837 | + 0 |
|
| 838 | + => [ |
|
| 839 | + 'url' => 'https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/1.png', |
|
| 840 | + ], |
|
| 841 | + 1 |
|
| 842 | + => [ |
|
| 843 | + 'url' => 'https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/2.png', |
|
| 844 | + ], |
|
| 845 | + 2 |
|
| 846 | + => [ |
|
| 847 | + 'url' => 'https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/3.png', |
|
| 848 | + ], |
|
| 849 | + 3 |
|
| 850 | + => [ |
|
| 851 | + 'url' => 'https://raw.githubusercontent.com/nextcloud/calendar/master/screenshots/4.png', |
|
| 852 | + ], |
|
| 853 | + ], |
|
| 854 | + 'translations' |
|
| 855 | + => [ |
|
| 856 | + 'en' |
|
| 857 | + => [ |
|
| 858 | + 'name' => 'Calendar', |
|
| 859 | + 'summary' => 'Calendar GUI for Nextcloud\'s CalDAV server', |
|
| 860 | + 'description' => 'The Nextcloud calendar app is a user interface for Nextcloud\'s CalDAV server. |
|
| 861 | 861 | |
| 862 | 862 | It integrates with other apps, allows you to manage calendars and events, display external calendars and invite attendees to your events', |
| 863 | - ], |
|
| 864 | - ], |
|
| 865 | - 'isFeatured' => true, |
|
| 866 | - 'authors' |
|
| 867 | - => [ |
|
| 868 | - 0 |
|
| 869 | - => [ |
|
| 870 | - 'name' => 'Georg Ehrke', |
|
| 871 | - 'mail' => '', |
|
| 872 | - 'homepage' => 'https://georg.coffee', |
|
| 873 | - ], |
|
| 874 | - 1 |
|
| 875 | - => [ |
|
| 876 | - 'name' => 'Raghu Nayyar', |
|
| 877 | - 'mail' => '', |
|
| 878 | - 'homepage' => 'http://raghunayyar.com', |
|
| 879 | - ], |
|
| 880 | - 2 |
|
| 881 | - => [ |
|
| 882 | - 'name' => 'Thomas Citharel', |
|
| 883 | - 'mail' => '', |
|
| 884 | - 'homepage' => 'https://tcit.fr', |
|
| 885 | - ], |
|
| 886 | - ], |
|
| 887 | - 'ratingRecent' => 0.94444444444444398, |
|
| 888 | - 'ratingOverall' => 0.94444444444444398, |
|
| 889 | - 'ratingNumRecent' => 9, |
|
| 890 | - 'ratingNumOverall' => 9, |
|
| 891 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 863 | + ], |
|
| 864 | + ], |
|
| 865 | + 'isFeatured' => true, |
|
| 866 | + 'authors' |
|
| 867 | + => [ |
|
| 868 | + 0 |
|
| 869 | + => [ |
|
| 870 | + 'name' => 'Georg Ehrke', |
|
| 871 | + 'mail' => '', |
|
| 872 | + 'homepage' => 'https://georg.coffee', |
|
| 873 | + ], |
|
| 874 | + 1 |
|
| 875 | + => [ |
|
| 876 | + 'name' => 'Raghu Nayyar', |
|
| 877 | + 'mail' => '', |
|
| 878 | + 'homepage' => 'http://raghunayyar.com', |
|
| 879 | + ], |
|
| 880 | + 2 |
|
| 881 | + => [ |
|
| 882 | + 'name' => 'Thomas Citharel', |
|
| 883 | + 'mail' => '', |
|
| 884 | + 'homepage' => 'https://tcit.fr', |
|
| 885 | + ], |
|
| 886 | + ], |
|
| 887 | + 'ratingRecent' => 0.94444444444444398, |
|
| 888 | + 'ratingOverall' => 0.94444444444444398, |
|
| 889 | + 'ratingNumRecent' => 9, |
|
| 890 | + 'ratingNumOverall' => 9, |
|
| 891 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 892 | 892 | MIIEAzCCAusCAhARMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
| 893 | 893 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
| 894 | 894 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -912,49 +912,49 @@ discard block |
||
| 912 | 912 | Q0Bl/QinETk72afGR46Qvc7tC1t9JjQQD3AUbEGuJdGvXjJJ9GREYu01XoODmPdT |
| 913 | 913 | jXXOI8XIOK6kxXhPHUc3iWu9b4KqGm0= |
| 914 | 914 | -----END CERTIFICATE-----', |
| 915 | - ], |
|
| 916 | - 8 |
|
| 917 | - => [ |
|
| 918 | - 'id' => 'ownpad', |
|
| 919 | - 'categories' |
|
| 920 | - => [ |
|
| 921 | - 0 => 'tools', |
|
| 922 | - ], |
|
| 923 | - 'userDocs' => 'https://github.com/otetard/ownpad/blob/master/README.md#mimetype-detection', |
|
| 924 | - 'adminDocs' => '', |
|
| 925 | - 'developerDocs' => '', |
|
| 926 | - 'issueTracker' => 'https://github.com/otetard/ownpad/issues', |
|
| 927 | - 'website' => '', |
|
| 928 | - 'created' => '2016-09-29T15:58:52.814912Z', |
|
| 929 | - 'lastModified' => '2016-11-19T17:37:52.278497Z', |
|
| 930 | - 'releases' |
|
| 931 | - => [ |
|
| 932 | - 0 |
|
| 933 | - => [ |
|
| 934 | - 'version' => '0.5.6', |
|
| 935 | - 'phpExtensions' |
|
| 936 | - => [ |
|
| 937 | - ], |
|
| 938 | - 'databases' |
|
| 939 | - => [ |
|
| 940 | - ], |
|
| 941 | - 'shellCommands' |
|
| 942 | - => [ |
|
| 943 | - ], |
|
| 944 | - 'phpVersionSpec' => '*', |
|
| 945 | - 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
| 946 | - 'minIntSize' => 32, |
|
| 947 | - 'download' => 'https://github.com/otetard/ownpad/releases/download/v0.5.6/ownpad.tar.gz', |
|
| 948 | - 'created' => '2016-11-19T17:37:52.234684Z', |
|
| 949 | - 'licenses' |
|
| 950 | - => [ |
|
| 951 | - 0 => 'agpl', |
|
| 952 | - ], |
|
| 953 | - 'lastModified' => '2016-11-19T17:37:52.423930Z', |
|
| 954 | - 'isNightly' => false, |
|
| 955 | - 'rawPhpVersionSpec' => '*', |
|
| 956 | - 'rawPlatformVersionSpec' => '>=9 <=11', |
|
| 957 | - 'signature' => 'dh+Txg1iVfqXr8+cxplNQuBZGErSnXUo0ewGwnybNMJqp8/EjEo72+zPpW3dVnhY |
|
| 915 | + ], |
|
| 916 | + 8 |
|
| 917 | + => [ |
|
| 918 | + 'id' => 'ownpad', |
|
| 919 | + 'categories' |
|
| 920 | + => [ |
|
| 921 | + 0 => 'tools', |
|
| 922 | + ], |
|
| 923 | + 'userDocs' => 'https://github.com/otetard/ownpad/blob/master/README.md#mimetype-detection', |
|
| 924 | + 'adminDocs' => '', |
|
| 925 | + 'developerDocs' => '', |
|
| 926 | + 'issueTracker' => 'https://github.com/otetard/ownpad/issues', |
|
| 927 | + 'website' => '', |
|
| 928 | + 'created' => '2016-09-29T15:58:52.814912Z', |
|
| 929 | + 'lastModified' => '2016-11-19T17:37:52.278497Z', |
|
| 930 | + 'releases' |
|
| 931 | + => [ |
|
| 932 | + 0 |
|
| 933 | + => [ |
|
| 934 | + 'version' => '0.5.6', |
|
| 935 | + 'phpExtensions' |
|
| 936 | + => [ |
|
| 937 | + ], |
|
| 938 | + 'databases' |
|
| 939 | + => [ |
|
| 940 | + ], |
|
| 941 | + 'shellCommands' |
|
| 942 | + => [ |
|
| 943 | + ], |
|
| 944 | + 'phpVersionSpec' => '*', |
|
| 945 | + 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
| 946 | + 'minIntSize' => 32, |
|
| 947 | + 'download' => 'https://github.com/otetard/ownpad/releases/download/v0.5.6/ownpad.tar.gz', |
|
| 948 | + 'created' => '2016-11-19T17:37:52.234684Z', |
|
| 949 | + 'licenses' |
|
| 950 | + => [ |
|
| 951 | + 0 => 'agpl', |
|
| 952 | + ], |
|
| 953 | + 'lastModified' => '2016-11-19T17:37:52.423930Z', |
|
| 954 | + 'isNightly' => false, |
|
| 955 | + 'rawPhpVersionSpec' => '*', |
|
| 956 | + 'rawPlatformVersionSpec' => '>=9 <=11', |
|
| 957 | + 'signature' => 'dh+Txg1iVfqXr8+cxplNQuBZGErSnXUo0ewGwnybNMJqp8/EjEo72+zPpW3dVnhY |
|
| 958 | 958 | 67YCvhrm2bo+VRdFFymEfymzSJu9nWVFkGJhEwvTxPyIdAtuD5YAVrzmnR6L+H7m |
| 959 | 959 | 7Q1nXE63ICPCAQpHkxIfIXLh25OhWeyofBB8AVsjDUNn58FEYJ8fFkr6dCgPriZS |
| 960 | 960 | sM2J+xtZMDYufy+xFMsVf/Q3WopjFuBjMC3qOecW76ZTwtREaswOC2RtpzUku2r1 |
@@ -965,46 +965,46 @@ discard block |
||
| 965 | 965 | o3n0+gw3QYIhLEe75sUhxG6ynVUdW25AKKju1kVj3KJnZTBH1R8t8/zy4DnJG8d4 |
| 966 | 966 | uRGqyU4BXpZjEC3nVlsC7vCncWWhxl0WZQ/MWKqsfjVAU4I88E518D6NioqMnPEJ |
| 967 | 967 | iCZ2x+69UCDEQyfCSKajgAYT17r3OhZei8F9KSCH8Vw=', |
| 968 | - 'translations' |
|
| 969 | - => [ |
|
| 970 | - ], |
|
| 971 | - ], |
|
| 972 | - ], |
|
| 973 | - 'screenshots' |
|
| 974 | - => [ |
|
| 975 | - ], |
|
| 976 | - 'translations' |
|
| 977 | - => [ |
|
| 978 | - 'en' |
|
| 979 | - => [ |
|
| 980 | - 'name' => 'Ownpad', |
|
| 981 | - 'summary' => ' |
|
| 968 | + 'translations' |
|
| 969 | + => [ |
|
| 970 | + ], |
|
| 971 | + ], |
|
| 972 | + ], |
|
| 973 | + 'screenshots' |
|
| 974 | + => [ |
|
| 975 | + ], |
|
| 976 | + 'translations' |
|
| 977 | + => [ |
|
| 978 | + 'en' |
|
| 979 | + => [ |
|
| 980 | + 'name' => 'Ownpad', |
|
| 981 | + 'summary' => ' |
|
| 982 | 982 | Create and open Etherpad and Ethercalc documents. |
| 983 | 983 | ', |
| 984 | - 'description' => ' |
|
| 984 | + 'description' => ' |
|
| 985 | 985 | Ownpad is an ownCloud application that allows to create and open |
| 986 | 986 | Etherpad and Ethercalc documents. |
| 987 | 987 | |
| 988 | 988 | This application requires to have access to an instance of |
| 989 | 989 | Etherpad and/or Ethercalc to work properly. |
| 990 | 990 | ', |
| 991 | - ], |
|
| 992 | - ], |
|
| 993 | - 'isFeatured' => false, |
|
| 994 | - 'authors' |
|
| 995 | - => [ |
|
| 996 | - 0 |
|
| 997 | - => [ |
|
| 998 | - 'name' => 'Olivier Tétard', |
|
| 999 | - 'mail' => '[email protected]', |
|
| 1000 | - 'homepage' => '', |
|
| 1001 | - ], |
|
| 1002 | - ], |
|
| 1003 | - 'ratingRecent' => 0.5, |
|
| 1004 | - 'ratingOverall' => 0.5, |
|
| 1005 | - 'ratingNumRecent' => 0, |
|
| 1006 | - 'ratingNumOverall' => 0, |
|
| 1007 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 991 | + ], |
|
| 992 | + ], |
|
| 993 | + 'isFeatured' => false, |
|
| 994 | + 'authors' |
|
| 995 | + => [ |
|
| 996 | + 0 |
|
| 997 | + => [ |
|
| 998 | + 'name' => 'Olivier Tétard', |
|
| 999 | + 'mail' => '[email protected]', |
|
| 1000 | + 'homepage' => '', |
|
| 1001 | + ], |
|
| 1002 | + ], |
|
| 1003 | + 'ratingRecent' => 0.5, |
|
| 1004 | + 'ratingOverall' => 0.5, |
|
| 1005 | + 'ratingNumRecent' => 0, |
|
| 1006 | + 'ratingNumOverall' => 0, |
|
| 1007 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 1008 | 1008 | MIIEATCCAukCAhAPMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
| 1009 | 1009 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
| 1010 | 1010 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -1028,90 +1028,90 @@ discard block |
||
| 1028 | 1028 | EUa2uYht/z475k4+vf0YhV98iQH07GnmlfD2TDZgmOCQGKlNfJh1v88OZyLLa3dz |
| 1029 | 1029 | gRHzGwKbAiJ8T8bbpZ3e2ozXxADr |
| 1030 | 1030 | -----END CERTIFICATE-----', |
| 1031 | - ], |
|
| 1032 | - 9 |
|
| 1033 | - => [ |
|
| 1034 | - 'id' => 'announcementcenter', |
|
| 1035 | - 'categories' |
|
| 1036 | - => [ |
|
| 1037 | - 0 => 'organization', |
|
| 1038 | - ], |
|
| 1039 | - 'userDocs' => '', |
|
| 1040 | - 'adminDocs' => '', |
|
| 1041 | - 'developerDocs' => '', |
|
| 1042 | - 'issueTracker' => 'https://github.com/nextcloud/announcementcenter/issues', |
|
| 1043 | - 'website' => 'https://github.com/nextcloud/announcementcenter', |
|
| 1044 | - 'created' => '2016-09-14T10:38:53.939634Z', |
|
| 1045 | - 'lastModified' => '2016-11-24T11:21:50.324839Z', |
|
| 1046 | - 'releases' |
|
| 1047 | - => [ |
|
| 1048 | - 0 |
|
| 1049 | - => [ |
|
| 1050 | - 'version' => '2.0.0', |
|
| 1051 | - 'phpExtensions' |
|
| 1052 | - => [ |
|
| 1053 | - ], |
|
| 1054 | - 'databases' |
|
| 1055 | - => [ |
|
| 1056 | - ], |
|
| 1057 | - 'shellCommands' |
|
| 1058 | - => [ |
|
| 1059 | - ], |
|
| 1060 | - 'phpVersionSpec' => '*', |
|
| 1061 | - 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
| 1062 | - 'minIntSize' => 32, |
|
| 1063 | - 'download' => 'https://github.com/nextcloud/announcementcenter/releases/download/v2.0.0/announcementcenter-2.0.0.tar.gz', |
|
| 1064 | - 'created' => '2016-10-06T12:41:56.195206Z', |
|
| 1065 | - 'licenses' |
|
| 1066 | - => [ |
|
| 1067 | - 0 => 'agpl', |
|
| 1068 | - ], |
|
| 1069 | - 'lastModified' => '2016-10-06T12:41:56.263124Z', |
|
| 1070 | - 'isNightly' => false, |
|
| 1071 | - 'rawPhpVersionSpec' => '*', |
|
| 1072 | - 'rawPlatformVersionSpec' => '>=10 <=11', |
|
| 1073 | - 'signature' => 'NVWYz73KtuoZ7ti2sluztJO5aFUc7PzhlDcg0VWyAQd1H7sk5wjw7i0bhrjw8O7M |
|
| 1031 | + ], |
|
| 1032 | + 9 |
|
| 1033 | + => [ |
|
| 1034 | + 'id' => 'announcementcenter', |
|
| 1035 | + 'categories' |
|
| 1036 | + => [ |
|
| 1037 | + 0 => 'organization', |
|
| 1038 | + ], |
|
| 1039 | + 'userDocs' => '', |
|
| 1040 | + 'adminDocs' => '', |
|
| 1041 | + 'developerDocs' => '', |
|
| 1042 | + 'issueTracker' => 'https://github.com/nextcloud/announcementcenter/issues', |
|
| 1043 | + 'website' => 'https://github.com/nextcloud/announcementcenter', |
|
| 1044 | + 'created' => '2016-09-14T10:38:53.939634Z', |
|
| 1045 | + 'lastModified' => '2016-11-24T11:21:50.324839Z', |
|
| 1046 | + 'releases' |
|
| 1047 | + => [ |
|
| 1048 | + 0 |
|
| 1049 | + => [ |
|
| 1050 | + 'version' => '2.0.0', |
|
| 1051 | + 'phpExtensions' |
|
| 1052 | + => [ |
|
| 1053 | + ], |
|
| 1054 | + 'databases' |
|
| 1055 | + => [ |
|
| 1056 | + ], |
|
| 1057 | + 'shellCommands' |
|
| 1058 | + => [ |
|
| 1059 | + ], |
|
| 1060 | + 'phpVersionSpec' => '*', |
|
| 1061 | + 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
| 1062 | + 'minIntSize' => 32, |
|
| 1063 | + 'download' => 'https://github.com/nextcloud/announcementcenter/releases/download/v2.0.0/announcementcenter-2.0.0.tar.gz', |
|
| 1064 | + 'created' => '2016-10-06T12:41:56.195206Z', |
|
| 1065 | + 'licenses' |
|
| 1066 | + => [ |
|
| 1067 | + 0 => 'agpl', |
|
| 1068 | + ], |
|
| 1069 | + 'lastModified' => '2016-10-06T12:41:56.263124Z', |
|
| 1070 | + 'isNightly' => false, |
|
| 1071 | + 'rawPhpVersionSpec' => '*', |
|
| 1072 | + 'rawPlatformVersionSpec' => '>=10 <=11', |
|
| 1073 | + 'signature' => 'NVWYz73KtuoZ7ti2sluztJO5aFUc7PzhlDcg0VWyAQd1H7sk5wjw7i0bhrjw8O7M |
|
| 1074 | 1074 | Lsrb+PegnsL9eMlYM2WrRom+RF1PDP482xymZf1T8vh8qcTCm3TK89xSuiSm8yoA |
| 1075 | 1075 | iWUb/Uv/ODj74wVDWqWxAFKaAG/FestCB3InOOZQqQZLzlAV0U9ziYDGNzBjFqof |
| 1076 | 1076 | 9rLNxJ2IOqZOA7hhMIKhSrpA0KkSfNhBsVf8CWClYnVkZQiq0LoYkHkHIlXmXUr3 |
| 1077 | 1077 | OfQFKEjtsx+bNLa6CkAaocHGHJXAofX3GQZ9cjBsjZqiTfbXfcVk0kRfz7pwL92L |
| 1078 | 1078 | I1McfJYvgMxDQG5bjRpNJw==', |
| 1079 | - 'translations' |
|
| 1080 | - => [ |
|
| 1081 | - ], |
|
| 1082 | - ], |
|
| 1083 | - ], |
|
| 1084 | - 'screenshots' |
|
| 1085 | - => [ |
|
| 1086 | - 0 |
|
| 1087 | - => [ |
|
| 1088 | - 'url' => 'https://github.com/nextcloud/announcementcenter/raw/stable10/docs/AnnouncementCenterFrontpage.png', |
|
| 1089 | - ], |
|
| 1090 | - ], |
|
| 1091 | - 'translations' |
|
| 1092 | - => [ |
|
| 1093 | - 'en' |
|
| 1094 | - => [ |
|
| 1095 | - 'name' => 'Announcement Center', |
|
| 1096 | - 'summary' => 'An announcement center for Nextcloud', |
|
| 1097 | - 'description' => 'An announcement center for Nextcloud', |
|
| 1098 | - ], |
|
| 1099 | - ], |
|
| 1100 | - 'isFeatured' => true, |
|
| 1101 | - 'authors' |
|
| 1102 | - => [ |
|
| 1103 | - 0 |
|
| 1104 | - => [ |
|
| 1105 | - 'name' => 'Joas Schilling', |
|
| 1106 | - 'mail' => '', |
|
| 1107 | - 'homepage' => '', |
|
| 1108 | - ], |
|
| 1109 | - ], |
|
| 1110 | - 'ratingRecent' => 0.75, |
|
| 1111 | - 'ratingOverall' => 0.75, |
|
| 1112 | - 'ratingNumRecent' => 0, |
|
| 1113 | - 'ratingNumOverall' => 0, |
|
| 1114 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 1079 | + 'translations' |
|
| 1080 | + => [ |
|
| 1081 | + ], |
|
| 1082 | + ], |
|
| 1083 | + ], |
|
| 1084 | + 'screenshots' |
|
| 1085 | + => [ |
|
| 1086 | + 0 |
|
| 1087 | + => [ |
|
| 1088 | + 'url' => 'https://github.com/nextcloud/announcementcenter/raw/stable10/docs/AnnouncementCenterFrontpage.png', |
|
| 1089 | + ], |
|
| 1090 | + ], |
|
| 1091 | + 'translations' |
|
| 1092 | + => [ |
|
| 1093 | + 'en' |
|
| 1094 | + => [ |
|
| 1095 | + 'name' => 'Announcement Center', |
|
| 1096 | + 'summary' => 'An announcement center for Nextcloud', |
|
| 1097 | + 'description' => 'An announcement center for Nextcloud', |
|
| 1098 | + ], |
|
| 1099 | + ], |
|
| 1100 | + 'isFeatured' => true, |
|
| 1101 | + 'authors' |
|
| 1102 | + => [ |
|
| 1103 | + 0 |
|
| 1104 | + => [ |
|
| 1105 | + 'name' => 'Joas Schilling', |
|
| 1106 | + 'mail' => '', |
|
| 1107 | + 'homepage' => '', |
|
| 1108 | + ], |
|
| 1109 | + ], |
|
| 1110 | + 'ratingRecent' => 0.75, |
|
| 1111 | + 'ratingOverall' => 0.75, |
|
| 1112 | + 'ratingNumRecent' => 0, |
|
| 1113 | + 'ratingNumOverall' => 0, |
|
| 1114 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 1115 | 1115 | MIIDDTCCAfUCAhABMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
| 1116 | 1116 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
| 1117 | 1117 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -1130,50 +1130,50 @@ discard block |
||
| 1130 | 1130 | JJoU8LQoHwGRtp3wutk0GlFzpEQEvSsn/Lsvvot5IfIe46tnzA6MVj5s64s5G8+Q |
| 1131 | 1131 | phhXFlzXqO/VxquPdbfYjvU= |
| 1132 | 1132 | -----END CERTIFICATE-----', |
| 1133 | - ], |
|
| 1134 | - 11 |
|
| 1135 | - => [ |
|
| 1136 | - 'id' => 'rainloop', |
|
| 1137 | - 'categories' |
|
| 1138 | - => [ |
|
| 1139 | - 0 => 'social', |
|
| 1140 | - 1 => 'tools', |
|
| 1141 | - ], |
|
| 1142 | - 'userDocs' => '', |
|
| 1143 | - 'adminDocs' => '', |
|
| 1144 | - 'developerDocs' => '', |
|
| 1145 | - 'issueTracker' => 'https://github.com/RainLoop/rainloop-webmail/issues', |
|
| 1146 | - 'website' => 'http://www.rainloop.net/', |
|
| 1147 | - 'created' => '2016-10-20T04:17:37.217555Z', |
|
| 1148 | - 'lastModified' => '2016-11-18T11:36:04.309739Z', |
|
| 1149 | - 'releases' |
|
| 1150 | - => [ |
|
| 1151 | - 0 |
|
| 1152 | - => [ |
|
| 1153 | - 'version' => '4.26.0', |
|
| 1154 | - 'phpExtensions' |
|
| 1155 | - => [ |
|
| 1156 | - ], |
|
| 1157 | - 'databases' |
|
| 1158 | - => [ |
|
| 1159 | - ], |
|
| 1160 | - 'shellCommands' |
|
| 1161 | - => [ |
|
| 1162 | - ], |
|
| 1163 | - 'phpVersionSpec' => '>=5.4.0', |
|
| 1164 | - 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
| 1165 | - 'minIntSize' => 32, |
|
| 1166 | - 'download' => 'https://github.com/pierre-alain-b/rainloop-nextcloud/releases/download/v4.26.0/rainloop-4.26.0.tar.gz', |
|
| 1167 | - 'created' => '2016-10-20T04:28:21.491747Z', |
|
| 1168 | - 'licenses' |
|
| 1169 | - => [ |
|
| 1170 | - 0 => 'agpl', |
|
| 1171 | - ], |
|
| 1172 | - 'lastModified' => '2016-11-18T11:36:04.619927Z', |
|
| 1173 | - 'isNightly' => false, |
|
| 1174 | - 'rawPhpVersionSpec' => '>=5.4', |
|
| 1175 | - 'rawPlatformVersionSpec' => '>=10 <=11', |
|
| 1176 | - 'signature' => 'nTYIVSB6mIwKtXIrKoVGsOGFflpLjed8jFem1VLQNtXQj4bztnNrdc4YaPIn0yzM |
|
| 1133 | + ], |
|
| 1134 | + 11 |
|
| 1135 | + => [ |
|
| 1136 | + 'id' => 'rainloop', |
|
| 1137 | + 'categories' |
|
| 1138 | + => [ |
|
| 1139 | + 0 => 'social', |
|
| 1140 | + 1 => 'tools', |
|
| 1141 | + ], |
|
| 1142 | + 'userDocs' => '', |
|
| 1143 | + 'adminDocs' => '', |
|
| 1144 | + 'developerDocs' => '', |
|
| 1145 | + 'issueTracker' => 'https://github.com/RainLoop/rainloop-webmail/issues', |
|
| 1146 | + 'website' => 'http://www.rainloop.net/', |
|
| 1147 | + 'created' => '2016-10-20T04:17:37.217555Z', |
|
| 1148 | + 'lastModified' => '2016-11-18T11:36:04.309739Z', |
|
| 1149 | + 'releases' |
|
| 1150 | + => [ |
|
| 1151 | + 0 |
|
| 1152 | + => [ |
|
| 1153 | + 'version' => '4.26.0', |
|
| 1154 | + 'phpExtensions' |
|
| 1155 | + => [ |
|
| 1156 | + ], |
|
| 1157 | + 'databases' |
|
| 1158 | + => [ |
|
| 1159 | + ], |
|
| 1160 | + 'shellCommands' |
|
| 1161 | + => [ |
|
| 1162 | + ], |
|
| 1163 | + 'phpVersionSpec' => '>=5.4.0', |
|
| 1164 | + 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
| 1165 | + 'minIntSize' => 32, |
|
| 1166 | + 'download' => 'https://github.com/pierre-alain-b/rainloop-nextcloud/releases/download/v4.26.0/rainloop-4.26.0.tar.gz', |
|
| 1167 | + 'created' => '2016-10-20T04:28:21.491747Z', |
|
| 1168 | + 'licenses' |
|
| 1169 | + => [ |
|
| 1170 | + 0 => 'agpl', |
|
| 1171 | + ], |
|
| 1172 | + 'lastModified' => '2016-11-18T11:36:04.619927Z', |
|
| 1173 | + 'isNightly' => false, |
|
| 1174 | + 'rawPhpVersionSpec' => '>=5.4', |
|
| 1175 | + 'rawPlatformVersionSpec' => '>=10 <=11', |
|
| 1176 | + 'signature' => 'nTYIVSB6mIwKtXIrKoVGsOGFflpLjed8jFem1VLQNtXQj4bztnNrdc4YaPIn0yzM |
|
| 1177 | 1177 | yLpMSqRDNzdYNFuOeDiyKLPJPTA++MotLCNjEe7kxUekek+m+qzgnGBdcT7RQT6R |
| 1178 | 1178 | p9xWGecnVx94d6aA55uiRhgQRyHpdDMMLCOz1be+HvpwHy69DRFZ1+SPmGUt6eW0 |
| 1179 | 1179 | u5yS0vHCu1K22cbrVNXFKjxAOlGcIDm61oQuz7ycl3uAujZO4rZbWt55jilgKGak |
@@ -1184,42 +1184,42 @@ discard block |
||
| 1184 | 1184 | LhIczc32ECi3ZVVgyF8zyT4Y/3MRS05oX3FHvHyt88mjni6bVaO78F7ZRSha8gHh |
| 1185 | 1185 | NOAkku7AMXPvUCHaZP2iVCCoAViEso8GeR3O8xh2G42Ai61RLYwx8LB1+23EoJTr |
| 1186 | 1186 | mfFuRYNSg+qAKCokXNnh+lDlwu4AkaQo3vtKGPXvU7A=', |
| 1187 | - 'translations' |
|
| 1188 | - => [ |
|
| 1189 | - ], |
|
| 1190 | - ], |
|
| 1191 | - ], |
|
| 1192 | - 'screenshots' |
|
| 1193 | - => [ |
|
| 1194 | - 0 |
|
| 1195 | - => [ |
|
| 1196 | - 'url' => 'https://raw.githubusercontent.com/pierre-alain-b/rainloop-nextcloud/master/screenshots/2016.10.20-screenshot.jpg', |
|
| 1197 | - ], |
|
| 1198 | - ], |
|
| 1199 | - 'translations' |
|
| 1200 | - => [ |
|
| 1201 | - 'en' |
|
| 1202 | - => [ |
|
| 1203 | - 'name' => 'RainLoop', |
|
| 1204 | - 'summary' => 'RainLoop Webmail', |
|
| 1205 | - 'description' => 'Simple, modern and fast web-based email client.', |
|
| 1206 | - ], |
|
| 1207 | - ], |
|
| 1208 | - 'isFeatured' => false, |
|
| 1209 | - 'authors' |
|
| 1210 | - => [ |
|
| 1211 | - 0 |
|
| 1212 | - => [ |
|
| 1213 | - 'name' => 'RainLoop Team', |
|
| 1214 | - 'mail' => '', |
|
| 1215 | - 'homepage' => '', |
|
| 1216 | - ], |
|
| 1217 | - ], |
|
| 1218 | - 'ratingRecent' => 0.5, |
|
| 1219 | - 'ratingOverall' => 0.5, |
|
| 1220 | - 'ratingNumRecent' => 0, |
|
| 1221 | - 'ratingNumOverall' => 0, |
|
| 1222 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 1187 | + 'translations' |
|
| 1188 | + => [ |
|
| 1189 | + ], |
|
| 1190 | + ], |
|
| 1191 | + ], |
|
| 1192 | + 'screenshots' |
|
| 1193 | + => [ |
|
| 1194 | + 0 |
|
| 1195 | + => [ |
|
| 1196 | + 'url' => 'https://raw.githubusercontent.com/pierre-alain-b/rainloop-nextcloud/master/screenshots/2016.10.20-screenshot.jpg', |
|
| 1197 | + ], |
|
| 1198 | + ], |
|
| 1199 | + 'translations' |
|
| 1200 | + => [ |
|
| 1201 | + 'en' |
|
| 1202 | + => [ |
|
| 1203 | + 'name' => 'RainLoop', |
|
| 1204 | + 'summary' => 'RainLoop Webmail', |
|
| 1205 | + 'description' => 'Simple, modern and fast web-based email client.', |
|
| 1206 | + ], |
|
| 1207 | + ], |
|
| 1208 | + 'isFeatured' => false, |
|
| 1209 | + 'authors' |
|
| 1210 | + => [ |
|
| 1211 | + 0 |
|
| 1212 | + => [ |
|
| 1213 | + 'name' => 'RainLoop Team', |
|
| 1214 | + 'mail' => '', |
|
| 1215 | + 'homepage' => '', |
|
| 1216 | + ], |
|
| 1217 | + ], |
|
| 1218 | + 'ratingRecent' => 0.5, |
|
| 1219 | + 'ratingOverall' => 0.5, |
|
| 1220 | + 'ratingNumRecent' => 0, |
|
| 1221 | + 'ratingNumOverall' => 0, |
|
| 1222 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 1223 | 1223 | MIIEAzCCAusCAhAXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
| 1224 | 1224 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
| 1225 | 1225 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -1243,103 +1243,103 @@ discard block |
||
| 1243 | 1243 | iLYeXQTV0XSRs8xVt+iyGlj7nPkv2DR0oCqRpWUFWeSBI//niDG5WxS3qg8kacSW |
| 1244 | 1244 | fDSYhSN+IjrnIkwNtc8V9t7/GeQB5FE= |
| 1245 | 1245 | -----END CERTIFICATE-----', |
| 1246 | - ], |
|
| 1247 | - 12 |
|
| 1248 | - => [ |
|
| 1249 | - 'id' => 'richdocuments', |
|
| 1250 | - 'categories' |
|
| 1251 | - => [ |
|
| 1252 | - 0 => 'integration', |
|
| 1253 | - 1 => 'office', |
|
| 1254 | - ], |
|
| 1255 | - 'userDocs' => 'https://nextcloud.com/collaboraonline/', |
|
| 1256 | - 'adminDocs' => 'https://nextcloud.com/collaboraonline/', |
|
| 1257 | - 'developerDocs' => '', |
|
| 1258 | - 'issueTracker' => 'https://github.com/owncloud/richdocuments/issues', |
|
| 1259 | - 'website' => '', |
|
| 1260 | - 'created' => '2016-10-31T08:55:45.631429Z', |
|
| 1261 | - 'lastModified' => '2016-11-24T12:13:53.905352Z', |
|
| 1262 | - 'releases' |
|
| 1263 | - => [ |
|
| 1264 | - 0 |
|
| 1265 | - => [ |
|
| 1266 | - 'version' => '1.1.14', |
|
| 1267 | - 'phpExtensions' |
|
| 1268 | - => [ |
|
| 1269 | - ], |
|
| 1270 | - 'databases' |
|
| 1271 | - => [ |
|
| 1272 | - ], |
|
| 1273 | - 'shellCommands' |
|
| 1274 | - => [ |
|
| 1275 | - ], |
|
| 1276 | - 'phpVersionSpec' => '*', |
|
| 1277 | - 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
| 1278 | - 'minIntSize' => 32, |
|
| 1279 | - 'download' => 'https://github.com/owncloud/richdocuments/releases/download/1.1.14/richdocuments.tar.gz', |
|
| 1280 | - 'created' => '2016-11-24T12:10:13.337165Z', |
|
| 1281 | - 'licenses' |
|
| 1282 | - => [ |
|
| 1283 | - 0 => 'agpl', |
|
| 1284 | - ], |
|
| 1285 | - 'lastModified' => '2016-11-24T12:13:53.963638Z', |
|
| 1286 | - 'isNightly' => false, |
|
| 1287 | - 'rawPhpVersionSpec' => '*', |
|
| 1288 | - 'rawPlatformVersionSpec' => '>=9 <=11', |
|
| 1289 | - 'signature' => 'prDGlfRPxqT6LP0BsAFPwGww7P4Bngha2N4u5B6+F02N+RVOjGtTcXKqvM1KjZb1 |
|
| 1246 | + ], |
|
| 1247 | + 12 |
|
| 1248 | + => [ |
|
| 1249 | + 'id' => 'richdocuments', |
|
| 1250 | + 'categories' |
|
| 1251 | + => [ |
|
| 1252 | + 0 => 'integration', |
|
| 1253 | + 1 => 'office', |
|
| 1254 | + ], |
|
| 1255 | + 'userDocs' => 'https://nextcloud.com/collaboraonline/', |
|
| 1256 | + 'adminDocs' => 'https://nextcloud.com/collaboraonline/', |
|
| 1257 | + 'developerDocs' => '', |
|
| 1258 | + 'issueTracker' => 'https://github.com/owncloud/richdocuments/issues', |
|
| 1259 | + 'website' => '', |
|
| 1260 | + 'created' => '2016-10-31T08:55:45.631429Z', |
|
| 1261 | + 'lastModified' => '2016-11-24T12:13:53.905352Z', |
|
| 1262 | + 'releases' |
|
| 1263 | + => [ |
|
| 1264 | + 0 |
|
| 1265 | + => [ |
|
| 1266 | + 'version' => '1.1.14', |
|
| 1267 | + 'phpExtensions' |
|
| 1268 | + => [ |
|
| 1269 | + ], |
|
| 1270 | + 'databases' |
|
| 1271 | + => [ |
|
| 1272 | + ], |
|
| 1273 | + 'shellCommands' |
|
| 1274 | + => [ |
|
| 1275 | + ], |
|
| 1276 | + 'phpVersionSpec' => '*', |
|
| 1277 | + 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
| 1278 | + 'minIntSize' => 32, |
|
| 1279 | + 'download' => 'https://github.com/owncloud/richdocuments/releases/download/1.1.14/richdocuments.tar.gz', |
|
| 1280 | + 'created' => '2016-11-24T12:10:13.337165Z', |
|
| 1281 | + 'licenses' |
|
| 1282 | + => [ |
|
| 1283 | + 0 => 'agpl', |
|
| 1284 | + ], |
|
| 1285 | + 'lastModified' => '2016-11-24T12:13:53.963638Z', |
|
| 1286 | + 'isNightly' => false, |
|
| 1287 | + 'rawPhpVersionSpec' => '*', |
|
| 1288 | + 'rawPlatformVersionSpec' => '>=9 <=11', |
|
| 1289 | + 'signature' => 'prDGlfRPxqT6LP0BsAFPwGww7P4Bngha2N4u5B6+F02N+RVOjGtTcXKqvM1KjZb1 |
|
| 1290 | 1290 | Co7qJvgJmjpvIvDmB+rup02i8ObfwP2ct6UdsD7ouzOWJG2sJANXK31bHyvOmQ2h |
| 1291 | 1291 | vKu5eNcOkf+WFyFKYi51TbsfWn2+1Wge3WWujKAVcEvqtcOOz+uMWNtqzBptEupk |
| 1292 | 1292 | E1aaRnQfTx488YB8Ubul06LIY0PNCHgGCWPgy817tOVT7JA+V0P0FFonl/PXE0dr |
| 1293 | 1293 | WgtxRJmvGaNiFzYq+kQmdKMfayZTm3kdVgP0W52t5wp878K0i4s2KPg5lANvjTz7 |
| 1294 | 1294 | DCT+VV2IGIE52o4RpMUGyQ==', |
| 1295 | - 'translations' |
|
| 1296 | - => [ |
|
| 1297 | - ], |
|
| 1298 | - ], |
|
| 1299 | - ], |
|
| 1300 | - 'screenshots' |
|
| 1301 | - => [ |
|
| 1302 | - 0 |
|
| 1303 | - => [ |
|
| 1304 | - 'url' => 'https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-document.png', |
|
| 1305 | - ], |
|
| 1306 | - 1 |
|
| 1307 | - => [ |
|
| 1308 | - 'url' => 'https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-app.png', |
|
| 1309 | - ], |
|
| 1310 | - 2 |
|
| 1311 | - => [ |
|
| 1312 | - 'url' => 'https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-presentation.png', |
|
| 1313 | - ], |
|
| 1314 | - 3 |
|
| 1315 | - => [ |
|
| 1316 | - 'url' => 'https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-spreadsheet.png', |
|
| 1317 | - ], |
|
| 1318 | - ], |
|
| 1319 | - 'translations' |
|
| 1320 | - => [ |
|
| 1321 | - 'en' |
|
| 1322 | - => [ |
|
| 1323 | - 'name' => 'Collabora Online', |
|
| 1324 | - 'summary' => 'Edit office documents directly in your browser.', |
|
| 1325 | - 'description' => 'Collabora Online allows you to to work with all kinds of office documents directly in your browser. This application requires Collabora Cloudsuite to be installed on one of your servers, please read the documentation to learn more about that.', |
|
| 1326 | - ], |
|
| 1327 | - ], |
|
| 1328 | - 'isFeatured' => false, |
|
| 1329 | - 'authors' |
|
| 1330 | - => [ |
|
| 1331 | - 0 |
|
| 1332 | - => [ |
|
| 1333 | - 'name' => 'Collabora Productivity based on work of Frank Karlitschek, Victor Dubiniuk', |
|
| 1334 | - 'mail' => '', |
|
| 1335 | - 'homepage' => '', |
|
| 1336 | - ], |
|
| 1337 | - ], |
|
| 1338 | - 'ratingRecent' => 0.5, |
|
| 1339 | - 'ratingOverall' => 0.5, |
|
| 1340 | - 'ratingNumRecent' => 0, |
|
| 1341 | - 'ratingNumOverall' => 0, |
|
| 1342 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 1295 | + 'translations' |
|
| 1296 | + => [ |
|
| 1297 | + ], |
|
| 1298 | + ], |
|
| 1299 | + ], |
|
| 1300 | + 'screenshots' |
|
| 1301 | + => [ |
|
| 1302 | + 0 |
|
| 1303 | + => [ |
|
| 1304 | + 'url' => 'https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-document.png', |
|
| 1305 | + ], |
|
| 1306 | + 1 |
|
| 1307 | + => [ |
|
| 1308 | + 'url' => 'https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-app.png', |
|
| 1309 | + ], |
|
| 1310 | + 2 |
|
| 1311 | + => [ |
|
| 1312 | + 'url' => 'https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-presentation.png', |
|
| 1313 | + ], |
|
| 1314 | + 3 |
|
| 1315 | + => [ |
|
| 1316 | + 'url' => 'https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-spreadsheet.png', |
|
| 1317 | + ], |
|
| 1318 | + ], |
|
| 1319 | + 'translations' |
|
| 1320 | + => [ |
|
| 1321 | + 'en' |
|
| 1322 | + => [ |
|
| 1323 | + 'name' => 'Collabora Online', |
|
| 1324 | + 'summary' => 'Edit office documents directly in your browser.', |
|
| 1325 | + 'description' => 'Collabora Online allows you to to work with all kinds of office documents directly in your browser. This application requires Collabora Cloudsuite to be installed on one of your servers, please read the documentation to learn more about that.', |
|
| 1326 | + ], |
|
| 1327 | + ], |
|
| 1328 | + 'isFeatured' => false, |
|
| 1329 | + 'authors' |
|
| 1330 | + => [ |
|
| 1331 | + 0 |
|
| 1332 | + => [ |
|
| 1333 | + 'name' => 'Collabora Productivity based on work of Frank Karlitschek, Victor Dubiniuk', |
|
| 1334 | + 'mail' => '', |
|
| 1335 | + 'homepage' => '', |
|
| 1336 | + ], |
|
| 1337 | + ], |
|
| 1338 | + 'ratingRecent' => 0.5, |
|
| 1339 | + 'ratingOverall' => 0.5, |
|
| 1340 | + 'ratingNumRecent' => 0, |
|
| 1341 | + 'ratingNumOverall' => 0, |
|
| 1342 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 1343 | 1343 | MIIDCDCCAfACAhAZMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
| 1344 | 1344 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
| 1345 | 1345 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -1358,70 +1358,70 @@ discard block |
||
| 1358 | 1358 | myBOrjhrJgLIwvgH26MYZhdiSkFzoE38nMPZdrUmUDxcPCwucWJqgzDPudguFthj |
| 1359 | 1359 | WCVZ3TTG/2z3+tWM |
| 1360 | 1360 | -----END CERTIFICATE-----', |
| 1361 | - ], |
|
| 1362 | - 13 |
|
| 1363 | - => [ |
|
| 1364 | - 'id' => 'ocr', |
|
| 1365 | - 'categories' |
|
| 1366 | - => [ |
|
| 1367 | - 0 => 'files', |
|
| 1368 | - 1 => 'tools', |
|
| 1369 | - ], |
|
| 1370 | - 'userDocs' => 'https://janis91.github.io/ocr/', |
|
| 1371 | - 'adminDocs' => 'https://github.com/janis91/ocr/wiki', |
|
| 1372 | - 'developerDocs' => 'https://github.com/janis91/ocr/wiki', |
|
| 1373 | - 'issueTracker' => 'https://github.com/janis91/ocr/issues', |
|
| 1374 | - 'website' => 'https://janis91.github.io/ocr/', |
|
| 1375 | - 'created' => '2016-09-19T12:07:49.220376Z', |
|
| 1376 | - 'lastModified' => '2016-11-21T11:22:21.024501Z', |
|
| 1377 | - 'releases' |
|
| 1378 | - => [ |
|
| 1379 | - 0 |
|
| 1380 | - => [ |
|
| 1381 | - 'version' => '1.0.0', |
|
| 1382 | - 'phpExtensions' |
|
| 1383 | - => [ |
|
| 1384 | - ], |
|
| 1385 | - 'databases' |
|
| 1386 | - => [ |
|
| 1387 | - 0 |
|
| 1388 | - => [ |
|
| 1389 | - 'id' => 'pgsql', |
|
| 1390 | - 'versionSpec' => '*', |
|
| 1391 | - 'rawVersionSpec' => '*', |
|
| 1392 | - ], |
|
| 1393 | - 1 |
|
| 1394 | - => [ |
|
| 1395 | - 'id' => 'mysql', |
|
| 1396 | - 'versionSpec' => '*', |
|
| 1397 | - 'rawVersionSpec' => '*', |
|
| 1398 | - ], |
|
| 1399 | - 2 |
|
| 1400 | - => [ |
|
| 1401 | - 'id' => 'sqlite', |
|
| 1402 | - 'versionSpec' => '*', |
|
| 1403 | - 'rawVersionSpec' => '*', |
|
| 1404 | - ], |
|
| 1405 | - ], |
|
| 1406 | - 'shellCommands' |
|
| 1407 | - => [ |
|
| 1408 | - 0 => 'ocrmypdf', |
|
| 1409 | - 1 => 'tesseract', |
|
| 1410 | - ], |
|
| 1411 | - 'phpVersionSpec' => '>=5.6.0 <8.0.0', |
|
| 1412 | - 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
| 1413 | - 'minIntSize' => 32, |
|
| 1414 | - 'download' => 'https://github.com/janis91/ocr/releases/download/v1.0.0/ocr.tar.gz', |
|
| 1415 | - 'created' => '2016-10-24T06:50:43.283900Z', |
|
| 1416 | - 'licenses' |
|
| 1417 | - => [ |
|
| 1418 | - 0 => 'agpl', |
|
| 1419 | - ], |
|
| 1420 | - 'lastModified' => '2016-11-21T11:22:21.269108Z', |
|
| 1421 | - 'isNightly' => false, |
|
| 1422 | - 'rawPhpVersionSpec' => '>=5.6 <=7', |
|
| 1423 | - 'rawPlatformVersionSpec' => '>=10 <=11', |
|
| 1424 | - 'signature' => 'CBJkCIiUKyf2NuWfz2zJ3grhf8p7wJes7DPV/OxUzhlxIH0Fh7K54+U5A9JOOi6f |
|
| 1361 | + ], |
|
| 1362 | + 13 |
|
| 1363 | + => [ |
|
| 1364 | + 'id' => 'ocr', |
|
| 1365 | + 'categories' |
|
| 1366 | + => [ |
|
| 1367 | + 0 => 'files', |
|
| 1368 | + 1 => 'tools', |
|
| 1369 | + ], |
|
| 1370 | + 'userDocs' => 'https://janis91.github.io/ocr/', |
|
| 1371 | + 'adminDocs' => 'https://github.com/janis91/ocr/wiki', |
|
| 1372 | + 'developerDocs' => 'https://github.com/janis91/ocr/wiki', |
|
| 1373 | + 'issueTracker' => 'https://github.com/janis91/ocr/issues', |
|
| 1374 | + 'website' => 'https://janis91.github.io/ocr/', |
|
| 1375 | + 'created' => '2016-09-19T12:07:49.220376Z', |
|
| 1376 | + 'lastModified' => '2016-11-21T11:22:21.024501Z', |
|
| 1377 | + 'releases' |
|
| 1378 | + => [ |
|
| 1379 | + 0 |
|
| 1380 | + => [ |
|
| 1381 | + 'version' => '1.0.0', |
|
| 1382 | + 'phpExtensions' |
|
| 1383 | + => [ |
|
| 1384 | + ], |
|
| 1385 | + 'databases' |
|
| 1386 | + => [ |
|
| 1387 | + 0 |
|
| 1388 | + => [ |
|
| 1389 | + 'id' => 'pgsql', |
|
| 1390 | + 'versionSpec' => '*', |
|
| 1391 | + 'rawVersionSpec' => '*', |
|
| 1392 | + ], |
|
| 1393 | + 1 |
|
| 1394 | + => [ |
|
| 1395 | + 'id' => 'mysql', |
|
| 1396 | + 'versionSpec' => '*', |
|
| 1397 | + 'rawVersionSpec' => '*', |
|
| 1398 | + ], |
|
| 1399 | + 2 |
|
| 1400 | + => [ |
|
| 1401 | + 'id' => 'sqlite', |
|
| 1402 | + 'versionSpec' => '*', |
|
| 1403 | + 'rawVersionSpec' => '*', |
|
| 1404 | + ], |
|
| 1405 | + ], |
|
| 1406 | + 'shellCommands' |
|
| 1407 | + => [ |
|
| 1408 | + 0 => 'ocrmypdf', |
|
| 1409 | + 1 => 'tesseract', |
|
| 1410 | + ], |
|
| 1411 | + 'phpVersionSpec' => '>=5.6.0 <8.0.0', |
|
| 1412 | + 'platformVersionSpec' => '>=10.0.0 <12.0.0', |
|
| 1413 | + 'minIntSize' => 32, |
|
| 1414 | + 'download' => 'https://github.com/janis91/ocr/releases/download/v1.0.0/ocr.tar.gz', |
|
| 1415 | + 'created' => '2016-10-24T06:50:43.283900Z', |
|
| 1416 | + 'licenses' |
|
| 1417 | + => [ |
|
| 1418 | + 0 => 'agpl', |
|
| 1419 | + ], |
|
| 1420 | + 'lastModified' => '2016-11-21T11:22:21.269108Z', |
|
| 1421 | + 'isNightly' => false, |
|
| 1422 | + 'rawPhpVersionSpec' => '>=5.6 <=7', |
|
| 1423 | + 'rawPlatformVersionSpec' => '>=10 <=11', |
|
| 1424 | + 'signature' => 'CBJkCIiUKyf2NuWfz2zJ3grhf8p7wJes7DPV/OxUzhlxIH0Fh7K54+U5A9JOOi6f |
|
| 1425 | 1425 | WPhjXG1ylkyIVY1glr/B8svWNsD4jAclpnUi1/9ZW5UPT8LnRBfTbtF9Uoj0OgNs |
| 1426 | 1426 | tsGQYbpuREoHnjbJWTRe0kq1OsOfX44xuf8PuX43B+lpQPW4iRSSz3ZIhdPcDGq1 |
| 1427 | 1427 | 7pyqQM7gdKhBQ6/tOiwd7Enyt5Hi4V6jhwhUOCYeTNiLD2V3yKL+qA9DzpXUfNNw |
@@ -1432,33 +1432,33 @@ discard block |
||
| 1432 | 1432 | D3tJOF7spnK6I3BhVLviou/zs30AIRVBDTU0Orzx78cbInwy6/vyJib2a1olAaHz |
| 1433 | 1433 | v05SzlQRnBWM4jYBe0mA/2ds9AO6VrXGrT/iLlHemj6JYoGBM185TGewA7OJyX3a |
| 1434 | 1434 | HSlSDqaremmi+aS3onx3AKhXykDxTRkMVarePwTzzFs=', |
| 1435 | - 'translations' |
|
| 1436 | - => [ |
|
| 1437 | - ], |
|
| 1438 | - ], |
|
| 1439 | - ], |
|
| 1440 | - 'screenshots' |
|
| 1441 | - => [ |
|
| 1442 | - 0 |
|
| 1443 | - => [ |
|
| 1444 | - 'url' => 'https://raw.githubusercontent.com/janis91/ocr/master/screenshots/sc1.png', |
|
| 1445 | - ], |
|
| 1446 | - 1 |
|
| 1447 | - => [ |
|
| 1448 | - 'url' => 'https://raw.githubusercontent.com/janis91/ocr/master/screenshots/sc2.png', |
|
| 1449 | - ], |
|
| 1450 | - 2 |
|
| 1451 | - => [ |
|
| 1452 | - 'url' => 'https://raw.githubusercontent.com/janis91/ocr/master/screenshots/sc3.png', |
|
| 1453 | - ], |
|
| 1454 | - ], |
|
| 1455 | - 'translations' |
|
| 1456 | - => [ |
|
| 1457 | - 'en' |
|
| 1458 | - => [ |
|
| 1459 | - 'name' => 'OCR', |
|
| 1460 | - 'summary' => 'Character recoginition for your images and pdf files.', |
|
| 1461 | - 'description' => '# Description |
|
| 1435 | + 'translations' |
|
| 1436 | + => [ |
|
| 1437 | + ], |
|
| 1438 | + ], |
|
| 1439 | + ], |
|
| 1440 | + 'screenshots' |
|
| 1441 | + => [ |
|
| 1442 | + 0 |
|
| 1443 | + => [ |
|
| 1444 | + 'url' => 'https://raw.githubusercontent.com/janis91/ocr/master/screenshots/sc1.png', |
|
| 1445 | + ], |
|
| 1446 | + 1 |
|
| 1447 | + => [ |
|
| 1448 | + 'url' => 'https://raw.githubusercontent.com/janis91/ocr/master/screenshots/sc2.png', |
|
| 1449 | + ], |
|
| 1450 | + 2 |
|
| 1451 | + => [ |
|
| 1452 | + 'url' => 'https://raw.githubusercontent.com/janis91/ocr/master/screenshots/sc3.png', |
|
| 1453 | + ], |
|
| 1454 | + ], |
|
| 1455 | + 'translations' |
|
| 1456 | + => [ |
|
| 1457 | + 'en' |
|
| 1458 | + => [ |
|
| 1459 | + 'name' => 'OCR', |
|
| 1460 | + 'summary' => 'Character recoginition for your images and pdf files.', |
|
| 1461 | + 'description' => '# Description |
|
| 1462 | 1462 | |
| 1463 | 1463 | Nextcloud OCR (optical character recoginition) processing for images and PDF with tesseract-ocr and OCRmyPDF brings OCR capability to your Nextcloud 10. |
| 1464 | 1464 | The app uses tesseract-ocr, OCRmyPDF and a php internal message queueing service in order to process images (png, jpeg, tiff) and PDF (currently not all PDF-types are supported, for more information see [here](https://github.com/jbarlow83/OCRmyPDF)) asynchronously and save the output file to the same folder in nextcloud, so you are able to search in it. |
@@ -1476,12 +1476,12 @@ discard block |
||
| 1476 | 1476 | - **[tesseract-ocr](https://github.com/tesseract-ocr/tesseract)** >v3.02.02 with corresponding language files (e.g. tesseract-ocr-eng) |
| 1477 | 1477 | |
| 1478 | 1478 | For further information see the homepage or the appropriate documentation.', |
| 1479 | - ], |
|
| 1480 | - 'de' |
|
| 1481 | - => [ |
|
| 1482 | - 'name' => 'OCR', |
|
| 1483 | - 'summary' => 'Schrifterkennung für Bilder (mit Text) und PDF Dateien.', |
|
| 1484 | - 'description' => '# Beschreibung |
|
| 1479 | + ], |
|
| 1480 | + 'de' |
|
| 1481 | + => [ |
|
| 1482 | + 'name' => 'OCR', |
|
| 1483 | + 'summary' => 'Schrifterkennung für Bilder (mit Text) und PDF Dateien.', |
|
| 1484 | + 'description' => '# Beschreibung |
|
| 1485 | 1485 | |
| 1486 | 1486 | OCR (Automatische Texterkennung) für Bilder (mit Text) und PDF Dateien mithilfe von tesseract-ocr und OCRmyPDF ermöglicht Ihnen automatische Schrifterkennung direkt in Ihrer Nextcloud 10. |
| 1487 | 1487 | Die App nutzt Tesseract-ocr, OCRmyPDF und den internen Message Queueing Service von PHP, um so asynchron (im Hintegrund) Bilder (PNG, JPEG, TIFF) und PDFs (aktuell werden nicht alle Typen unterstützt, näheres [hier](https://github.com/jbarlow83/OCRmyPDF)) zu verarbeiten. Das Ergebnis, welches jetzt durchsuchbar, kopierbar und ähnliches ist, wird anschließend im selben Ordner gespeichert, wie die Ursprungsdatei. |
@@ -1499,23 +1499,23 @@ discard block |
||
| 1499 | 1499 | - **[tesseract-ocr](https://github.com/tesseract-ocr/tesseract)** >v3.02.02 mit den dazugehörigen Übersetzungs- und Sprachdateien (z. B. tesseract-ocr-deu) |
| 1500 | 1500 | |
| 1501 | 1501 | Für weiter Informationen besuchen Sie die Homepage oder lesen Sie die zutreffende Dokumentation.', |
| 1502 | - ], |
|
| 1503 | - ], |
|
| 1504 | - 'isFeatured' => false, |
|
| 1505 | - 'authors' |
|
| 1506 | - => [ |
|
| 1507 | - 0 |
|
| 1508 | - => [ |
|
| 1509 | - 'name' => 'Janis Koehr', |
|
| 1510 | - 'mail' => '', |
|
| 1511 | - 'homepage' => '', |
|
| 1512 | - ], |
|
| 1513 | - ], |
|
| 1514 | - 'ratingRecent' => 0.5, |
|
| 1515 | - 'ratingOverall' => 0.5, |
|
| 1516 | - 'ratingNumRecent' => 0, |
|
| 1517 | - 'ratingNumOverall' => 0, |
|
| 1518 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 1502 | + ], |
|
| 1503 | + ], |
|
| 1504 | + 'isFeatured' => false, |
|
| 1505 | + 'authors' |
|
| 1506 | + => [ |
|
| 1507 | + 0 |
|
| 1508 | + => [ |
|
| 1509 | + 'name' => 'Janis Koehr', |
|
| 1510 | + 'mail' => '', |
|
| 1511 | + 'homepage' => '', |
|
| 1512 | + ], |
|
| 1513 | + ], |
|
| 1514 | + 'ratingRecent' => 0.5, |
|
| 1515 | + 'ratingOverall' => 0.5, |
|
| 1516 | + 'ratingNumRecent' => 0, |
|
| 1517 | + 'ratingNumOverall' => 0, |
|
| 1518 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 1519 | 1519 | MIID/jCCAuYCAhAKMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
| 1520 | 1520 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
| 1521 | 1521 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -1539,49 +1539,49 @@ discard block |
||
| 1539 | 1539 | yA1z/MCBEyTRo80jxFmL+MpwbsdbUJi7Qxlnd56zb6HHDGrLHXZTh9LXgyVbnhWL |
| 1540 | 1540 | kxomWjIXQh4aMHQL4QF7U4EK |
| 1541 | 1541 | -----END CERTIFICATE-----', |
| 1542 | - ], |
|
| 1543 | - 14 |
|
| 1544 | - => [ |
|
| 1545 | - 'id' => 'spreedme', |
|
| 1546 | - 'categories' |
|
| 1547 | - => [ |
|
| 1548 | - 0 => 'tools', |
|
| 1549 | - ], |
|
| 1550 | - 'userDocs' => 'https://github.com/strukturag/nextcloud-spreedme/blob/master/README.md', |
|
| 1551 | - 'adminDocs' => 'https://github.com/strukturag/nextcloud-spreedme/blob/master/README.md', |
|
| 1552 | - 'developerDocs' => '', |
|
| 1553 | - 'issueTracker' => 'https://github.com/strukturag/nextcloud-spreedme/issues', |
|
| 1554 | - 'website' => '', |
|
| 1555 | - 'created' => '2016-09-27T08:43:07.835196Z', |
|
| 1556 | - 'lastModified' => '2016-11-21T16:51:23.703819Z', |
|
| 1557 | - 'releases' |
|
| 1558 | - => [ |
|
| 1559 | - 0 |
|
| 1560 | - => [ |
|
| 1561 | - 'version' => '0.3.4', |
|
| 1562 | - 'phpExtensions' |
|
| 1563 | - => [ |
|
| 1564 | - ], |
|
| 1565 | - 'databases' |
|
| 1566 | - => [ |
|
| 1567 | - ], |
|
| 1568 | - 'shellCommands' |
|
| 1569 | - => [ |
|
| 1570 | - ], |
|
| 1571 | - 'phpVersionSpec' => '*', |
|
| 1572 | - 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
| 1573 | - 'minIntSize' => 32, |
|
| 1574 | - 'download' => 'https://apps.owncloud.com/CONTENT/content-files/174436-spreedme.tar.gz', |
|
| 1575 | - 'created' => '2016-11-21T16:51:23.689599Z', |
|
| 1576 | - 'licenses' |
|
| 1577 | - => [ |
|
| 1578 | - 0 => 'agpl', |
|
| 1579 | - ], |
|
| 1580 | - 'lastModified' => '2016-11-21T16:51:23.826509Z', |
|
| 1581 | - 'isNightly' => false, |
|
| 1582 | - 'rawPhpVersionSpec' => '*', |
|
| 1583 | - 'rawPlatformVersionSpec' => '>=9 <=11', |
|
| 1584 | - 'signature' => 'Mhy3hXeGWlIujx1Op39MMRdqHYOo360BCwr4FPWoTNNggH3aS0gWlh48DAfGYK9W |
|
| 1542 | + ], |
|
| 1543 | + 14 |
|
| 1544 | + => [ |
|
| 1545 | + 'id' => 'spreedme', |
|
| 1546 | + 'categories' |
|
| 1547 | + => [ |
|
| 1548 | + 0 => 'tools', |
|
| 1549 | + ], |
|
| 1550 | + 'userDocs' => 'https://github.com/strukturag/nextcloud-spreedme/blob/master/README.md', |
|
| 1551 | + 'adminDocs' => 'https://github.com/strukturag/nextcloud-spreedme/blob/master/README.md', |
|
| 1552 | + 'developerDocs' => '', |
|
| 1553 | + 'issueTracker' => 'https://github.com/strukturag/nextcloud-spreedme/issues', |
|
| 1554 | + 'website' => '', |
|
| 1555 | + 'created' => '2016-09-27T08:43:07.835196Z', |
|
| 1556 | + 'lastModified' => '2016-11-21T16:51:23.703819Z', |
|
| 1557 | + 'releases' |
|
| 1558 | + => [ |
|
| 1559 | + 0 |
|
| 1560 | + => [ |
|
| 1561 | + 'version' => '0.3.4', |
|
| 1562 | + 'phpExtensions' |
|
| 1563 | + => [ |
|
| 1564 | + ], |
|
| 1565 | + 'databases' |
|
| 1566 | + => [ |
|
| 1567 | + ], |
|
| 1568 | + 'shellCommands' |
|
| 1569 | + => [ |
|
| 1570 | + ], |
|
| 1571 | + 'phpVersionSpec' => '*', |
|
| 1572 | + 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
| 1573 | + 'minIntSize' => 32, |
|
| 1574 | + 'download' => 'https://apps.owncloud.com/CONTENT/content-files/174436-spreedme.tar.gz', |
|
| 1575 | + 'created' => '2016-11-21T16:51:23.689599Z', |
|
| 1576 | + 'licenses' |
|
| 1577 | + => [ |
|
| 1578 | + 0 => 'agpl', |
|
| 1579 | + ], |
|
| 1580 | + 'lastModified' => '2016-11-21T16:51:23.826509Z', |
|
| 1581 | + 'isNightly' => false, |
|
| 1582 | + 'rawPhpVersionSpec' => '*', |
|
| 1583 | + 'rawPlatformVersionSpec' => '>=9 <=11', |
|
| 1584 | + 'signature' => 'Mhy3hXeGWlIujx1Op39MMRdqHYOo360BCwr4FPWoTNNggH3aS0gWlh48DAfGYK9W |
|
| 1585 | 1585 | etNiOqIuRyA0NrVlsqR2vDILgFtODJSbKPyHd3PQn3hcGsjogjQ+dkKciLNLinw7 |
| 1586 | 1586 | Ohbv6aDdRFLBeRHpX/7wOnWL5W3ko/gyn0Awvi88M9+nC5aARtqncQqPy2SxDGzH |
| 1587 | 1587 | KlOZHSNDnEQCGMhA8hNWWKdVwNUJHod/wmBWpW5QVNSJq5DqrKZcNwpGM2UUJoql |
@@ -1592,54 +1592,54 @@ discard block |
||
| 1592 | 1592 | 2Y28qLxwHVaINDFUUxD75WWdrlulRbqHwiSw8jolP9qrpXhDuLAqYam9tRwV5K5R |
| 1593 | 1593 | 8uNawnFwWkicBEYkN/WtBTouWzehOPn38tHXov6SyEyD6lkuxUBZrsGQ2ru+t33U |
| 1594 | 1594 | k0kKCbV0GFw43I+3Ji5DiB4TUVNZYVoPG1B7Qve+UfA=', |
| 1595 | - 'translations' |
|
| 1596 | - => [ |
|
| 1597 | - ], |
|
| 1598 | - ], |
|
| 1599 | - ], |
|
| 1600 | - 'screenshots' |
|
| 1601 | - => [ |
|
| 1602 | - 0 |
|
| 1603 | - => [ |
|
| 1604 | - 'url' => 'https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/conference.gif', |
|
| 1605 | - ], |
|
| 1606 | - 1 |
|
| 1607 | - => [ |
|
| 1608 | - 'url' => 'https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/presentation.png', |
|
| 1609 | - ], |
|
| 1610 | - 2 |
|
| 1611 | - => [ |
|
| 1612 | - 'url' => 'https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/import.png', |
|
| 1613 | - ], |
|
| 1614 | - 3 |
|
| 1615 | - => [ |
|
| 1616 | - 'url' => 'https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/users.png', |
|
| 1617 | - ], |
|
| 1618 | - ], |
|
| 1619 | - 'translations' |
|
| 1620 | - => [ |
|
| 1621 | - 'en' |
|
| 1622 | - => [ |
|
| 1623 | - 'name' => 'Spreed.ME', |
|
| 1624 | - 'summary' => 'Audio-, video- and text chat for your Nextcloud', |
|
| 1625 | - 'description' => 'Securely communicate with your friends and family using rich audio-, video- and text chat, and much more right from your Nextcloud – in your browser', |
|
| 1626 | - ], |
|
| 1627 | - ], |
|
| 1628 | - 'isFeatured' => false, |
|
| 1629 | - 'authors' |
|
| 1630 | - => [ |
|
| 1631 | - 0 |
|
| 1632 | - => [ |
|
| 1633 | - 'name' => 'struktur AG', |
|
| 1634 | - 'mail' => '', |
|
| 1635 | - 'homepage' => '', |
|
| 1636 | - ], |
|
| 1637 | - ], |
|
| 1638 | - 'ratingRecent' => 0.5, |
|
| 1639 | - 'ratingOverall' => 0.5, |
|
| 1640 | - 'ratingNumRecent' => 0, |
|
| 1641 | - 'ratingNumOverall' => 0, |
|
| 1642 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 1595 | + 'translations' |
|
| 1596 | + => [ |
|
| 1597 | + ], |
|
| 1598 | + ], |
|
| 1599 | + ], |
|
| 1600 | + 'screenshots' |
|
| 1601 | + => [ |
|
| 1602 | + 0 |
|
| 1603 | + => [ |
|
| 1604 | + 'url' => 'https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/conference.gif', |
|
| 1605 | + ], |
|
| 1606 | + 1 |
|
| 1607 | + => [ |
|
| 1608 | + 'url' => 'https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/presentation.png', |
|
| 1609 | + ], |
|
| 1610 | + 2 |
|
| 1611 | + => [ |
|
| 1612 | + 'url' => 'https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/import.png', |
|
| 1613 | + ], |
|
| 1614 | + 3 |
|
| 1615 | + => [ |
|
| 1616 | + 'url' => 'https://raw.githubusercontent.com/strukturag/nextcloud-spreedme/master/screenshots/appstore/users.png', |
|
| 1617 | + ], |
|
| 1618 | + ], |
|
| 1619 | + 'translations' |
|
| 1620 | + => [ |
|
| 1621 | + 'en' |
|
| 1622 | + => [ |
|
| 1623 | + 'name' => 'Spreed.ME', |
|
| 1624 | + 'summary' => 'Audio-, video- and text chat for your Nextcloud', |
|
| 1625 | + 'description' => 'Securely communicate with your friends and family using rich audio-, video- and text chat, and much more right from your Nextcloud – in your browser', |
|
| 1626 | + ], |
|
| 1627 | + ], |
|
| 1628 | + 'isFeatured' => false, |
|
| 1629 | + 'authors' |
|
| 1630 | + => [ |
|
| 1631 | + 0 |
|
| 1632 | + => [ |
|
| 1633 | + 'name' => 'struktur AG', |
|
| 1634 | + 'mail' => '', |
|
| 1635 | + 'homepage' => '', |
|
| 1636 | + ], |
|
| 1637 | + ], |
|
| 1638 | + 'ratingRecent' => 0.5, |
|
| 1639 | + 'ratingOverall' => 0.5, |
|
| 1640 | + 'ratingNumRecent' => 0, |
|
| 1641 | + 'ratingNumOverall' => 0, |
|
| 1642 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 1643 | 1643 | MIIEAzCCAusCAhANMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
| 1644 | 1644 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
| 1645 | 1645 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -1663,50 +1663,50 @@ discard block |
||
| 1663 | 1663 | sUNUEU2Decyp0jxLVnrrpz6Y5UupfBR0V8yAv1t5Od/mCKLc5DxHsDWiKOpsob9U |
| 1664 | 1664 | JN+bdzJil2NNftihD4Dm7Ha7OS3O8W0= |
| 1665 | 1665 | -----END CERTIFICATE-----', |
| 1666 | - ], |
|
| 1667 | - 15 |
|
| 1668 | - => [ |
|
| 1669 | - 'id' => 'nextant', |
|
| 1670 | - 'categories' |
|
| 1671 | - => [ |
|
| 1672 | - 0 => 'files', |
|
| 1673 | - 1 => 'tools', |
|
| 1674 | - ], |
|
| 1675 | - 'userDocs' => '', |
|
| 1676 | - 'adminDocs' => 'https://github.com/nextcloud/nextant/wiki', |
|
| 1677 | - 'developerDocs' => '', |
|
| 1678 | - 'issueTracker' => 'https://github.com/nextcloud/nextant/issues', |
|
| 1679 | - 'website' => 'https://github.com/nextcloud/nextant/wiki', |
|
| 1680 | - 'created' => '2016-09-14T14:34:35.977699Z', |
|
| 1681 | - 'lastModified' => '2016-11-22T16:02:57.758477Z', |
|
| 1682 | - 'releases' |
|
| 1683 | - => [ |
|
| 1684 | - 0 |
|
| 1685 | - => [ |
|
| 1686 | - 'version' => '0.6.6', |
|
| 1687 | - 'phpExtensions' |
|
| 1688 | - => [ |
|
| 1689 | - ], |
|
| 1690 | - 'databases' |
|
| 1691 | - => [ |
|
| 1692 | - ], |
|
| 1693 | - 'shellCommands' |
|
| 1694 | - => [ |
|
| 1695 | - ], |
|
| 1696 | - 'phpVersionSpec' => '*', |
|
| 1697 | - 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
| 1698 | - 'minIntSize' => 32, |
|
| 1699 | - 'download' => 'https://github.com/nextcloud/nextant/releases/download/v0.6.6/nextant-0.6.6.tar.gz', |
|
| 1700 | - 'created' => '2016-11-16T15:11:14.344704Z', |
|
| 1701 | - 'licenses' |
|
| 1702 | - => [ |
|
| 1703 | - 0 => 'agpl', |
|
| 1704 | - ], |
|
| 1705 | - 'lastModified' => '2016-11-16T20:39:59.030384Z', |
|
| 1706 | - 'isNightly' => false, |
|
| 1707 | - 'rawPhpVersionSpec' => '*', |
|
| 1708 | - 'rawPlatformVersionSpec' => '>=9 <=11', |
|
| 1709 | - 'signature' => 'aOZeEeThyZ0V/vXBcn6c+Z0vyCsZcN6nfSJ8oWEea4zXh4g705Si+MFZESqix3M2 |
|
| 1666 | + ], |
|
| 1667 | + 15 |
|
| 1668 | + => [ |
|
| 1669 | + 'id' => 'nextant', |
|
| 1670 | + 'categories' |
|
| 1671 | + => [ |
|
| 1672 | + 0 => 'files', |
|
| 1673 | + 1 => 'tools', |
|
| 1674 | + ], |
|
| 1675 | + 'userDocs' => '', |
|
| 1676 | + 'adminDocs' => 'https://github.com/nextcloud/nextant/wiki', |
|
| 1677 | + 'developerDocs' => '', |
|
| 1678 | + 'issueTracker' => 'https://github.com/nextcloud/nextant/issues', |
|
| 1679 | + 'website' => 'https://github.com/nextcloud/nextant/wiki', |
|
| 1680 | + 'created' => '2016-09-14T14:34:35.977699Z', |
|
| 1681 | + 'lastModified' => '2016-11-22T16:02:57.758477Z', |
|
| 1682 | + 'releases' |
|
| 1683 | + => [ |
|
| 1684 | + 0 |
|
| 1685 | + => [ |
|
| 1686 | + 'version' => '0.6.6', |
|
| 1687 | + 'phpExtensions' |
|
| 1688 | + => [ |
|
| 1689 | + ], |
|
| 1690 | + 'databases' |
|
| 1691 | + => [ |
|
| 1692 | + ], |
|
| 1693 | + 'shellCommands' |
|
| 1694 | + => [ |
|
| 1695 | + ], |
|
| 1696 | + 'phpVersionSpec' => '*', |
|
| 1697 | + 'platformVersionSpec' => '>=9.0.0 <12.0.0', |
|
| 1698 | + 'minIntSize' => 32, |
|
| 1699 | + 'download' => 'https://github.com/nextcloud/nextant/releases/download/v0.6.6/nextant-0.6.6.tar.gz', |
|
| 1700 | + 'created' => '2016-11-16T15:11:14.344704Z', |
|
| 1701 | + 'licenses' |
|
| 1702 | + => [ |
|
| 1703 | + 0 => 'agpl', |
|
| 1704 | + ], |
|
| 1705 | + 'lastModified' => '2016-11-16T20:39:59.030384Z', |
|
| 1706 | + 'isNightly' => false, |
|
| 1707 | + 'rawPhpVersionSpec' => '*', |
|
| 1708 | + 'rawPlatformVersionSpec' => '>=9 <=11', |
|
| 1709 | + 'signature' => 'aOZeEeThyZ0V/vXBcn6c+Z0vyCsZcN6nfSJ8oWEea4zXh4g705Si+MFZESqix3M2 |
|
| 1710 | 1710 | OPCnA/U8eASwdRTAEwQJrW5ECmu1THXSIsrzQzc9kFycvyOGzCgAWtuu0ayzZD2/ |
| 1711 | 1711 | U5aDWlzpLHC1Czg9QJ5UnfZR0AfChWQ402N1YzGqMShdJv6AHXFrVE+uYnIyxuYI |
| 1712 | 1712 | oPJQBUYbQwthVUjpYwFwSxw50YU17gmx5RZ0Y0OPz3i/EiuEUrxopXtfDVYAuCML |
@@ -1717,29 +1717,29 @@ discard block |
||
| 1717 | 1717 | 9P3iPd2hQ6yOM9fG21LVN74b6wggI81BzFf/xJPd4ZqYLjfeG/yqd0zaiMOzMm1W |
| 1718 | 1718 | se+kc/a4iB3BoCNX3E942pBBzew4ya8LkCXdCHUUsuelDf1va1ikTh/G7D84ll9/ |
| 1719 | 1719 | 2avNqQnUh3hgOnxFCLI/5VrbqxfSTVdO6O/LTuAmwgw=', |
| 1720 | - 'translations' |
|
| 1721 | - => [ |
|
| 1722 | - ], |
|
| 1723 | - ], |
|
| 1724 | - ], |
|
| 1725 | - 'screenshots' |
|
| 1726 | - => [ |
|
| 1727 | - 0 |
|
| 1728 | - => [ |
|
| 1729 | - 'url' => 'https://raw.githubusercontent.com/nextcloud/nextant/master/screenshots/displayResult.jpg', |
|
| 1730 | - ], |
|
| 1731 | - 1 |
|
| 1732 | - => [ |
|
| 1733 | - 'url' => 'https://raw.githubusercontent.com/nextcloud/nextant/master/screenshots/admin.jpg', |
|
| 1734 | - ], |
|
| 1735 | - ], |
|
| 1736 | - 'translations' |
|
| 1737 | - => [ |
|
| 1738 | - 'en' |
|
| 1739 | - => [ |
|
| 1740 | - 'name' => 'Nextant', |
|
| 1741 | - 'summary' => 'Navigate through your cloud using Solr', |
|
| 1742 | - 'description' => ' |
|
| 1720 | + 'translations' |
|
| 1721 | + => [ |
|
| 1722 | + ], |
|
| 1723 | + ], |
|
| 1724 | + ], |
|
| 1725 | + 'screenshots' |
|
| 1726 | + => [ |
|
| 1727 | + 0 |
|
| 1728 | + => [ |
|
| 1729 | + 'url' => 'https://raw.githubusercontent.com/nextcloud/nextant/master/screenshots/displayResult.jpg', |
|
| 1730 | + ], |
|
| 1731 | + 1 |
|
| 1732 | + => [ |
|
| 1733 | + 'url' => 'https://raw.githubusercontent.com/nextcloud/nextant/master/screenshots/admin.jpg', |
|
| 1734 | + ], |
|
| 1735 | + ], |
|
| 1736 | + 'translations' |
|
| 1737 | + => [ |
|
| 1738 | + 'en' |
|
| 1739 | + => [ |
|
| 1740 | + 'name' => 'Nextant', |
|
| 1741 | + 'summary' => 'Navigate through your cloud using Solr', |
|
| 1742 | + 'description' => ' |
|
| 1743 | 1743 | Navigate through your cloud using Solr |
| 1744 | 1744 | |
| 1745 | 1745 | |
@@ -1775,23 +1775,23 @@ discard block |
||
| 1775 | 1775 | |
| 1776 | 1776 | |
| 1777 | 1777 | ', |
| 1778 | - ], |
|
| 1779 | - ], |
|
| 1780 | - 'isFeatured' => false, |
|
| 1781 | - 'authors' |
|
| 1782 | - => [ |
|
| 1783 | - 0 |
|
| 1784 | - => [ |
|
| 1785 | - 'name' => 'Maxence Lange', |
|
| 1786 | - 'mail' => '', |
|
| 1787 | - 'homepage' => '', |
|
| 1788 | - ], |
|
| 1789 | - ], |
|
| 1790 | - 'ratingRecent' => 0.5, |
|
| 1791 | - 'ratingOverall' => 0.5, |
|
| 1792 | - 'ratingNumRecent' => 0, |
|
| 1793 | - 'ratingNumOverall' => 0, |
|
| 1794 | - 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 1778 | + ], |
|
| 1779 | + ], |
|
| 1780 | + 'isFeatured' => false, |
|
| 1781 | + 'authors' |
|
| 1782 | + => [ |
|
| 1783 | + 0 |
|
| 1784 | + => [ |
|
| 1785 | + 'name' => 'Maxence Lange', |
|
| 1786 | + 'mail' => '', |
|
| 1787 | + 'homepage' => '', |
|
| 1788 | + ], |
|
| 1789 | + ], |
|
| 1790 | + 'ratingRecent' => 0.5, |
|
| 1791 | + 'ratingOverall' => 0.5, |
|
| 1792 | + 'ratingNumRecent' => 0, |
|
| 1793 | + 'ratingNumOverall' => 0, |
|
| 1794 | + 'certificate' => '-----BEGIN CERTIFICATE----- |
|
| 1795 | 1795 | MIIEAjCCAuoCAhAFMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD |
| 1796 | 1796 | VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI |
| 1797 | 1797 | MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB |
@@ -1815,444 +1815,444 @@ discard block |
||
| 1815 | 1815 | 0bfhnvTZ2VhMmK83t7ovo71An4ycmsolGD/MA0vNI78VrVISrdI8rRh2WntUnCBU |
| 1816 | 1816 | EJL3BaQAQaASSsvFrcozYxrQG4VzEg== |
| 1817 | 1817 | -----END CERTIFICATE-----', |
| 1818 | - ], |
|
| 1819 | - ], |
|
| 1820 | - 'timestamp' => 1234, |
|
| 1821 | - 'ncversion' => '11.0.0.2', |
|
| 1822 | - 'ETag' => '"myETag"', |
|
| 1823 | - ]; |
|
| 1824 | - |
|
| 1825 | - |
|
| 1826 | - protected function setUp(): void { |
|
| 1827 | - parent::setUp(); |
|
| 1828 | - |
|
| 1829 | - /** @var Factory|\PHPUnit\Framework\MockObject\MockObject $factory */ |
|
| 1830 | - $factory = $this->createMock(Factory::class); |
|
| 1831 | - $this->appData = $this->createMock(AppData::class); |
|
| 1832 | - $factory->expects($this->once()) |
|
| 1833 | - ->method('get') |
|
| 1834 | - ->with('appstore') |
|
| 1835 | - ->willReturn($this->appData); |
|
| 1836 | - $this->clientService = $this->createMock(IClientService::class); |
|
| 1837 | - $this->timeFactory = $this->createMock(ITimeFactory::class); |
|
| 1838 | - $this->config = $this->createMock(IConfig::class); |
|
| 1839 | - $this->compareVersion = new CompareVersion(); |
|
| 1840 | - $this->logger = $this->createMock(LoggerInterface::class); |
|
| 1841 | - $this->registry = $this->createMock(IRegistry::class); |
|
| 1842 | - |
|
| 1843 | - $this->fetcher = $this->getMockBuilder(AppFetcher::class) |
|
| 1844 | - ->onlyMethods(['getChannel']) |
|
| 1845 | - ->setConstructorArgs([ |
|
| 1846 | - $factory, |
|
| 1847 | - $this->clientService, |
|
| 1848 | - $this->timeFactory, |
|
| 1849 | - $this->config, |
|
| 1850 | - $this->compareVersion, |
|
| 1851 | - $this->logger, |
|
| 1852 | - $this->registry, |
|
| 1853 | - ]) |
|
| 1854 | - ->getMock(); |
|
| 1855 | - |
|
| 1856 | - $this->fetcher->method('getChannel') |
|
| 1857 | - ->willReturn('stable'); |
|
| 1858 | - } |
|
| 1859 | - |
|
| 1860 | - public function testGetWithFilter(): void { |
|
| 1861 | - $this->config->method('getSystemValueString') |
|
| 1862 | - ->willReturnCallback(function ($key, $default) { |
|
| 1863 | - if ($key === 'version') { |
|
| 1864 | - return '11.0.0.2'; |
|
| 1865 | - } elseif ($key === 'appstoreurl' && $default === 'https://apps.nextcloud.com/api/v1') { |
|
| 1866 | - return 'https://custom.appsstore.endpoint/api/v1'; |
|
| 1867 | - } else { |
|
| 1868 | - return $default; |
|
| 1869 | - } |
|
| 1870 | - }); |
|
| 1871 | - $this->config |
|
| 1872 | - ->method('getSystemValueBool') |
|
| 1873 | - ->willReturnArgument(1); |
|
| 1874 | - |
|
| 1875 | - $file = $this->createMock(ISimpleFile::class); |
|
| 1876 | - $folder = $this->createMock(ISimpleFolder::class); |
|
| 1877 | - $folder |
|
| 1878 | - ->expects($this->once()) |
|
| 1879 | - ->method('getFile') |
|
| 1880 | - ->with('apps.json') |
|
| 1881 | - ->willThrowException(new NotFoundException()); |
|
| 1882 | - $folder |
|
| 1883 | - ->expects($this->once()) |
|
| 1884 | - ->method('newFile') |
|
| 1885 | - ->with('apps.json') |
|
| 1886 | - ->willReturn($file); |
|
| 1887 | - $this->appData |
|
| 1888 | - ->expects($this->once()) |
|
| 1889 | - ->method('getFolder') |
|
| 1890 | - ->with('/') |
|
| 1891 | - ->willReturn($folder); |
|
| 1892 | - $client = $this->createMock(IClient::class); |
|
| 1893 | - $this->clientService |
|
| 1894 | - ->expects($this->once()) |
|
| 1895 | - ->method('newClient') |
|
| 1896 | - ->willReturn($client); |
|
| 1897 | - $response = $this->createMock(IResponse::class); |
|
| 1898 | - $client |
|
| 1899 | - ->method('get') |
|
| 1900 | - ->with('https://custom.appsstore.endpoint/api/v1/apps.json') |
|
| 1901 | - ->willReturn($response); |
|
| 1902 | - $response |
|
| 1903 | - ->expects($this->once()) |
|
| 1904 | - ->method('getBody') |
|
| 1905 | - ->willReturn(self::$responseJson); |
|
| 1906 | - $response->method('getHeader') |
|
| 1907 | - ->with($this->equalTo('ETag')) |
|
| 1908 | - ->willReturn('"myETag"'); |
|
| 1909 | - $this->timeFactory |
|
| 1910 | - ->expects($this->once()) |
|
| 1911 | - ->method('getTime') |
|
| 1912 | - ->willReturn(1234); |
|
| 1913 | - |
|
| 1914 | - $dataToPut = self::$expectedResponse; |
|
| 1915 | - $dataToPut['data'] = array_values($dataToPut['data']); |
|
| 1916 | - $originalArray = json_decode(self::$responseJson, true); |
|
| 1917 | - $mappedOriginalArray = []; |
|
| 1918 | - foreach ($originalArray as $key => $value) { |
|
| 1919 | - foreach ($value as $releaseKey => $releaseValue) { |
|
| 1920 | - if ($releaseKey === 'id') { |
|
| 1921 | - $mappedOriginalArray[$releaseValue] = $originalArray[$key]; |
|
| 1922 | - } |
|
| 1923 | - } |
|
| 1924 | - } |
|
| 1925 | - foreach ($dataToPut['data'] as $key => $appValue) { |
|
| 1926 | - foreach ($appValue as $appKey => $value) { |
|
| 1927 | - if ($appKey === 'certificate' || $appKey === 'description') { |
|
| 1928 | - $dataToPut['data'][$key][$appKey] = $mappedOriginalArray[$appValue['id']][$appKey]; |
|
| 1929 | - } |
|
| 1930 | - } |
|
| 1931 | - } |
|
| 1932 | - |
|
| 1933 | - $file |
|
| 1934 | - ->expects($this->once()) |
|
| 1935 | - ->method('putContent'); |
|
| 1936 | - $file |
|
| 1937 | - ->method('getContent') |
|
| 1938 | - ->willReturn(json_encode(self::$expectedResponse)); |
|
| 1939 | - |
|
| 1940 | - $this->assertEquals(self::$expectedResponse['data'], $this->fetcher->get()); |
|
| 1941 | - } |
|
| 1942 | - |
|
| 1943 | - public function testAppstoreDisabled(): void { |
|
| 1944 | - $this->config |
|
| 1945 | - ->method('getSystemValueString') |
|
| 1946 | - ->willReturnCallback(function ($var, $default) { |
|
| 1947 | - if ($var === 'version') { |
|
| 1948 | - return '11.0.0.2'; |
|
| 1949 | - } |
|
| 1950 | - return $default; |
|
| 1951 | - }); |
|
| 1952 | - $this->config |
|
| 1953 | - ->method('getSystemValueBool') |
|
| 1954 | - ->willReturnCallback(function ($var, $default) { |
|
| 1955 | - if ($var === 'has_internet_connection') { |
|
| 1956 | - return true; |
|
| 1957 | - } elseif ($var === 'appstoreenabled') { |
|
| 1958 | - return false; |
|
| 1959 | - } |
|
| 1960 | - return $default; |
|
| 1961 | - }); |
|
| 1962 | - $this->appData |
|
| 1963 | - ->expects($this->never()) |
|
| 1964 | - ->method('getFolder'); |
|
| 1965 | - |
|
| 1966 | - $this->assertEquals([], $this->fetcher->get()); |
|
| 1967 | - } |
|
| 1968 | - |
|
| 1969 | - |
|
| 1970 | - public function testNoInternet(): void { |
|
| 1971 | - $this->config |
|
| 1972 | - ->method('getSystemValueString') |
|
| 1973 | - ->willReturnCallback(function ($var, $default) { |
|
| 1974 | - if ($var === 'has_internet_connection') { |
|
| 1975 | - return false; |
|
| 1976 | - } elseif ($var === 'version') { |
|
| 1977 | - return '11.0.0.2'; |
|
| 1978 | - } |
|
| 1979 | - return $default; |
|
| 1980 | - }); |
|
| 1981 | - $this->config |
|
| 1982 | - ->method('getSystemValueBool') |
|
| 1983 | - ->willReturnCallback(function ($var, $default) { |
|
| 1984 | - if ($var === 'has_internet_connection') { |
|
| 1985 | - return false; |
|
| 1986 | - } elseif ($var === 'appstoreenabled') { |
|
| 1987 | - return true; |
|
| 1988 | - } |
|
| 1989 | - return $default; |
|
| 1990 | - }); |
|
| 1991 | - $this->appData |
|
| 1992 | - ->expects($this->never()) |
|
| 1993 | - ->method('getFolder'); |
|
| 1994 | - |
|
| 1995 | - $this->assertEquals([], $this->fetcher->get()); |
|
| 1996 | - } |
|
| 1997 | - |
|
| 1998 | - public function testSetVersion(): void { |
|
| 1999 | - $this->config->method('getSystemValueString') |
|
| 2000 | - ->willReturnCallback(function ($key, $default) { |
|
| 2001 | - if ($key === 'version') { |
|
| 2002 | - return '10.0.7.2'; |
|
| 2003 | - } elseif ($key === 'appstoreurl' && $default === 'https://apps.nextcloud.com/api/v1') { |
|
| 2004 | - return 'https://custom.appsstore.endpoint/api/v1'; |
|
| 2005 | - } else { |
|
| 2006 | - return $default; |
|
| 2007 | - } |
|
| 2008 | - }); |
|
| 2009 | - $this->config |
|
| 2010 | - ->method('getSystemValueBool') |
|
| 2011 | - ->willReturnArgument(1); |
|
| 2012 | - |
|
| 2013 | - $file = $this->createMock(ISimpleFile::class); |
|
| 2014 | - $folder = $this->createMock(ISimpleFolder::class); |
|
| 2015 | - $folder |
|
| 2016 | - ->expects($this->once()) |
|
| 2017 | - ->method('getFile') |
|
| 2018 | - ->with('future-apps.json') |
|
| 2019 | - ->willThrowException(new NotFoundException()); |
|
| 2020 | - $folder |
|
| 2021 | - ->expects($this->once()) |
|
| 2022 | - ->method('newFile') |
|
| 2023 | - ->with('future-apps.json') |
|
| 2024 | - ->willReturn($file); |
|
| 2025 | - $this->appData |
|
| 2026 | - ->expects($this->once()) |
|
| 2027 | - ->method('getFolder') |
|
| 2028 | - ->with('/') |
|
| 2029 | - ->willReturn($folder); |
|
| 2030 | - $client = $this->createMock(IClient::class); |
|
| 2031 | - $this->clientService |
|
| 2032 | - ->expects($this->once()) |
|
| 2033 | - ->method('newClient') |
|
| 2034 | - ->willReturn($client); |
|
| 2035 | - $response = $this->createMock(IResponse::class); |
|
| 2036 | - $client |
|
| 2037 | - ->method('get') |
|
| 2038 | - ->with('https://custom.appsstore.endpoint/api/v1/apps.json') |
|
| 2039 | - ->willReturn($response); |
|
| 2040 | - $response |
|
| 2041 | - ->expects($this->once()) |
|
| 2042 | - ->method('getBody') |
|
| 2043 | - ->willReturn(self::$responseJson); |
|
| 2044 | - $response->method('getHeader') |
|
| 2045 | - ->with($this->equalTo('ETag')) |
|
| 2046 | - ->willReturn('"myETag"'); |
|
| 2047 | - $this->timeFactory |
|
| 2048 | - ->expects($this->once()) |
|
| 2049 | - ->method('getTime') |
|
| 2050 | - ->willReturn(1234); |
|
| 2051 | - |
|
| 2052 | - $dataToPut = self::$expectedResponse; |
|
| 2053 | - $dataToPut['data'] = array_values($dataToPut['data']); |
|
| 2054 | - $originalArray = json_decode(self::$responseJson, true); |
|
| 2055 | - $mappedOriginalArray = []; |
|
| 2056 | - foreach ($originalArray as $key => $value) { |
|
| 2057 | - foreach ($value as $releaseKey => $releaseValue) { |
|
| 2058 | - if ($releaseKey === 'id') { |
|
| 2059 | - $mappedOriginalArray[$releaseValue] = $originalArray[$key]; |
|
| 2060 | - } |
|
| 2061 | - } |
|
| 2062 | - } |
|
| 2063 | - foreach ($dataToPut['data'] as $key => $appValue) { |
|
| 2064 | - foreach ($appValue as $appKey => $value) { |
|
| 2065 | - if ($appKey === 'certificate' || $appKey === 'description') { |
|
| 2066 | - $dataToPut['data'][$key][$appKey] = $mappedOriginalArray[$appValue['id']][$appKey]; |
|
| 2067 | - } |
|
| 2068 | - } |
|
| 2069 | - } |
|
| 2070 | - |
|
| 2071 | - $file |
|
| 2072 | - ->expects($this->once()) |
|
| 2073 | - ->method('putContent'); |
|
| 2074 | - $file |
|
| 2075 | - ->method('getContent') |
|
| 2076 | - ->willReturn(json_encode(self::$expectedResponse)); |
|
| 2077 | - |
|
| 2078 | - $this->fetcher->setVersion('11.0.0.2', 'future-apps.json', false); |
|
| 2079 | - $this->assertEquals(self::$expectedResponse['data'], $this->fetcher->get()); |
|
| 2080 | - } |
|
| 2081 | - |
|
| 2082 | - public function testGetAppsAllowlist(): void { |
|
| 2083 | - $this->config->method('getSystemValueString') |
|
| 2084 | - ->willReturnCallback(function ($key, $default) { |
|
| 2085 | - if ($key === 'version') { |
|
| 2086 | - return '11.0.0.2'; |
|
| 2087 | - } else { |
|
| 2088 | - return $default; |
|
| 2089 | - } |
|
| 2090 | - }); |
|
| 2091 | - $this->config->method('getSystemValue') |
|
| 2092 | - ->willReturnCallback(function ($key, $default) { |
|
| 2093 | - if ($key === 'appsallowlist') { |
|
| 2094 | - return ['contacts']; |
|
| 2095 | - } |
|
| 2096 | - return $default; |
|
| 2097 | - }); |
|
| 2098 | - $this->config->method('getAppValue') |
|
| 2099 | - ->willReturnCallback(function ($app, $key, $default) { |
|
| 2100 | - if ($app === 'support' && $key === 'subscription_key') { |
|
| 2101 | - return 'subscription-key'; |
|
| 2102 | - } |
|
| 2103 | - return $default; |
|
| 2104 | - }); |
|
| 2105 | - $this->config |
|
| 2106 | - ->method('getSystemValueBool') |
|
| 2107 | - ->willReturnArgument(1); |
|
| 2108 | - |
|
| 2109 | - $file = $this->createMock(ISimpleFile::class); |
|
| 2110 | - $folder = $this->createMock(ISimpleFolder::class); |
|
| 2111 | - $folder |
|
| 2112 | - ->expects($this->once()) |
|
| 2113 | - ->method('getFile') |
|
| 2114 | - ->with('apps.json') |
|
| 2115 | - ->willThrowException(new NotFoundException()); |
|
| 2116 | - $folder |
|
| 2117 | - ->expects($this->once()) |
|
| 2118 | - ->method('newFile') |
|
| 2119 | - ->with('apps.json') |
|
| 2120 | - ->willReturn($file); |
|
| 2121 | - $this->appData |
|
| 2122 | - ->expects($this->once()) |
|
| 2123 | - ->method('getFolder') |
|
| 2124 | - ->with('/') |
|
| 2125 | - ->willReturn($folder); |
|
| 2126 | - $client = $this->createMock(IClient::class); |
|
| 2127 | - $this->clientService |
|
| 2128 | - ->expects($this->once()) |
|
| 2129 | - ->method('newClient') |
|
| 2130 | - ->willReturn($client); |
|
| 2131 | - $response = $this->createMock(IResponse::class); |
|
| 2132 | - $client |
|
| 2133 | - ->expects($this->once()) |
|
| 2134 | - ->method('get') |
|
| 2135 | - ->with('https://apps.nextcloud.com/api/v1/apps.json', [ |
|
| 2136 | - 'timeout' => 120, |
|
| 2137 | - 'headers' => [ |
|
| 2138 | - 'X-NC-Subscription-Key' => 'subscription-key', |
|
| 2139 | - ], |
|
| 2140 | - ]) |
|
| 2141 | - ->willReturn($response); |
|
| 2142 | - $response |
|
| 2143 | - ->expects($this->once()) |
|
| 2144 | - ->method('getBody') |
|
| 2145 | - ->willReturn(self::$responseJson); |
|
| 2146 | - $response->method('getHeader') |
|
| 2147 | - ->with($this->equalTo('ETag')) |
|
| 2148 | - ->willReturn('"myETag"'); |
|
| 2149 | - $this->timeFactory |
|
| 2150 | - ->expects($this->once()) |
|
| 2151 | - ->method('getTime') |
|
| 2152 | - ->willReturn(1234); |
|
| 2153 | - |
|
| 2154 | - $this->registry |
|
| 2155 | - ->expects($this->exactly(2)) |
|
| 2156 | - ->method('delegateHasValidSubscription') |
|
| 2157 | - ->willReturn(true); |
|
| 2158 | - |
|
| 2159 | - $file |
|
| 2160 | - ->expects($this->once()) |
|
| 2161 | - ->method('putContent'); |
|
| 2162 | - $file |
|
| 2163 | - ->method('getContent') |
|
| 2164 | - ->willReturn(json_encode(self::$expectedResponse)); |
|
| 2165 | - |
|
| 2166 | - $apps = array_values($this->fetcher->get()); |
|
| 2167 | - $this->assertEquals(count($apps), 1); |
|
| 2168 | - $this->assertEquals($apps[0]['id'], 'contacts'); |
|
| 2169 | - } |
|
| 2170 | - |
|
| 2171 | - public function testGetAppsAllowlistCustomAppstore(): void { |
|
| 2172 | - $this->config->method('getSystemValueString') |
|
| 2173 | - ->willReturnCallback(function ($key, $default) { |
|
| 2174 | - if ($key === 'version') { |
|
| 2175 | - return '11.0.0.2'; |
|
| 2176 | - } elseif ($key === 'appstoreurl' && $default === 'https://apps.nextcloud.com/api/v1') { |
|
| 2177 | - return 'https://custom.appsstore.endpoint/api/v1'; |
|
| 2178 | - } else { |
|
| 2179 | - return $default; |
|
| 2180 | - } |
|
| 2181 | - }); |
|
| 2182 | - $this->config->method('getSystemValue') |
|
| 2183 | - ->willReturnCallback(function ($key, $default) { |
|
| 2184 | - if ($key === 'appsallowlist') { |
|
| 2185 | - return ['contacts']; |
|
| 2186 | - } else { |
|
| 2187 | - return $default; |
|
| 2188 | - } |
|
| 2189 | - }); |
|
| 2190 | - $this->config |
|
| 2191 | - ->method('getSystemValueBool') |
|
| 2192 | - ->willReturnArgument(1); |
|
| 2193 | - |
|
| 2194 | - $this->config->method('getAppValue') |
|
| 2195 | - ->willReturnMap([ |
|
| 2196 | - ['settings', 'appstore-fetcher-lastFailure', '0', '0'], |
|
| 2197 | - ['settings', 'appstore-timeout', '120', '120'], |
|
| 2198 | - ]); |
|
| 2199 | - |
|
| 2200 | - $file = $this->createMock(ISimpleFile::class); |
|
| 2201 | - $folder = $this->createMock(ISimpleFolder::class); |
|
| 2202 | - $folder |
|
| 2203 | - ->expects($this->once()) |
|
| 2204 | - ->method('getFile') |
|
| 2205 | - ->with('apps.json') |
|
| 2206 | - ->willThrowException(new NotFoundException()); |
|
| 2207 | - $folder |
|
| 2208 | - ->expects($this->once()) |
|
| 2209 | - ->method('newFile') |
|
| 2210 | - ->with('apps.json') |
|
| 2211 | - ->willReturn($file); |
|
| 2212 | - $this->appData |
|
| 2213 | - ->expects($this->once()) |
|
| 2214 | - ->method('getFolder') |
|
| 2215 | - ->with('/') |
|
| 2216 | - ->willReturn($folder); |
|
| 2217 | - $client = $this->createMock(IClient::class); |
|
| 2218 | - $this->clientService |
|
| 2219 | - ->expects($this->once()) |
|
| 2220 | - ->method('newClient') |
|
| 2221 | - ->willReturn($client); |
|
| 2222 | - $response = $this->createMock(IResponse::class); |
|
| 2223 | - $client |
|
| 2224 | - ->expects($this->once()) |
|
| 2225 | - ->method('get') |
|
| 2226 | - ->with('https://custom.appsstore.endpoint/api/v1/apps.json', [ |
|
| 2227 | - 'timeout' => 120, |
|
| 2228 | - ]) |
|
| 2229 | - ->willReturn($response); |
|
| 2230 | - $response |
|
| 2231 | - ->expects($this->once()) |
|
| 2232 | - ->method('getBody') |
|
| 2233 | - ->willReturn(self::$responseJson); |
|
| 2234 | - $response->method('getHeader') |
|
| 2235 | - ->with($this->equalTo('ETag')) |
|
| 2236 | - ->willReturn('"myETag"'); |
|
| 2237 | - $this->timeFactory |
|
| 2238 | - ->expects($this->once()) |
|
| 2239 | - ->method('getTime') |
|
| 2240 | - ->willReturn(1234); |
|
| 2241 | - |
|
| 2242 | - $this->registry |
|
| 2243 | - ->expects($this->exactly(1)) |
|
| 2244 | - ->method('delegateHasValidSubscription') |
|
| 2245 | - ->willReturn(true); |
|
| 2246 | - |
|
| 2247 | - $file |
|
| 2248 | - ->expects($this->once()) |
|
| 2249 | - ->method('putContent'); |
|
| 2250 | - $file |
|
| 2251 | - ->method('getContent') |
|
| 2252 | - ->willReturn(json_encode(self::$expectedResponse)); |
|
| 2253 | - |
|
| 2254 | - $apps = array_values($this->fetcher->get()); |
|
| 2255 | - $this->assertEquals(count($apps), 1); |
|
| 2256 | - $this->assertEquals($apps[0]['id'], 'contacts'); |
|
| 2257 | - } |
|
| 1818 | + ], |
|
| 1819 | + ], |
|
| 1820 | + 'timestamp' => 1234, |
|
| 1821 | + 'ncversion' => '11.0.0.2', |
|
| 1822 | + 'ETag' => '"myETag"', |
|
| 1823 | + ]; |
|
| 1824 | + |
|
| 1825 | + |
|
| 1826 | + protected function setUp(): void { |
|
| 1827 | + parent::setUp(); |
|
| 1828 | + |
|
| 1829 | + /** @var Factory|\PHPUnit\Framework\MockObject\MockObject $factory */ |
|
| 1830 | + $factory = $this->createMock(Factory::class); |
|
| 1831 | + $this->appData = $this->createMock(AppData::class); |
|
| 1832 | + $factory->expects($this->once()) |
|
| 1833 | + ->method('get') |
|
| 1834 | + ->with('appstore') |
|
| 1835 | + ->willReturn($this->appData); |
|
| 1836 | + $this->clientService = $this->createMock(IClientService::class); |
|
| 1837 | + $this->timeFactory = $this->createMock(ITimeFactory::class); |
|
| 1838 | + $this->config = $this->createMock(IConfig::class); |
|
| 1839 | + $this->compareVersion = new CompareVersion(); |
|
| 1840 | + $this->logger = $this->createMock(LoggerInterface::class); |
|
| 1841 | + $this->registry = $this->createMock(IRegistry::class); |
|
| 1842 | + |
|
| 1843 | + $this->fetcher = $this->getMockBuilder(AppFetcher::class) |
|
| 1844 | + ->onlyMethods(['getChannel']) |
|
| 1845 | + ->setConstructorArgs([ |
|
| 1846 | + $factory, |
|
| 1847 | + $this->clientService, |
|
| 1848 | + $this->timeFactory, |
|
| 1849 | + $this->config, |
|
| 1850 | + $this->compareVersion, |
|
| 1851 | + $this->logger, |
|
| 1852 | + $this->registry, |
|
| 1853 | + ]) |
|
| 1854 | + ->getMock(); |
|
| 1855 | + |
|
| 1856 | + $this->fetcher->method('getChannel') |
|
| 1857 | + ->willReturn('stable'); |
|
| 1858 | + } |
|
| 1859 | + |
|
| 1860 | + public function testGetWithFilter(): void { |
|
| 1861 | + $this->config->method('getSystemValueString') |
|
| 1862 | + ->willReturnCallback(function ($key, $default) { |
|
| 1863 | + if ($key === 'version') { |
|
| 1864 | + return '11.0.0.2'; |
|
| 1865 | + } elseif ($key === 'appstoreurl' && $default === 'https://apps.nextcloud.com/api/v1') { |
|
| 1866 | + return 'https://custom.appsstore.endpoint/api/v1'; |
|
| 1867 | + } else { |
|
| 1868 | + return $default; |
|
| 1869 | + } |
|
| 1870 | + }); |
|
| 1871 | + $this->config |
|
| 1872 | + ->method('getSystemValueBool') |
|
| 1873 | + ->willReturnArgument(1); |
|
| 1874 | + |
|
| 1875 | + $file = $this->createMock(ISimpleFile::class); |
|
| 1876 | + $folder = $this->createMock(ISimpleFolder::class); |
|
| 1877 | + $folder |
|
| 1878 | + ->expects($this->once()) |
|
| 1879 | + ->method('getFile') |
|
| 1880 | + ->with('apps.json') |
|
| 1881 | + ->willThrowException(new NotFoundException()); |
|
| 1882 | + $folder |
|
| 1883 | + ->expects($this->once()) |
|
| 1884 | + ->method('newFile') |
|
| 1885 | + ->with('apps.json') |
|
| 1886 | + ->willReturn($file); |
|
| 1887 | + $this->appData |
|
| 1888 | + ->expects($this->once()) |
|
| 1889 | + ->method('getFolder') |
|
| 1890 | + ->with('/') |
|
| 1891 | + ->willReturn($folder); |
|
| 1892 | + $client = $this->createMock(IClient::class); |
|
| 1893 | + $this->clientService |
|
| 1894 | + ->expects($this->once()) |
|
| 1895 | + ->method('newClient') |
|
| 1896 | + ->willReturn($client); |
|
| 1897 | + $response = $this->createMock(IResponse::class); |
|
| 1898 | + $client |
|
| 1899 | + ->method('get') |
|
| 1900 | + ->with('https://custom.appsstore.endpoint/api/v1/apps.json') |
|
| 1901 | + ->willReturn($response); |
|
| 1902 | + $response |
|
| 1903 | + ->expects($this->once()) |
|
| 1904 | + ->method('getBody') |
|
| 1905 | + ->willReturn(self::$responseJson); |
|
| 1906 | + $response->method('getHeader') |
|
| 1907 | + ->with($this->equalTo('ETag')) |
|
| 1908 | + ->willReturn('"myETag"'); |
|
| 1909 | + $this->timeFactory |
|
| 1910 | + ->expects($this->once()) |
|
| 1911 | + ->method('getTime') |
|
| 1912 | + ->willReturn(1234); |
|
| 1913 | + |
|
| 1914 | + $dataToPut = self::$expectedResponse; |
|
| 1915 | + $dataToPut['data'] = array_values($dataToPut['data']); |
|
| 1916 | + $originalArray = json_decode(self::$responseJson, true); |
|
| 1917 | + $mappedOriginalArray = []; |
|
| 1918 | + foreach ($originalArray as $key => $value) { |
|
| 1919 | + foreach ($value as $releaseKey => $releaseValue) { |
|
| 1920 | + if ($releaseKey === 'id') { |
|
| 1921 | + $mappedOriginalArray[$releaseValue] = $originalArray[$key]; |
|
| 1922 | + } |
|
| 1923 | + } |
|
| 1924 | + } |
|
| 1925 | + foreach ($dataToPut['data'] as $key => $appValue) { |
|
| 1926 | + foreach ($appValue as $appKey => $value) { |
|
| 1927 | + if ($appKey === 'certificate' || $appKey === 'description') { |
|
| 1928 | + $dataToPut['data'][$key][$appKey] = $mappedOriginalArray[$appValue['id']][$appKey]; |
|
| 1929 | + } |
|
| 1930 | + } |
|
| 1931 | + } |
|
| 1932 | + |
|
| 1933 | + $file |
|
| 1934 | + ->expects($this->once()) |
|
| 1935 | + ->method('putContent'); |
|
| 1936 | + $file |
|
| 1937 | + ->method('getContent') |
|
| 1938 | + ->willReturn(json_encode(self::$expectedResponse)); |
|
| 1939 | + |
|
| 1940 | + $this->assertEquals(self::$expectedResponse['data'], $this->fetcher->get()); |
|
| 1941 | + } |
|
| 1942 | + |
|
| 1943 | + public function testAppstoreDisabled(): void { |
|
| 1944 | + $this->config |
|
| 1945 | + ->method('getSystemValueString') |
|
| 1946 | + ->willReturnCallback(function ($var, $default) { |
|
| 1947 | + if ($var === 'version') { |
|
| 1948 | + return '11.0.0.2'; |
|
| 1949 | + } |
|
| 1950 | + return $default; |
|
| 1951 | + }); |
|
| 1952 | + $this->config |
|
| 1953 | + ->method('getSystemValueBool') |
|
| 1954 | + ->willReturnCallback(function ($var, $default) { |
|
| 1955 | + if ($var === 'has_internet_connection') { |
|
| 1956 | + return true; |
|
| 1957 | + } elseif ($var === 'appstoreenabled') { |
|
| 1958 | + return false; |
|
| 1959 | + } |
|
| 1960 | + return $default; |
|
| 1961 | + }); |
|
| 1962 | + $this->appData |
|
| 1963 | + ->expects($this->never()) |
|
| 1964 | + ->method('getFolder'); |
|
| 1965 | + |
|
| 1966 | + $this->assertEquals([], $this->fetcher->get()); |
|
| 1967 | + } |
|
| 1968 | + |
|
| 1969 | + |
|
| 1970 | + public function testNoInternet(): void { |
|
| 1971 | + $this->config |
|
| 1972 | + ->method('getSystemValueString') |
|
| 1973 | + ->willReturnCallback(function ($var, $default) { |
|
| 1974 | + if ($var === 'has_internet_connection') { |
|
| 1975 | + return false; |
|
| 1976 | + } elseif ($var === 'version') { |
|
| 1977 | + return '11.0.0.2'; |
|
| 1978 | + } |
|
| 1979 | + return $default; |
|
| 1980 | + }); |
|
| 1981 | + $this->config |
|
| 1982 | + ->method('getSystemValueBool') |
|
| 1983 | + ->willReturnCallback(function ($var, $default) { |
|
| 1984 | + if ($var === 'has_internet_connection') { |
|
| 1985 | + return false; |
|
| 1986 | + } elseif ($var === 'appstoreenabled') { |
|
| 1987 | + return true; |
|
| 1988 | + } |
|
| 1989 | + return $default; |
|
| 1990 | + }); |
|
| 1991 | + $this->appData |
|
| 1992 | + ->expects($this->never()) |
|
| 1993 | + ->method('getFolder'); |
|
| 1994 | + |
|
| 1995 | + $this->assertEquals([], $this->fetcher->get()); |
|
| 1996 | + } |
|
| 1997 | + |
|
| 1998 | + public function testSetVersion(): void { |
|
| 1999 | + $this->config->method('getSystemValueString') |
|
| 2000 | + ->willReturnCallback(function ($key, $default) { |
|
| 2001 | + if ($key === 'version') { |
|
| 2002 | + return '10.0.7.2'; |
|
| 2003 | + } elseif ($key === 'appstoreurl' && $default === 'https://apps.nextcloud.com/api/v1') { |
|
| 2004 | + return 'https://custom.appsstore.endpoint/api/v1'; |
|
| 2005 | + } else { |
|
| 2006 | + return $default; |
|
| 2007 | + } |
|
| 2008 | + }); |
|
| 2009 | + $this->config |
|
| 2010 | + ->method('getSystemValueBool') |
|
| 2011 | + ->willReturnArgument(1); |
|
| 2012 | + |
|
| 2013 | + $file = $this->createMock(ISimpleFile::class); |
|
| 2014 | + $folder = $this->createMock(ISimpleFolder::class); |
|
| 2015 | + $folder |
|
| 2016 | + ->expects($this->once()) |
|
| 2017 | + ->method('getFile') |
|
| 2018 | + ->with('future-apps.json') |
|
| 2019 | + ->willThrowException(new NotFoundException()); |
|
| 2020 | + $folder |
|
| 2021 | + ->expects($this->once()) |
|
| 2022 | + ->method('newFile') |
|
| 2023 | + ->with('future-apps.json') |
|
| 2024 | + ->willReturn($file); |
|
| 2025 | + $this->appData |
|
| 2026 | + ->expects($this->once()) |
|
| 2027 | + ->method('getFolder') |
|
| 2028 | + ->with('/') |
|
| 2029 | + ->willReturn($folder); |
|
| 2030 | + $client = $this->createMock(IClient::class); |
|
| 2031 | + $this->clientService |
|
| 2032 | + ->expects($this->once()) |
|
| 2033 | + ->method('newClient') |
|
| 2034 | + ->willReturn($client); |
|
| 2035 | + $response = $this->createMock(IResponse::class); |
|
| 2036 | + $client |
|
| 2037 | + ->method('get') |
|
| 2038 | + ->with('https://custom.appsstore.endpoint/api/v1/apps.json') |
|
| 2039 | + ->willReturn($response); |
|
| 2040 | + $response |
|
| 2041 | + ->expects($this->once()) |
|
| 2042 | + ->method('getBody') |
|
| 2043 | + ->willReturn(self::$responseJson); |
|
| 2044 | + $response->method('getHeader') |
|
| 2045 | + ->with($this->equalTo('ETag')) |
|
| 2046 | + ->willReturn('"myETag"'); |
|
| 2047 | + $this->timeFactory |
|
| 2048 | + ->expects($this->once()) |
|
| 2049 | + ->method('getTime') |
|
| 2050 | + ->willReturn(1234); |
|
| 2051 | + |
|
| 2052 | + $dataToPut = self::$expectedResponse; |
|
| 2053 | + $dataToPut['data'] = array_values($dataToPut['data']); |
|
| 2054 | + $originalArray = json_decode(self::$responseJson, true); |
|
| 2055 | + $mappedOriginalArray = []; |
|
| 2056 | + foreach ($originalArray as $key => $value) { |
|
| 2057 | + foreach ($value as $releaseKey => $releaseValue) { |
|
| 2058 | + if ($releaseKey === 'id') { |
|
| 2059 | + $mappedOriginalArray[$releaseValue] = $originalArray[$key]; |
|
| 2060 | + } |
|
| 2061 | + } |
|
| 2062 | + } |
|
| 2063 | + foreach ($dataToPut['data'] as $key => $appValue) { |
|
| 2064 | + foreach ($appValue as $appKey => $value) { |
|
| 2065 | + if ($appKey === 'certificate' || $appKey === 'description') { |
|
| 2066 | + $dataToPut['data'][$key][$appKey] = $mappedOriginalArray[$appValue['id']][$appKey]; |
|
| 2067 | + } |
|
| 2068 | + } |
|
| 2069 | + } |
|
| 2070 | + |
|
| 2071 | + $file |
|
| 2072 | + ->expects($this->once()) |
|
| 2073 | + ->method('putContent'); |
|
| 2074 | + $file |
|
| 2075 | + ->method('getContent') |
|
| 2076 | + ->willReturn(json_encode(self::$expectedResponse)); |
|
| 2077 | + |
|
| 2078 | + $this->fetcher->setVersion('11.0.0.2', 'future-apps.json', false); |
|
| 2079 | + $this->assertEquals(self::$expectedResponse['data'], $this->fetcher->get()); |
|
| 2080 | + } |
|
| 2081 | + |
|
| 2082 | + public function testGetAppsAllowlist(): void { |
|
| 2083 | + $this->config->method('getSystemValueString') |
|
| 2084 | + ->willReturnCallback(function ($key, $default) { |
|
| 2085 | + if ($key === 'version') { |
|
| 2086 | + return '11.0.0.2'; |
|
| 2087 | + } else { |
|
| 2088 | + return $default; |
|
| 2089 | + } |
|
| 2090 | + }); |
|
| 2091 | + $this->config->method('getSystemValue') |
|
| 2092 | + ->willReturnCallback(function ($key, $default) { |
|
| 2093 | + if ($key === 'appsallowlist') { |
|
| 2094 | + return ['contacts']; |
|
| 2095 | + } |
|
| 2096 | + return $default; |
|
| 2097 | + }); |
|
| 2098 | + $this->config->method('getAppValue') |
|
| 2099 | + ->willReturnCallback(function ($app, $key, $default) { |
|
| 2100 | + if ($app === 'support' && $key === 'subscription_key') { |
|
| 2101 | + return 'subscription-key'; |
|
| 2102 | + } |
|
| 2103 | + return $default; |
|
| 2104 | + }); |
|
| 2105 | + $this->config |
|
| 2106 | + ->method('getSystemValueBool') |
|
| 2107 | + ->willReturnArgument(1); |
|
| 2108 | + |
|
| 2109 | + $file = $this->createMock(ISimpleFile::class); |
|
| 2110 | + $folder = $this->createMock(ISimpleFolder::class); |
|
| 2111 | + $folder |
|
| 2112 | + ->expects($this->once()) |
|
| 2113 | + ->method('getFile') |
|
| 2114 | + ->with('apps.json') |
|
| 2115 | + ->willThrowException(new NotFoundException()); |
|
| 2116 | + $folder |
|
| 2117 | + ->expects($this->once()) |
|
| 2118 | + ->method('newFile') |
|
| 2119 | + ->with('apps.json') |
|
| 2120 | + ->willReturn($file); |
|
| 2121 | + $this->appData |
|
| 2122 | + ->expects($this->once()) |
|
| 2123 | + ->method('getFolder') |
|
| 2124 | + ->with('/') |
|
| 2125 | + ->willReturn($folder); |
|
| 2126 | + $client = $this->createMock(IClient::class); |
|
| 2127 | + $this->clientService |
|
| 2128 | + ->expects($this->once()) |
|
| 2129 | + ->method('newClient') |
|
| 2130 | + ->willReturn($client); |
|
| 2131 | + $response = $this->createMock(IResponse::class); |
|
| 2132 | + $client |
|
| 2133 | + ->expects($this->once()) |
|
| 2134 | + ->method('get') |
|
| 2135 | + ->with('https://apps.nextcloud.com/api/v1/apps.json', [ |
|
| 2136 | + 'timeout' => 120, |
|
| 2137 | + 'headers' => [ |
|
| 2138 | + 'X-NC-Subscription-Key' => 'subscription-key', |
|
| 2139 | + ], |
|
| 2140 | + ]) |
|
| 2141 | + ->willReturn($response); |
|
| 2142 | + $response |
|
| 2143 | + ->expects($this->once()) |
|
| 2144 | + ->method('getBody') |
|
| 2145 | + ->willReturn(self::$responseJson); |
|
| 2146 | + $response->method('getHeader') |
|
| 2147 | + ->with($this->equalTo('ETag')) |
|
| 2148 | + ->willReturn('"myETag"'); |
|
| 2149 | + $this->timeFactory |
|
| 2150 | + ->expects($this->once()) |
|
| 2151 | + ->method('getTime') |
|
| 2152 | + ->willReturn(1234); |
|
| 2153 | + |
|
| 2154 | + $this->registry |
|
| 2155 | + ->expects($this->exactly(2)) |
|
| 2156 | + ->method('delegateHasValidSubscription') |
|
| 2157 | + ->willReturn(true); |
|
| 2158 | + |
|
| 2159 | + $file |
|
| 2160 | + ->expects($this->once()) |
|
| 2161 | + ->method('putContent'); |
|
| 2162 | + $file |
|
| 2163 | + ->method('getContent') |
|
| 2164 | + ->willReturn(json_encode(self::$expectedResponse)); |
|
| 2165 | + |
|
| 2166 | + $apps = array_values($this->fetcher->get()); |
|
| 2167 | + $this->assertEquals(count($apps), 1); |
|
| 2168 | + $this->assertEquals($apps[0]['id'], 'contacts'); |
|
| 2169 | + } |
|
| 2170 | + |
|
| 2171 | + public function testGetAppsAllowlistCustomAppstore(): void { |
|
| 2172 | + $this->config->method('getSystemValueString') |
|
| 2173 | + ->willReturnCallback(function ($key, $default) { |
|
| 2174 | + if ($key === 'version') { |
|
| 2175 | + return '11.0.0.2'; |
|
| 2176 | + } elseif ($key === 'appstoreurl' && $default === 'https://apps.nextcloud.com/api/v1') { |
|
| 2177 | + return 'https://custom.appsstore.endpoint/api/v1'; |
|
| 2178 | + } else { |
|
| 2179 | + return $default; |
|
| 2180 | + } |
|
| 2181 | + }); |
|
| 2182 | + $this->config->method('getSystemValue') |
|
| 2183 | + ->willReturnCallback(function ($key, $default) { |
|
| 2184 | + if ($key === 'appsallowlist') { |
|
| 2185 | + return ['contacts']; |
|
| 2186 | + } else { |
|
| 2187 | + return $default; |
|
| 2188 | + } |
|
| 2189 | + }); |
|
| 2190 | + $this->config |
|
| 2191 | + ->method('getSystemValueBool') |
|
| 2192 | + ->willReturnArgument(1); |
|
| 2193 | + |
|
| 2194 | + $this->config->method('getAppValue') |
|
| 2195 | + ->willReturnMap([ |
|
| 2196 | + ['settings', 'appstore-fetcher-lastFailure', '0', '0'], |
|
| 2197 | + ['settings', 'appstore-timeout', '120', '120'], |
|
| 2198 | + ]); |
|
| 2199 | + |
|
| 2200 | + $file = $this->createMock(ISimpleFile::class); |
|
| 2201 | + $folder = $this->createMock(ISimpleFolder::class); |
|
| 2202 | + $folder |
|
| 2203 | + ->expects($this->once()) |
|
| 2204 | + ->method('getFile') |
|
| 2205 | + ->with('apps.json') |
|
| 2206 | + ->willThrowException(new NotFoundException()); |
|
| 2207 | + $folder |
|
| 2208 | + ->expects($this->once()) |
|
| 2209 | + ->method('newFile') |
|
| 2210 | + ->with('apps.json') |
|
| 2211 | + ->willReturn($file); |
|
| 2212 | + $this->appData |
|
| 2213 | + ->expects($this->once()) |
|
| 2214 | + ->method('getFolder') |
|
| 2215 | + ->with('/') |
|
| 2216 | + ->willReturn($folder); |
|
| 2217 | + $client = $this->createMock(IClient::class); |
|
| 2218 | + $this->clientService |
|
| 2219 | + ->expects($this->once()) |
|
| 2220 | + ->method('newClient') |
|
| 2221 | + ->willReturn($client); |
|
| 2222 | + $response = $this->createMock(IResponse::class); |
|
| 2223 | + $client |
|
| 2224 | + ->expects($this->once()) |
|
| 2225 | + ->method('get') |
|
| 2226 | + ->with('https://custom.appsstore.endpoint/api/v1/apps.json', [ |
|
| 2227 | + 'timeout' => 120, |
|
| 2228 | + ]) |
|
| 2229 | + ->willReturn($response); |
|
| 2230 | + $response |
|
| 2231 | + ->expects($this->once()) |
|
| 2232 | + ->method('getBody') |
|
| 2233 | + ->willReturn(self::$responseJson); |
|
| 2234 | + $response->method('getHeader') |
|
| 2235 | + ->with($this->equalTo('ETag')) |
|
| 2236 | + ->willReturn('"myETag"'); |
|
| 2237 | + $this->timeFactory |
|
| 2238 | + ->expects($this->once()) |
|
| 2239 | + ->method('getTime') |
|
| 2240 | + ->willReturn(1234); |
|
| 2241 | + |
|
| 2242 | + $this->registry |
|
| 2243 | + ->expects($this->exactly(1)) |
|
| 2244 | + ->method('delegateHasValidSubscription') |
|
| 2245 | + ->willReturn(true); |
|
| 2246 | + |
|
| 2247 | + $file |
|
| 2248 | + ->expects($this->once()) |
|
| 2249 | + ->method('putContent'); |
|
| 2250 | + $file |
|
| 2251 | + ->method('getContent') |
|
| 2252 | + ->willReturn(json_encode(self::$expectedResponse)); |
|
| 2253 | + |
|
| 2254 | + $apps = array_values($this->fetcher->get()); |
|
| 2255 | + $this->assertEquals(count($apps), 1); |
|
| 2256 | + $this->assertEquals($apps[0]['id'], 'contacts'); |
|
| 2257 | + } |
|
| 2258 | 2258 | } |
@@ -24,670 +24,670 @@ |
||
| 24 | 24 | use Test\TestCase; |
| 25 | 25 | |
| 26 | 26 | abstract class FetcherBase extends TestCase { |
| 27 | - /** @var Factory|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 28 | - protected $appDataFactory; |
|
| 29 | - /** @var IAppData|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 30 | - protected $appData; |
|
| 31 | - /** @var IClientService|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 32 | - protected $clientService; |
|
| 33 | - /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 34 | - protected $timeFactory; |
|
| 35 | - /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 36 | - protected $config; |
|
| 37 | - /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 38 | - protected $logger; |
|
| 39 | - /** @var IRegistry|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 40 | - protected $registry; |
|
| 41 | - /** @var Fetcher */ |
|
| 42 | - protected $fetcher; |
|
| 43 | - /** @var string */ |
|
| 44 | - protected $fileName; |
|
| 45 | - /** @var string */ |
|
| 46 | - protected $endpoint; |
|
| 47 | - |
|
| 48 | - protected function setUp(): void { |
|
| 49 | - parent::setUp(); |
|
| 50 | - $this->appDataFactory = $this->createMock(Factory::class); |
|
| 51 | - $this->appData = $this->createMock(AppData::class); |
|
| 52 | - $this->appDataFactory->expects($this->once()) |
|
| 53 | - ->method('get') |
|
| 54 | - ->with('appstore') |
|
| 55 | - ->willReturn($this->appData); |
|
| 56 | - $this->clientService = $this->createMock(IClientService::class); |
|
| 57 | - $this->timeFactory = $this->createMock(ITimeFactory::class); |
|
| 58 | - $this->config = $this->createMock(IConfig::class); |
|
| 59 | - $this->logger = $this->createMock(LoggerInterface::class); |
|
| 60 | - $this->registry = $this->createMock(IRegistry::class); |
|
| 61 | - } |
|
| 62 | - |
|
| 63 | - public function testGetWithAlreadyExistingFileAndUpToDateTimestampAndVersion(): void { |
|
| 64 | - $this->config |
|
| 65 | - ->method('getSystemValueString') |
|
| 66 | - ->willReturnCallback(function ($var, $default) { |
|
| 67 | - if ($var === 'version') { |
|
| 68 | - return '11.0.0.2'; |
|
| 69 | - } |
|
| 70 | - return $default; |
|
| 71 | - }); |
|
| 72 | - $this->config->method('getSystemValueBool') |
|
| 73 | - ->willReturnArgument(1); |
|
| 74 | - |
|
| 75 | - $folder = $this->createMock(ISimpleFolder::class); |
|
| 76 | - $file = $this->createMock(ISimpleFile::class); |
|
| 77 | - $this->appData |
|
| 78 | - ->expects($this->once()) |
|
| 79 | - ->method('getFolder') |
|
| 80 | - ->with('/') |
|
| 81 | - ->willReturn($folder); |
|
| 82 | - $folder |
|
| 83 | - ->expects($this->once()) |
|
| 84 | - ->method('getFile') |
|
| 85 | - ->with($this->fileName) |
|
| 86 | - ->willReturn($file); |
|
| 87 | - $file |
|
| 88 | - ->expects($this->once()) |
|
| 89 | - ->method('getContent') |
|
| 90 | - ->willReturn('{"timestamp":1200,"data":[{"id":"MyApp"}],"ncversion":"11.0.0.2"}'); |
|
| 91 | - $this->timeFactory |
|
| 92 | - ->expects($this->once()) |
|
| 93 | - ->method('getTime') |
|
| 94 | - ->willReturn(1499); |
|
| 95 | - |
|
| 96 | - $expected = [ |
|
| 97 | - [ |
|
| 98 | - 'id' => 'MyApp', |
|
| 99 | - ], |
|
| 100 | - ]; |
|
| 101 | - $this->assertSame($expected, $this->fetcher->get()); |
|
| 102 | - } |
|
| 103 | - |
|
| 104 | - public function testGetWithNotExistingFileAndUpToDateTimestampAndVersion(): void { |
|
| 105 | - $this->config |
|
| 106 | - ->method('getSystemValueString') |
|
| 107 | - ->willReturnCallback(function ($var, $default) { |
|
| 108 | - if ($var === 'appstoreurl') { |
|
| 109 | - return 'https://apps.nextcloud.com/api/v1'; |
|
| 110 | - } elseif ($var === 'version') { |
|
| 111 | - return '11.0.0.2'; |
|
| 112 | - } |
|
| 113 | - return $default; |
|
| 114 | - }); |
|
| 115 | - $this->config->method('getSystemValueBool') |
|
| 116 | - ->willReturnArgument(1); |
|
| 117 | - |
|
| 118 | - $folder = $this->createMock(ISimpleFolder::class); |
|
| 119 | - $file = $this->createMock(ISimpleFile::class); |
|
| 120 | - $this->appData |
|
| 121 | - ->expects($this->once()) |
|
| 122 | - ->method('getFolder') |
|
| 123 | - ->with('/') |
|
| 124 | - ->willReturn($folder); |
|
| 125 | - $folder |
|
| 126 | - ->expects($this->once()) |
|
| 127 | - ->method('getFile') |
|
| 128 | - ->with($this->fileName) |
|
| 129 | - ->willThrowException(new NotFoundException()); |
|
| 130 | - $folder |
|
| 131 | - ->expects($this->once()) |
|
| 132 | - ->method('newFile') |
|
| 133 | - ->with($this->fileName) |
|
| 134 | - ->willReturn($file); |
|
| 135 | - $client = $this->createMock(IClient::class); |
|
| 136 | - $this->clientService |
|
| 137 | - ->expects($this->once()) |
|
| 138 | - ->method('newClient') |
|
| 139 | - ->willReturn($client); |
|
| 140 | - $response = $this->createMock(IResponse::class); |
|
| 141 | - $client |
|
| 142 | - ->expects($this->once()) |
|
| 143 | - ->method('get') |
|
| 144 | - ->with($this->endpoint) |
|
| 145 | - ->willReturn($response); |
|
| 146 | - $response |
|
| 147 | - ->expects($this->once()) |
|
| 148 | - ->method('getBody') |
|
| 149 | - ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]'); |
|
| 150 | - $response->method('getHeader') |
|
| 151 | - ->with($this->equalTo('ETag')) |
|
| 152 | - ->willReturn('"myETag"'); |
|
| 153 | - $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1502,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
| 154 | - $file |
|
| 155 | - ->expects($this->once()) |
|
| 156 | - ->method('putContent') |
|
| 157 | - ->with($fileData); |
|
| 158 | - $file |
|
| 159 | - ->expects($this->once()) |
|
| 160 | - ->method('getContent') |
|
| 161 | - ->willReturn($fileData); |
|
| 162 | - $this->timeFactory |
|
| 163 | - ->expects($this->once()) |
|
| 164 | - ->method('getTime') |
|
| 165 | - ->willReturn(1502); |
|
| 166 | - |
|
| 167 | - $expected = [ |
|
| 168 | - [ |
|
| 169 | - 'id' => 'MyNewApp', |
|
| 170 | - 'foo' => 'foo', |
|
| 171 | - ], |
|
| 172 | - [ |
|
| 173 | - 'id' => 'bar', |
|
| 174 | - ], |
|
| 175 | - ]; |
|
| 176 | - $this->assertSame($expected, $this->fetcher->get()); |
|
| 177 | - } |
|
| 178 | - |
|
| 179 | - public function testGetWithAlreadyExistingFileAndOutdatedTimestamp(): void { |
|
| 180 | - $this->config->method('getSystemValueString') |
|
| 181 | - ->willReturnCallback(function ($key, $default) { |
|
| 182 | - if ($key === 'version') { |
|
| 183 | - return '11.0.0.2'; |
|
| 184 | - } else { |
|
| 185 | - return $default; |
|
| 186 | - } |
|
| 187 | - }); |
|
| 188 | - $this->config->method('getSystemValueBool') |
|
| 189 | - ->willReturnArgument(1); |
|
| 190 | - |
|
| 191 | - $folder = $this->createMock(ISimpleFolder::class); |
|
| 192 | - $file = $this->createMock(ISimpleFile::class); |
|
| 193 | - $this->appData |
|
| 194 | - ->expects($this->once()) |
|
| 195 | - ->method('getFolder') |
|
| 196 | - ->with('/') |
|
| 197 | - ->willReturn($folder); |
|
| 198 | - $folder |
|
| 199 | - ->expects($this->once()) |
|
| 200 | - ->method('getFile') |
|
| 201 | - ->with($this->fileName) |
|
| 202 | - ->willReturn($file); |
|
| 203 | - $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1502,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
| 204 | - $file |
|
| 205 | - ->expects($this->once()) |
|
| 206 | - ->method('putContent') |
|
| 207 | - ->with($fileData); |
|
| 208 | - $file |
|
| 209 | - ->expects($this->exactly(2)) |
|
| 210 | - ->method('getContent') |
|
| 211 | - ->willReturnOnConsecutiveCalls( |
|
| 212 | - '{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}},"ncversion":"11.0.0.2"}', |
|
| 213 | - $fileData |
|
| 214 | - ); |
|
| 215 | - $this->timeFactory |
|
| 216 | - ->expects($this->exactly(2)) |
|
| 217 | - ->method('getTime') |
|
| 218 | - ->willReturnOnConsecutiveCalls( |
|
| 219 | - 4801, |
|
| 220 | - 1502 |
|
| 221 | - ); |
|
| 222 | - $client = $this->createMock(IClient::class); |
|
| 223 | - $this->clientService |
|
| 224 | - ->expects($this->once()) |
|
| 225 | - ->method('newClient') |
|
| 226 | - ->willReturn($client); |
|
| 227 | - $response = $this->createMock(IResponse::class); |
|
| 228 | - $client |
|
| 229 | - ->expects($this->once()) |
|
| 230 | - ->method('get') |
|
| 231 | - ->with($this->endpoint) |
|
| 232 | - ->willReturn($response); |
|
| 233 | - $response |
|
| 234 | - ->expects($this->once()) |
|
| 235 | - ->method('getBody') |
|
| 236 | - ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]'); |
|
| 237 | - $response->method('getHeader') |
|
| 238 | - ->with($this->equalTo('ETag')) |
|
| 239 | - ->willReturn('"myETag"'); |
|
| 240 | - |
|
| 241 | - $expected = [ |
|
| 242 | - [ |
|
| 243 | - 'id' => 'MyNewApp', |
|
| 244 | - 'foo' => 'foo', |
|
| 245 | - ], |
|
| 246 | - [ |
|
| 247 | - 'id' => 'bar', |
|
| 248 | - ], |
|
| 249 | - ]; |
|
| 250 | - $this->assertSame($expected, $this->fetcher->get()); |
|
| 251 | - } |
|
| 252 | - |
|
| 253 | - public function testGetWithAlreadyExistingFileAndNoVersion(): void { |
|
| 254 | - $this->config |
|
| 255 | - ->method('getSystemValueString') |
|
| 256 | - ->willReturnCallback(function ($var, $default) { |
|
| 257 | - if ($var === 'appstoreurl') { |
|
| 258 | - return 'https://apps.nextcloud.com/api/v1'; |
|
| 259 | - } elseif ($var === 'version') { |
|
| 260 | - return '11.0.0.2'; |
|
| 261 | - } |
|
| 262 | - return $default; |
|
| 263 | - }); |
|
| 264 | - $this->config->method('getSystemValueBool') |
|
| 265 | - ->willReturnArgument(1); |
|
| 266 | - |
|
| 267 | - $folder = $this->createMock(ISimpleFolder::class); |
|
| 268 | - $file = $this->createMock(ISimpleFile::class); |
|
| 269 | - $this->appData |
|
| 270 | - ->expects($this->once()) |
|
| 271 | - ->method('getFolder') |
|
| 272 | - ->with('/') |
|
| 273 | - ->willReturn($folder); |
|
| 274 | - $folder |
|
| 275 | - ->expects($this->once()) |
|
| 276 | - ->method('getFile') |
|
| 277 | - ->with($this->fileName) |
|
| 278 | - ->willReturn($file); |
|
| 279 | - $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1201,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
| 280 | - $file |
|
| 281 | - ->expects($this->once()) |
|
| 282 | - ->method('putContent') |
|
| 283 | - ->with($fileData); |
|
| 284 | - $file |
|
| 285 | - ->expects($this->exactly(2)) |
|
| 286 | - ->method('getContent') |
|
| 287 | - ->willReturnOnConsecutiveCalls( |
|
| 288 | - '{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}}', |
|
| 289 | - $fileData |
|
| 290 | - ); |
|
| 291 | - $this->timeFactory |
|
| 292 | - ->expects($this->once()) |
|
| 293 | - ->method('getTime') |
|
| 294 | - ->willReturn(1201); |
|
| 295 | - $client = $this->createMock(IClient::class); |
|
| 296 | - $this->clientService |
|
| 297 | - ->expects($this->once()) |
|
| 298 | - ->method('newClient') |
|
| 299 | - ->willReturn($client); |
|
| 300 | - $response = $this->createMock(IResponse::class); |
|
| 301 | - $client |
|
| 302 | - ->expects($this->once()) |
|
| 303 | - ->method('get') |
|
| 304 | - ->with($this->endpoint) |
|
| 305 | - ->willReturn($response); |
|
| 306 | - $response |
|
| 307 | - ->expects($this->once()) |
|
| 308 | - ->method('getBody') |
|
| 309 | - ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]'); |
|
| 310 | - $response->method('getHeader') |
|
| 311 | - ->with($this->equalTo('ETag')) |
|
| 312 | - ->willReturn('"myETag"'); |
|
| 313 | - |
|
| 314 | - $expected = [ |
|
| 315 | - [ |
|
| 316 | - 'id' => 'MyNewApp', |
|
| 317 | - 'foo' => 'foo', |
|
| 318 | - ], |
|
| 319 | - [ |
|
| 320 | - 'id' => 'bar', |
|
| 321 | - ], |
|
| 322 | - ]; |
|
| 323 | - $this->assertSame($expected, $this->fetcher->get()); |
|
| 324 | - } |
|
| 325 | - |
|
| 326 | - public function testGetWithAlreadyExistingFileAndOutdatedVersion(): void { |
|
| 327 | - $this->config |
|
| 328 | - ->method('getSystemValueString') |
|
| 329 | - ->willReturnCallback(function ($var, $default) { |
|
| 330 | - if ($var === 'appstoreurl') { |
|
| 331 | - return 'https://apps.nextcloud.com/api/v1'; |
|
| 332 | - } elseif ($var === 'version') { |
|
| 333 | - return '11.0.0.2'; |
|
| 334 | - } |
|
| 335 | - return $default; |
|
| 336 | - }); |
|
| 337 | - $this->config->method('getSystemValueBool') |
|
| 338 | - ->willReturnArgument(1); |
|
| 339 | - |
|
| 340 | - $folder = $this->createMock(ISimpleFolder::class); |
|
| 341 | - $file = $this->createMock(ISimpleFile::class); |
|
| 342 | - $this->appData |
|
| 343 | - ->expects($this->once()) |
|
| 344 | - ->method('getFolder') |
|
| 345 | - ->with('/') |
|
| 346 | - ->willReturn($folder); |
|
| 347 | - $folder |
|
| 348 | - ->expects($this->once()) |
|
| 349 | - ->method('getFile') |
|
| 350 | - ->with($this->fileName) |
|
| 351 | - ->willReturn($file); |
|
| 352 | - $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1201,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
| 353 | - $file |
|
| 354 | - ->expects($this->once()) |
|
| 355 | - ->method('putContent') |
|
| 356 | - ->with($fileData); |
|
| 357 | - $file |
|
| 358 | - ->expects($this->exactly(2)) |
|
| 359 | - ->method('getContent') |
|
| 360 | - ->willReturnOnConsecutiveCalls( |
|
| 361 | - '{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}},"ncversion":"11.0.0.1"', |
|
| 362 | - $fileData |
|
| 363 | - ); |
|
| 364 | - $this->timeFactory |
|
| 365 | - ->method('getTime') |
|
| 366 | - ->willReturn(1201); |
|
| 367 | - $client = $this->createMock(IClient::class); |
|
| 368 | - $this->clientService |
|
| 369 | - ->expects($this->once()) |
|
| 370 | - ->method('newClient') |
|
| 371 | - ->willReturn($client); |
|
| 372 | - $response = $this->createMock(IResponse::class); |
|
| 373 | - $client |
|
| 374 | - ->expects($this->once()) |
|
| 375 | - ->method('get') |
|
| 376 | - ->with($this->endpoint) |
|
| 377 | - ->willReturn($response); |
|
| 378 | - $response |
|
| 379 | - ->expects($this->once()) |
|
| 380 | - ->method('getBody') |
|
| 381 | - ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]'); |
|
| 382 | - $response->method('getHeader') |
|
| 383 | - ->with($this->equalTo('ETag')) |
|
| 384 | - ->willReturn('"myETag"'); |
|
| 385 | - |
|
| 386 | - $expected = [ |
|
| 387 | - [ |
|
| 388 | - 'id' => 'MyNewApp', |
|
| 389 | - 'foo' => 'foo', |
|
| 390 | - ], |
|
| 391 | - [ |
|
| 392 | - 'id' => 'bar', |
|
| 393 | - ], |
|
| 394 | - ]; |
|
| 395 | - $this->assertSame($expected, $this->fetcher->get()); |
|
| 396 | - } |
|
| 397 | - |
|
| 398 | - public function testGetWithExceptionInClient(): void { |
|
| 399 | - $this->config->method('getSystemValueString') |
|
| 400 | - ->willReturnArgument(1); |
|
| 401 | - $this->config->method('getSystemValueBool') |
|
| 402 | - ->willReturnArgument(1); |
|
| 403 | - |
|
| 404 | - $folder = $this->createMock(ISimpleFolder::class); |
|
| 405 | - $file = $this->createMock(ISimpleFile::class); |
|
| 406 | - $this->appData |
|
| 407 | - ->expects($this->once()) |
|
| 408 | - ->method('getFolder') |
|
| 409 | - ->with('/') |
|
| 410 | - ->willReturn($folder); |
|
| 411 | - $folder |
|
| 412 | - ->expects($this->once()) |
|
| 413 | - ->method('getFile') |
|
| 414 | - ->with($this->fileName) |
|
| 415 | - ->willReturn($file); |
|
| 416 | - $file |
|
| 417 | - ->expects($this->once()) |
|
| 418 | - ->method('getContent') |
|
| 419 | - ->willReturn('{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}}}'); |
|
| 420 | - $client = $this->createMock(IClient::class); |
|
| 421 | - $this->clientService |
|
| 422 | - ->expects($this->once()) |
|
| 423 | - ->method('newClient') |
|
| 424 | - ->willReturn($client); |
|
| 425 | - $client |
|
| 426 | - ->expects($this->once()) |
|
| 427 | - ->method('get') |
|
| 428 | - ->with($this->endpoint) |
|
| 429 | - ->willThrowException(new \Exception()); |
|
| 430 | - |
|
| 431 | - $this->assertSame([], $this->fetcher->get()); |
|
| 432 | - } |
|
| 433 | - |
|
| 434 | - public function testGetMatchingETag(): void { |
|
| 435 | - $this->config->method('getSystemValueString') |
|
| 436 | - ->willReturnCallback(function ($key, $default) { |
|
| 437 | - if ($key === 'version') { |
|
| 438 | - return '11.0.0.2'; |
|
| 439 | - } else { |
|
| 440 | - return $default; |
|
| 441 | - } |
|
| 442 | - }); |
|
| 443 | - $this->config->method('getSystemValueBool') |
|
| 444 | - ->willReturnArgument(1); |
|
| 445 | - |
|
| 446 | - $this->config->method('getAppValue') |
|
| 447 | - ->willReturnMap([ |
|
| 448 | - ['settings', 'appstore-fetcher-lastFailure', '0', '0'], |
|
| 449 | - ['settings', 'appstore-timeout', '120', '120'], |
|
| 450 | - ]); |
|
| 451 | - |
|
| 452 | - $folder = $this->createMock(ISimpleFolder::class); |
|
| 453 | - $file = $this->createMock(ISimpleFile::class); |
|
| 454 | - $this->appData |
|
| 455 | - ->expects($this->once()) |
|
| 456 | - ->method('getFolder') |
|
| 457 | - ->with('/') |
|
| 458 | - ->willReturn($folder); |
|
| 459 | - $folder |
|
| 460 | - ->expects($this->once()) |
|
| 461 | - ->method('getFile') |
|
| 462 | - ->with($this->fileName) |
|
| 463 | - ->willReturn($file); |
|
| 464 | - $origData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1200,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
| 465 | - |
|
| 466 | - $newData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":4802,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
| 467 | - $file |
|
| 468 | - ->expects($this->once()) |
|
| 469 | - ->method('putContent') |
|
| 470 | - ->with($newData); |
|
| 471 | - $file |
|
| 472 | - ->expects($this->exactly(2)) |
|
| 473 | - ->method('getContent') |
|
| 474 | - ->willReturnOnConsecutiveCalls( |
|
| 475 | - $origData, |
|
| 476 | - $newData, |
|
| 477 | - ); |
|
| 478 | - $this->timeFactory |
|
| 479 | - ->expects($this->exactly(2)) |
|
| 480 | - ->method('getTime') |
|
| 481 | - ->willReturnOnConsecutiveCalls( |
|
| 482 | - 4801, |
|
| 483 | - 4802 |
|
| 484 | - ); |
|
| 485 | - $client = $this->createMock(IClient::class); |
|
| 486 | - $this->clientService |
|
| 487 | - ->expects($this->once()) |
|
| 488 | - ->method('newClient') |
|
| 489 | - ->willReturn($client); |
|
| 490 | - $response = $this->createMock(IResponse::class); |
|
| 491 | - $client |
|
| 492 | - ->expects($this->once()) |
|
| 493 | - ->method('get') |
|
| 494 | - ->with( |
|
| 495 | - $this->equalTo($this->endpoint), |
|
| 496 | - $this->equalTo([ |
|
| 497 | - 'timeout' => 120, |
|
| 498 | - 'headers' => [ |
|
| 499 | - 'If-None-Match' => '"myETag"' |
|
| 500 | - ] |
|
| 501 | - ]) |
|
| 502 | - )->willReturn($response); |
|
| 503 | - $response->method('getStatusCode') |
|
| 504 | - ->willReturn(304); |
|
| 505 | - |
|
| 506 | - $expected = [ |
|
| 507 | - [ |
|
| 508 | - 'id' => 'MyNewApp', |
|
| 509 | - 'foo' => 'foo', |
|
| 510 | - ], |
|
| 511 | - [ |
|
| 512 | - 'id' => 'bar', |
|
| 513 | - ], |
|
| 514 | - ]; |
|
| 515 | - |
|
| 516 | - $this->assertSame($expected, $this->fetcher->get()); |
|
| 517 | - } |
|
| 518 | - |
|
| 519 | - public function testGetNoMatchingETag(): void { |
|
| 520 | - $this->config->method('getSystemValueString') |
|
| 521 | - ->willReturnCallback(function ($key, $default) { |
|
| 522 | - if ($key === 'version') { |
|
| 523 | - return '11.0.0.2'; |
|
| 524 | - } else { |
|
| 525 | - return $default; |
|
| 526 | - } |
|
| 527 | - }); |
|
| 528 | - $this->config->method('getSystemValueBool') |
|
| 529 | - ->willReturnArgument(1); |
|
| 530 | - |
|
| 531 | - $this->config->method('getAppValue') |
|
| 532 | - ->willReturnMap([ |
|
| 533 | - ['settings', 'appstore-fetcher-lastFailure', '0', '0'], |
|
| 534 | - ['settings', 'appstore-timeout', '120', '120'], |
|
| 535 | - ]); |
|
| 536 | - |
|
| 537 | - $folder = $this->createMock(ISimpleFolder::class); |
|
| 538 | - $file = $this->createMock(ISimpleFile::class); |
|
| 539 | - $this->appData |
|
| 540 | - ->expects($this->once()) |
|
| 541 | - ->method('getFolder') |
|
| 542 | - ->with('/') |
|
| 543 | - ->willReturn($folder); |
|
| 544 | - $folder |
|
| 545 | - ->expects($this->once()) |
|
| 546 | - ->method('getFile') |
|
| 547 | - ->with($this->fileName) |
|
| 548 | - ->willReturn($file); |
|
| 549 | - $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":4802,"ncversion":"11.0.0.2","ETag":"\"newETag\""}'; |
|
| 550 | - $file |
|
| 551 | - ->expects($this->once()) |
|
| 552 | - ->method('putContent') |
|
| 553 | - ->with($fileData); |
|
| 554 | - $file |
|
| 555 | - ->expects($this->exactly(2)) |
|
| 556 | - ->method('getContent') |
|
| 557 | - ->willReturnOnConsecutiveCalls( |
|
| 558 | - '{"data":[{"id":"MyOldApp","abc":"def"}],"timestamp":1200,"ncversion":"11.0.0.2","ETag":"\"myETag\""}', |
|
| 559 | - $fileData, |
|
| 560 | - ); |
|
| 561 | - $this->timeFactory |
|
| 562 | - ->expects($this->exactly(2)) |
|
| 563 | - ->method('getTime') |
|
| 564 | - ->willReturnOnConsecutiveCalls( |
|
| 565 | - 4801, |
|
| 566 | - 4802, |
|
| 567 | - ); |
|
| 568 | - $client = $this->createMock(IClient::class); |
|
| 569 | - $this->clientService |
|
| 570 | - ->expects($this->once()) |
|
| 571 | - ->method('newClient') |
|
| 572 | - ->willReturn($client); |
|
| 573 | - $response = $this->createMock(IResponse::class); |
|
| 574 | - $client |
|
| 575 | - ->expects($this->once()) |
|
| 576 | - ->method('get') |
|
| 577 | - ->with( |
|
| 578 | - $this->equalTo($this->endpoint), |
|
| 579 | - $this->equalTo([ |
|
| 580 | - 'timeout' => 120, |
|
| 581 | - 'headers' => [ |
|
| 582 | - 'If-None-Match' => '"myETag"', |
|
| 583 | - ] |
|
| 584 | - ]) |
|
| 585 | - ) |
|
| 586 | - ->willReturn($response); |
|
| 587 | - $response->method('getStatusCode') |
|
| 588 | - ->willReturn(200); |
|
| 589 | - $response |
|
| 590 | - ->expects($this->once()) |
|
| 591 | - ->method('getBody') |
|
| 592 | - ->willReturn('[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}]'); |
|
| 593 | - $response->method('getHeader') |
|
| 594 | - ->with($this->equalTo('ETag')) |
|
| 595 | - ->willReturn('"newETag"'); |
|
| 596 | - |
|
| 597 | - $expected = [ |
|
| 598 | - [ |
|
| 599 | - 'id' => 'MyNewApp', |
|
| 600 | - 'foo' => 'foo', |
|
| 601 | - ], |
|
| 602 | - [ |
|
| 603 | - 'id' => 'bar', |
|
| 604 | - ], |
|
| 605 | - ]; |
|
| 606 | - $this->assertSame($expected, $this->fetcher->get()); |
|
| 607 | - } |
|
| 608 | - |
|
| 609 | - |
|
| 610 | - public function testFetchAfterUpgradeNoETag(): void { |
|
| 611 | - $this->config->method('getSystemValueString') |
|
| 612 | - ->willReturnCallback(function ($key, $default) { |
|
| 613 | - if ($key === 'version') { |
|
| 614 | - return '11.0.0.3'; |
|
| 615 | - } else { |
|
| 616 | - return $default; |
|
| 617 | - } |
|
| 618 | - }); |
|
| 619 | - $this->config->method('getSystemValueBool') |
|
| 620 | - ->willReturnArgument(1); |
|
| 621 | - |
|
| 622 | - $this->config->method('getAppValue') |
|
| 623 | - ->willReturnMap([ |
|
| 624 | - ['settings', 'appstore-fetcher-lastFailure', '0', '0'], |
|
| 625 | - ['settings', 'appstore-timeout', '120', '120'], |
|
| 626 | - ]); |
|
| 627 | - |
|
| 628 | - $folder = $this->createMock(ISimpleFolder::class); |
|
| 629 | - $file = $this->createMock(ISimpleFile::class); |
|
| 630 | - $this->appData |
|
| 631 | - ->expects($this->once()) |
|
| 632 | - ->method('getFolder') |
|
| 633 | - ->with('/') |
|
| 634 | - ->willReturn($folder); |
|
| 635 | - $folder |
|
| 636 | - ->expects($this->once()) |
|
| 637 | - ->method('getFile') |
|
| 638 | - ->with($this->fileName) |
|
| 639 | - ->willReturn($file); |
|
| 640 | - $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1501,"ncversion":"11.0.0.3","ETag":"\"newETag\""}'; |
|
| 641 | - $file |
|
| 642 | - ->expects($this->once()) |
|
| 643 | - ->method('putContent') |
|
| 644 | - ->with($fileData); |
|
| 645 | - $file |
|
| 646 | - ->expects($this->exactly(2)) |
|
| 647 | - ->method('getContent') |
|
| 648 | - ->willReturnOnConsecutiveCalls( |
|
| 649 | - '{"data":[{"id":"MyOldApp","abc":"def"}],"timestamp":1200,"ncversion":"11.0.0.2","ETag":"\"myETag\""}', |
|
| 650 | - $fileData |
|
| 651 | - ); |
|
| 652 | - $client = $this->createMock(IClient::class); |
|
| 653 | - $this->clientService |
|
| 654 | - ->expects($this->once()) |
|
| 655 | - ->method('newClient') |
|
| 656 | - ->willReturn($client); |
|
| 657 | - $response = $this->createMock(IResponse::class); |
|
| 658 | - $client |
|
| 659 | - ->expects($this->once()) |
|
| 660 | - ->method('get') |
|
| 661 | - ->with( |
|
| 662 | - $this->equalTo($this->endpoint), |
|
| 663 | - $this->equalTo([ |
|
| 664 | - 'timeout' => 120, |
|
| 665 | - ]) |
|
| 666 | - ) |
|
| 667 | - ->willReturn($response); |
|
| 668 | - $response->method('getStatusCode') |
|
| 669 | - ->willReturn(200); |
|
| 670 | - $response |
|
| 671 | - ->expects($this->once()) |
|
| 672 | - ->method('getBody') |
|
| 673 | - ->willReturn('[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}]'); |
|
| 674 | - $response->method('getHeader') |
|
| 675 | - ->with($this->equalTo('ETag')) |
|
| 676 | - ->willReturn('"newETag"'); |
|
| 677 | - $this->timeFactory |
|
| 678 | - ->expects($this->once()) |
|
| 679 | - ->method('getTime') |
|
| 680 | - ->willReturn(1501); |
|
| 681 | - |
|
| 682 | - $expected = [ |
|
| 683 | - [ |
|
| 684 | - 'id' => 'MyNewApp', |
|
| 685 | - 'foo' => 'foo', |
|
| 686 | - ], |
|
| 687 | - [ |
|
| 688 | - 'id' => 'bar', |
|
| 689 | - ], |
|
| 690 | - ]; |
|
| 691 | - $this->assertSame($expected, $this->fetcher->get()); |
|
| 692 | - } |
|
| 27 | + /** @var Factory|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 28 | + protected $appDataFactory; |
|
| 29 | + /** @var IAppData|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 30 | + protected $appData; |
|
| 31 | + /** @var IClientService|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 32 | + protected $clientService; |
|
| 33 | + /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 34 | + protected $timeFactory; |
|
| 35 | + /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 36 | + protected $config; |
|
| 37 | + /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 38 | + protected $logger; |
|
| 39 | + /** @var IRegistry|\PHPUnit\Framework\MockObject\MockObject */ |
|
| 40 | + protected $registry; |
|
| 41 | + /** @var Fetcher */ |
|
| 42 | + protected $fetcher; |
|
| 43 | + /** @var string */ |
|
| 44 | + protected $fileName; |
|
| 45 | + /** @var string */ |
|
| 46 | + protected $endpoint; |
|
| 47 | + |
|
| 48 | + protected function setUp(): void { |
|
| 49 | + parent::setUp(); |
|
| 50 | + $this->appDataFactory = $this->createMock(Factory::class); |
|
| 51 | + $this->appData = $this->createMock(AppData::class); |
|
| 52 | + $this->appDataFactory->expects($this->once()) |
|
| 53 | + ->method('get') |
|
| 54 | + ->with('appstore') |
|
| 55 | + ->willReturn($this->appData); |
|
| 56 | + $this->clientService = $this->createMock(IClientService::class); |
|
| 57 | + $this->timeFactory = $this->createMock(ITimeFactory::class); |
|
| 58 | + $this->config = $this->createMock(IConfig::class); |
|
| 59 | + $this->logger = $this->createMock(LoggerInterface::class); |
|
| 60 | + $this->registry = $this->createMock(IRegistry::class); |
|
| 61 | + } |
|
| 62 | + |
|
| 63 | + public function testGetWithAlreadyExistingFileAndUpToDateTimestampAndVersion(): void { |
|
| 64 | + $this->config |
|
| 65 | + ->method('getSystemValueString') |
|
| 66 | + ->willReturnCallback(function ($var, $default) { |
|
| 67 | + if ($var === 'version') { |
|
| 68 | + return '11.0.0.2'; |
|
| 69 | + } |
|
| 70 | + return $default; |
|
| 71 | + }); |
|
| 72 | + $this->config->method('getSystemValueBool') |
|
| 73 | + ->willReturnArgument(1); |
|
| 74 | + |
|
| 75 | + $folder = $this->createMock(ISimpleFolder::class); |
|
| 76 | + $file = $this->createMock(ISimpleFile::class); |
|
| 77 | + $this->appData |
|
| 78 | + ->expects($this->once()) |
|
| 79 | + ->method('getFolder') |
|
| 80 | + ->with('/') |
|
| 81 | + ->willReturn($folder); |
|
| 82 | + $folder |
|
| 83 | + ->expects($this->once()) |
|
| 84 | + ->method('getFile') |
|
| 85 | + ->with($this->fileName) |
|
| 86 | + ->willReturn($file); |
|
| 87 | + $file |
|
| 88 | + ->expects($this->once()) |
|
| 89 | + ->method('getContent') |
|
| 90 | + ->willReturn('{"timestamp":1200,"data":[{"id":"MyApp"}],"ncversion":"11.0.0.2"}'); |
|
| 91 | + $this->timeFactory |
|
| 92 | + ->expects($this->once()) |
|
| 93 | + ->method('getTime') |
|
| 94 | + ->willReturn(1499); |
|
| 95 | + |
|
| 96 | + $expected = [ |
|
| 97 | + [ |
|
| 98 | + 'id' => 'MyApp', |
|
| 99 | + ], |
|
| 100 | + ]; |
|
| 101 | + $this->assertSame($expected, $this->fetcher->get()); |
|
| 102 | + } |
|
| 103 | + |
|
| 104 | + public function testGetWithNotExistingFileAndUpToDateTimestampAndVersion(): void { |
|
| 105 | + $this->config |
|
| 106 | + ->method('getSystemValueString') |
|
| 107 | + ->willReturnCallback(function ($var, $default) { |
|
| 108 | + if ($var === 'appstoreurl') { |
|
| 109 | + return 'https://apps.nextcloud.com/api/v1'; |
|
| 110 | + } elseif ($var === 'version') { |
|
| 111 | + return '11.0.0.2'; |
|
| 112 | + } |
|
| 113 | + return $default; |
|
| 114 | + }); |
|
| 115 | + $this->config->method('getSystemValueBool') |
|
| 116 | + ->willReturnArgument(1); |
|
| 117 | + |
|
| 118 | + $folder = $this->createMock(ISimpleFolder::class); |
|
| 119 | + $file = $this->createMock(ISimpleFile::class); |
|
| 120 | + $this->appData |
|
| 121 | + ->expects($this->once()) |
|
| 122 | + ->method('getFolder') |
|
| 123 | + ->with('/') |
|
| 124 | + ->willReturn($folder); |
|
| 125 | + $folder |
|
| 126 | + ->expects($this->once()) |
|
| 127 | + ->method('getFile') |
|
| 128 | + ->with($this->fileName) |
|
| 129 | + ->willThrowException(new NotFoundException()); |
|
| 130 | + $folder |
|
| 131 | + ->expects($this->once()) |
|
| 132 | + ->method('newFile') |
|
| 133 | + ->with($this->fileName) |
|
| 134 | + ->willReturn($file); |
|
| 135 | + $client = $this->createMock(IClient::class); |
|
| 136 | + $this->clientService |
|
| 137 | + ->expects($this->once()) |
|
| 138 | + ->method('newClient') |
|
| 139 | + ->willReturn($client); |
|
| 140 | + $response = $this->createMock(IResponse::class); |
|
| 141 | + $client |
|
| 142 | + ->expects($this->once()) |
|
| 143 | + ->method('get') |
|
| 144 | + ->with($this->endpoint) |
|
| 145 | + ->willReturn($response); |
|
| 146 | + $response |
|
| 147 | + ->expects($this->once()) |
|
| 148 | + ->method('getBody') |
|
| 149 | + ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]'); |
|
| 150 | + $response->method('getHeader') |
|
| 151 | + ->with($this->equalTo('ETag')) |
|
| 152 | + ->willReturn('"myETag"'); |
|
| 153 | + $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1502,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
| 154 | + $file |
|
| 155 | + ->expects($this->once()) |
|
| 156 | + ->method('putContent') |
|
| 157 | + ->with($fileData); |
|
| 158 | + $file |
|
| 159 | + ->expects($this->once()) |
|
| 160 | + ->method('getContent') |
|
| 161 | + ->willReturn($fileData); |
|
| 162 | + $this->timeFactory |
|
| 163 | + ->expects($this->once()) |
|
| 164 | + ->method('getTime') |
|
| 165 | + ->willReturn(1502); |
|
| 166 | + |
|
| 167 | + $expected = [ |
|
| 168 | + [ |
|
| 169 | + 'id' => 'MyNewApp', |
|
| 170 | + 'foo' => 'foo', |
|
| 171 | + ], |
|
| 172 | + [ |
|
| 173 | + 'id' => 'bar', |
|
| 174 | + ], |
|
| 175 | + ]; |
|
| 176 | + $this->assertSame($expected, $this->fetcher->get()); |
|
| 177 | + } |
|
| 178 | + |
|
| 179 | + public function testGetWithAlreadyExistingFileAndOutdatedTimestamp(): void { |
|
| 180 | + $this->config->method('getSystemValueString') |
|
| 181 | + ->willReturnCallback(function ($key, $default) { |
|
| 182 | + if ($key === 'version') { |
|
| 183 | + return '11.0.0.2'; |
|
| 184 | + } else { |
|
| 185 | + return $default; |
|
| 186 | + } |
|
| 187 | + }); |
|
| 188 | + $this->config->method('getSystemValueBool') |
|
| 189 | + ->willReturnArgument(1); |
|
| 190 | + |
|
| 191 | + $folder = $this->createMock(ISimpleFolder::class); |
|
| 192 | + $file = $this->createMock(ISimpleFile::class); |
|
| 193 | + $this->appData |
|
| 194 | + ->expects($this->once()) |
|
| 195 | + ->method('getFolder') |
|
| 196 | + ->with('/') |
|
| 197 | + ->willReturn($folder); |
|
| 198 | + $folder |
|
| 199 | + ->expects($this->once()) |
|
| 200 | + ->method('getFile') |
|
| 201 | + ->with($this->fileName) |
|
| 202 | + ->willReturn($file); |
|
| 203 | + $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1502,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
| 204 | + $file |
|
| 205 | + ->expects($this->once()) |
|
| 206 | + ->method('putContent') |
|
| 207 | + ->with($fileData); |
|
| 208 | + $file |
|
| 209 | + ->expects($this->exactly(2)) |
|
| 210 | + ->method('getContent') |
|
| 211 | + ->willReturnOnConsecutiveCalls( |
|
| 212 | + '{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}},"ncversion":"11.0.0.2"}', |
|
| 213 | + $fileData |
|
| 214 | + ); |
|
| 215 | + $this->timeFactory |
|
| 216 | + ->expects($this->exactly(2)) |
|
| 217 | + ->method('getTime') |
|
| 218 | + ->willReturnOnConsecutiveCalls( |
|
| 219 | + 4801, |
|
| 220 | + 1502 |
|
| 221 | + ); |
|
| 222 | + $client = $this->createMock(IClient::class); |
|
| 223 | + $this->clientService |
|
| 224 | + ->expects($this->once()) |
|
| 225 | + ->method('newClient') |
|
| 226 | + ->willReturn($client); |
|
| 227 | + $response = $this->createMock(IResponse::class); |
|
| 228 | + $client |
|
| 229 | + ->expects($this->once()) |
|
| 230 | + ->method('get') |
|
| 231 | + ->with($this->endpoint) |
|
| 232 | + ->willReturn($response); |
|
| 233 | + $response |
|
| 234 | + ->expects($this->once()) |
|
| 235 | + ->method('getBody') |
|
| 236 | + ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]'); |
|
| 237 | + $response->method('getHeader') |
|
| 238 | + ->with($this->equalTo('ETag')) |
|
| 239 | + ->willReturn('"myETag"'); |
|
| 240 | + |
|
| 241 | + $expected = [ |
|
| 242 | + [ |
|
| 243 | + 'id' => 'MyNewApp', |
|
| 244 | + 'foo' => 'foo', |
|
| 245 | + ], |
|
| 246 | + [ |
|
| 247 | + 'id' => 'bar', |
|
| 248 | + ], |
|
| 249 | + ]; |
|
| 250 | + $this->assertSame($expected, $this->fetcher->get()); |
|
| 251 | + } |
|
| 252 | + |
|
| 253 | + public function testGetWithAlreadyExistingFileAndNoVersion(): void { |
|
| 254 | + $this->config |
|
| 255 | + ->method('getSystemValueString') |
|
| 256 | + ->willReturnCallback(function ($var, $default) { |
|
| 257 | + if ($var === 'appstoreurl') { |
|
| 258 | + return 'https://apps.nextcloud.com/api/v1'; |
|
| 259 | + } elseif ($var === 'version') { |
|
| 260 | + return '11.0.0.2'; |
|
| 261 | + } |
|
| 262 | + return $default; |
|
| 263 | + }); |
|
| 264 | + $this->config->method('getSystemValueBool') |
|
| 265 | + ->willReturnArgument(1); |
|
| 266 | + |
|
| 267 | + $folder = $this->createMock(ISimpleFolder::class); |
|
| 268 | + $file = $this->createMock(ISimpleFile::class); |
|
| 269 | + $this->appData |
|
| 270 | + ->expects($this->once()) |
|
| 271 | + ->method('getFolder') |
|
| 272 | + ->with('/') |
|
| 273 | + ->willReturn($folder); |
|
| 274 | + $folder |
|
| 275 | + ->expects($this->once()) |
|
| 276 | + ->method('getFile') |
|
| 277 | + ->with($this->fileName) |
|
| 278 | + ->willReturn($file); |
|
| 279 | + $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1201,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
| 280 | + $file |
|
| 281 | + ->expects($this->once()) |
|
| 282 | + ->method('putContent') |
|
| 283 | + ->with($fileData); |
|
| 284 | + $file |
|
| 285 | + ->expects($this->exactly(2)) |
|
| 286 | + ->method('getContent') |
|
| 287 | + ->willReturnOnConsecutiveCalls( |
|
| 288 | + '{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}}', |
|
| 289 | + $fileData |
|
| 290 | + ); |
|
| 291 | + $this->timeFactory |
|
| 292 | + ->expects($this->once()) |
|
| 293 | + ->method('getTime') |
|
| 294 | + ->willReturn(1201); |
|
| 295 | + $client = $this->createMock(IClient::class); |
|
| 296 | + $this->clientService |
|
| 297 | + ->expects($this->once()) |
|
| 298 | + ->method('newClient') |
|
| 299 | + ->willReturn($client); |
|
| 300 | + $response = $this->createMock(IResponse::class); |
|
| 301 | + $client |
|
| 302 | + ->expects($this->once()) |
|
| 303 | + ->method('get') |
|
| 304 | + ->with($this->endpoint) |
|
| 305 | + ->willReturn($response); |
|
| 306 | + $response |
|
| 307 | + ->expects($this->once()) |
|
| 308 | + ->method('getBody') |
|
| 309 | + ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]'); |
|
| 310 | + $response->method('getHeader') |
|
| 311 | + ->with($this->equalTo('ETag')) |
|
| 312 | + ->willReturn('"myETag"'); |
|
| 313 | + |
|
| 314 | + $expected = [ |
|
| 315 | + [ |
|
| 316 | + 'id' => 'MyNewApp', |
|
| 317 | + 'foo' => 'foo', |
|
| 318 | + ], |
|
| 319 | + [ |
|
| 320 | + 'id' => 'bar', |
|
| 321 | + ], |
|
| 322 | + ]; |
|
| 323 | + $this->assertSame($expected, $this->fetcher->get()); |
|
| 324 | + } |
|
| 325 | + |
|
| 326 | + public function testGetWithAlreadyExistingFileAndOutdatedVersion(): void { |
|
| 327 | + $this->config |
|
| 328 | + ->method('getSystemValueString') |
|
| 329 | + ->willReturnCallback(function ($var, $default) { |
|
| 330 | + if ($var === 'appstoreurl') { |
|
| 331 | + return 'https://apps.nextcloud.com/api/v1'; |
|
| 332 | + } elseif ($var === 'version') { |
|
| 333 | + return '11.0.0.2'; |
|
| 334 | + } |
|
| 335 | + return $default; |
|
| 336 | + }); |
|
| 337 | + $this->config->method('getSystemValueBool') |
|
| 338 | + ->willReturnArgument(1); |
|
| 339 | + |
|
| 340 | + $folder = $this->createMock(ISimpleFolder::class); |
|
| 341 | + $file = $this->createMock(ISimpleFile::class); |
|
| 342 | + $this->appData |
|
| 343 | + ->expects($this->once()) |
|
| 344 | + ->method('getFolder') |
|
| 345 | + ->with('/') |
|
| 346 | + ->willReturn($folder); |
|
| 347 | + $folder |
|
| 348 | + ->expects($this->once()) |
|
| 349 | + ->method('getFile') |
|
| 350 | + ->with($this->fileName) |
|
| 351 | + ->willReturn($file); |
|
| 352 | + $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1201,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
| 353 | + $file |
|
| 354 | + ->expects($this->once()) |
|
| 355 | + ->method('putContent') |
|
| 356 | + ->with($fileData); |
|
| 357 | + $file |
|
| 358 | + ->expects($this->exactly(2)) |
|
| 359 | + ->method('getContent') |
|
| 360 | + ->willReturnOnConsecutiveCalls( |
|
| 361 | + '{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}},"ncversion":"11.0.0.1"', |
|
| 362 | + $fileData |
|
| 363 | + ); |
|
| 364 | + $this->timeFactory |
|
| 365 | + ->method('getTime') |
|
| 366 | + ->willReturn(1201); |
|
| 367 | + $client = $this->createMock(IClient::class); |
|
| 368 | + $this->clientService |
|
| 369 | + ->expects($this->once()) |
|
| 370 | + ->method('newClient') |
|
| 371 | + ->willReturn($client); |
|
| 372 | + $response = $this->createMock(IResponse::class); |
|
| 373 | + $client |
|
| 374 | + ->expects($this->once()) |
|
| 375 | + ->method('get') |
|
| 376 | + ->with($this->endpoint) |
|
| 377 | + ->willReturn($response); |
|
| 378 | + $response |
|
| 379 | + ->expects($this->once()) |
|
| 380 | + ->method('getBody') |
|
| 381 | + ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]'); |
|
| 382 | + $response->method('getHeader') |
|
| 383 | + ->with($this->equalTo('ETag')) |
|
| 384 | + ->willReturn('"myETag"'); |
|
| 385 | + |
|
| 386 | + $expected = [ |
|
| 387 | + [ |
|
| 388 | + 'id' => 'MyNewApp', |
|
| 389 | + 'foo' => 'foo', |
|
| 390 | + ], |
|
| 391 | + [ |
|
| 392 | + 'id' => 'bar', |
|
| 393 | + ], |
|
| 394 | + ]; |
|
| 395 | + $this->assertSame($expected, $this->fetcher->get()); |
|
| 396 | + } |
|
| 397 | + |
|
| 398 | + public function testGetWithExceptionInClient(): void { |
|
| 399 | + $this->config->method('getSystemValueString') |
|
| 400 | + ->willReturnArgument(1); |
|
| 401 | + $this->config->method('getSystemValueBool') |
|
| 402 | + ->willReturnArgument(1); |
|
| 403 | + |
|
| 404 | + $folder = $this->createMock(ISimpleFolder::class); |
|
| 405 | + $file = $this->createMock(ISimpleFile::class); |
|
| 406 | + $this->appData |
|
| 407 | + ->expects($this->once()) |
|
| 408 | + ->method('getFolder') |
|
| 409 | + ->with('/') |
|
| 410 | + ->willReturn($folder); |
|
| 411 | + $folder |
|
| 412 | + ->expects($this->once()) |
|
| 413 | + ->method('getFile') |
|
| 414 | + ->with($this->fileName) |
|
| 415 | + ->willReturn($file); |
|
| 416 | + $file |
|
| 417 | + ->expects($this->once()) |
|
| 418 | + ->method('getContent') |
|
| 419 | + ->willReturn('{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}}}'); |
|
| 420 | + $client = $this->createMock(IClient::class); |
|
| 421 | + $this->clientService |
|
| 422 | + ->expects($this->once()) |
|
| 423 | + ->method('newClient') |
|
| 424 | + ->willReturn($client); |
|
| 425 | + $client |
|
| 426 | + ->expects($this->once()) |
|
| 427 | + ->method('get') |
|
| 428 | + ->with($this->endpoint) |
|
| 429 | + ->willThrowException(new \Exception()); |
|
| 430 | + |
|
| 431 | + $this->assertSame([], $this->fetcher->get()); |
|
| 432 | + } |
|
| 433 | + |
|
| 434 | + public function testGetMatchingETag(): void { |
|
| 435 | + $this->config->method('getSystemValueString') |
|
| 436 | + ->willReturnCallback(function ($key, $default) { |
|
| 437 | + if ($key === 'version') { |
|
| 438 | + return '11.0.0.2'; |
|
| 439 | + } else { |
|
| 440 | + return $default; |
|
| 441 | + } |
|
| 442 | + }); |
|
| 443 | + $this->config->method('getSystemValueBool') |
|
| 444 | + ->willReturnArgument(1); |
|
| 445 | + |
|
| 446 | + $this->config->method('getAppValue') |
|
| 447 | + ->willReturnMap([ |
|
| 448 | + ['settings', 'appstore-fetcher-lastFailure', '0', '0'], |
|
| 449 | + ['settings', 'appstore-timeout', '120', '120'], |
|
| 450 | + ]); |
|
| 451 | + |
|
| 452 | + $folder = $this->createMock(ISimpleFolder::class); |
|
| 453 | + $file = $this->createMock(ISimpleFile::class); |
|
| 454 | + $this->appData |
|
| 455 | + ->expects($this->once()) |
|
| 456 | + ->method('getFolder') |
|
| 457 | + ->with('/') |
|
| 458 | + ->willReturn($folder); |
|
| 459 | + $folder |
|
| 460 | + ->expects($this->once()) |
|
| 461 | + ->method('getFile') |
|
| 462 | + ->with($this->fileName) |
|
| 463 | + ->willReturn($file); |
|
| 464 | + $origData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1200,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
| 465 | + |
|
| 466 | + $newData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":4802,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; |
|
| 467 | + $file |
|
| 468 | + ->expects($this->once()) |
|
| 469 | + ->method('putContent') |
|
| 470 | + ->with($newData); |
|
| 471 | + $file |
|
| 472 | + ->expects($this->exactly(2)) |
|
| 473 | + ->method('getContent') |
|
| 474 | + ->willReturnOnConsecutiveCalls( |
|
| 475 | + $origData, |
|
| 476 | + $newData, |
|
| 477 | + ); |
|
| 478 | + $this->timeFactory |
|
| 479 | + ->expects($this->exactly(2)) |
|
| 480 | + ->method('getTime') |
|
| 481 | + ->willReturnOnConsecutiveCalls( |
|
| 482 | + 4801, |
|
| 483 | + 4802 |
|
| 484 | + ); |
|
| 485 | + $client = $this->createMock(IClient::class); |
|
| 486 | + $this->clientService |
|
| 487 | + ->expects($this->once()) |
|
| 488 | + ->method('newClient') |
|
| 489 | + ->willReturn($client); |
|
| 490 | + $response = $this->createMock(IResponse::class); |
|
| 491 | + $client |
|
| 492 | + ->expects($this->once()) |
|
| 493 | + ->method('get') |
|
| 494 | + ->with( |
|
| 495 | + $this->equalTo($this->endpoint), |
|
| 496 | + $this->equalTo([ |
|
| 497 | + 'timeout' => 120, |
|
| 498 | + 'headers' => [ |
|
| 499 | + 'If-None-Match' => '"myETag"' |
|
| 500 | + ] |
|
| 501 | + ]) |
|
| 502 | + )->willReturn($response); |
|
| 503 | + $response->method('getStatusCode') |
|
| 504 | + ->willReturn(304); |
|
| 505 | + |
|
| 506 | + $expected = [ |
|
| 507 | + [ |
|
| 508 | + 'id' => 'MyNewApp', |
|
| 509 | + 'foo' => 'foo', |
|
| 510 | + ], |
|
| 511 | + [ |
|
| 512 | + 'id' => 'bar', |
|
| 513 | + ], |
|
| 514 | + ]; |
|
| 515 | + |
|
| 516 | + $this->assertSame($expected, $this->fetcher->get()); |
|
| 517 | + } |
|
| 518 | + |
|
| 519 | + public function testGetNoMatchingETag(): void { |
|
| 520 | + $this->config->method('getSystemValueString') |
|
| 521 | + ->willReturnCallback(function ($key, $default) { |
|
| 522 | + if ($key === 'version') { |
|
| 523 | + return '11.0.0.2'; |
|
| 524 | + } else { |
|
| 525 | + return $default; |
|
| 526 | + } |
|
| 527 | + }); |
|
| 528 | + $this->config->method('getSystemValueBool') |
|
| 529 | + ->willReturnArgument(1); |
|
| 530 | + |
|
| 531 | + $this->config->method('getAppValue') |
|
| 532 | + ->willReturnMap([ |
|
| 533 | + ['settings', 'appstore-fetcher-lastFailure', '0', '0'], |
|
| 534 | + ['settings', 'appstore-timeout', '120', '120'], |
|
| 535 | + ]); |
|
| 536 | + |
|
| 537 | + $folder = $this->createMock(ISimpleFolder::class); |
|
| 538 | + $file = $this->createMock(ISimpleFile::class); |
|
| 539 | + $this->appData |
|
| 540 | + ->expects($this->once()) |
|
| 541 | + ->method('getFolder') |
|
| 542 | + ->with('/') |
|
| 543 | + ->willReturn($folder); |
|
| 544 | + $folder |
|
| 545 | + ->expects($this->once()) |
|
| 546 | + ->method('getFile') |
|
| 547 | + ->with($this->fileName) |
|
| 548 | + ->willReturn($file); |
|
| 549 | + $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":4802,"ncversion":"11.0.0.2","ETag":"\"newETag\""}'; |
|
| 550 | + $file |
|
| 551 | + ->expects($this->once()) |
|
| 552 | + ->method('putContent') |
|
| 553 | + ->with($fileData); |
|
| 554 | + $file |
|
| 555 | + ->expects($this->exactly(2)) |
|
| 556 | + ->method('getContent') |
|
| 557 | + ->willReturnOnConsecutiveCalls( |
|
| 558 | + '{"data":[{"id":"MyOldApp","abc":"def"}],"timestamp":1200,"ncversion":"11.0.0.2","ETag":"\"myETag\""}', |
|
| 559 | + $fileData, |
|
| 560 | + ); |
|
| 561 | + $this->timeFactory |
|
| 562 | + ->expects($this->exactly(2)) |
|
| 563 | + ->method('getTime') |
|
| 564 | + ->willReturnOnConsecutiveCalls( |
|
| 565 | + 4801, |
|
| 566 | + 4802, |
|
| 567 | + ); |
|
| 568 | + $client = $this->createMock(IClient::class); |
|
| 569 | + $this->clientService |
|
| 570 | + ->expects($this->once()) |
|
| 571 | + ->method('newClient') |
|
| 572 | + ->willReturn($client); |
|
| 573 | + $response = $this->createMock(IResponse::class); |
|
| 574 | + $client |
|
| 575 | + ->expects($this->once()) |
|
| 576 | + ->method('get') |
|
| 577 | + ->with( |
|
| 578 | + $this->equalTo($this->endpoint), |
|
| 579 | + $this->equalTo([ |
|
| 580 | + 'timeout' => 120, |
|
| 581 | + 'headers' => [ |
|
| 582 | + 'If-None-Match' => '"myETag"', |
|
| 583 | + ] |
|
| 584 | + ]) |
|
| 585 | + ) |
|
| 586 | + ->willReturn($response); |
|
| 587 | + $response->method('getStatusCode') |
|
| 588 | + ->willReturn(200); |
|
| 589 | + $response |
|
| 590 | + ->expects($this->once()) |
|
| 591 | + ->method('getBody') |
|
| 592 | + ->willReturn('[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}]'); |
|
| 593 | + $response->method('getHeader') |
|
| 594 | + ->with($this->equalTo('ETag')) |
|
| 595 | + ->willReturn('"newETag"'); |
|
| 596 | + |
|
| 597 | + $expected = [ |
|
| 598 | + [ |
|
| 599 | + 'id' => 'MyNewApp', |
|
| 600 | + 'foo' => 'foo', |
|
| 601 | + ], |
|
| 602 | + [ |
|
| 603 | + 'id' => 'bar', |
|
| 604 | + ], |
|
| 605 | + ]; |
|
| 606 | + $this->assertSame($expected, $this->fetcher->get()); |
|
| 607 | + } |
|
| 608 | + |
|
| 609 | + |
|
| 610 | + public function testFetchAfterUpgradeNoETag(): void { |
|
| 611 | + $this->config->method('getSystemValueString') |
|
| 612 | + ->willReturnCallback(function ($key, $default) { |
|
| 613 | + if ($key === 'version') { |
|
| 614 | + return '11.0.0.3'; |
|
| 615 | + } else { |
|
| 616 | + return $default; |
|
| 617 | + } |
|
| 618 | + }); |
|
| 619 | + $this->config->method('getSystemValueBool') |
|
| 620 | + ->willReturnArgument(1); |
|
| 621 | + |
|
| 622 | + $this->config->method('getAppValue') |
|
| 623 | + ->willReturnMap([ |
|
| 624 | + ['settings', 'appstore-fetcher-lastFailure', '0', '0'], |
|
| 625 | + ['settings', 'appstore-timeout', '120', '120'], |
|
| 626 | + ]); |
|
| 627 | + |
|
| 628 | + $folder = $this->createMock(ISimpleFolder::class); |
|
| 629 | + $file = $this->createMock(ISimpleFile::class); |
|
| 630 | + $this->appData |
|
| 631 | + ->expects($this->once()) |
|
| 632 | + ->method('getFolder') |
|
| 633 | + ->with('/') |
|
| 634 | + ->willReturn($folder); |
|
| 635 | + $folder |
|
| 636 | + ->expects($this->once()) |
|
| 637 | + ->method('getFile') |
|
| 638 | + ->with($this->fileName) |
|
| 639 | + ->willReturn($file); |
|
| 640 | + $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1501,"ncversion":"11.0.0.3","ETag":"\"newETag\""}'; |
|
| 641 | + $file |
|
| 642 | + ->expects($this->once()) |
|
| 643 | + ->method('putContent') |
|
| 644 | + ->with($fileData); |
|
| 645 | + $file |
|
| 646 | + ->expects($this->exactly(2)) |
|
| 647 | + ->method('getContent') |
|
| 648 | + ->willReturnOnConsecutiveCalls( |
|
| 649 | + '{"data":[{"id":"MyOldApp","abc":"def"}],"timestamp":1200,"ncversion":"11.0.0.2","ETag":"\"myETag\""}', |
|
| 650 | + $fileData |
|
| 651 | + ); |
|
| 652 | + $client = $this->createMock(IClient::class); |
|
| 653 | + $this->clientService |
|
| 654 | + ->expects($this->once()) |
|
| 655 | + ->method('newClient') |
|
| 656 | + ->willReturn($client); |
|
| 657 | + $response = $this->createMock(IResponse::class); |
|
| 658 | + $client |
|
| 659 | + ->expects($this->once()) |
|
| 660 | + ->method('get') |
|
| 661 | + ->with( |
|
| 662 | + $this->equalTo($this->endpoint), |
|
| 663 | + $this->equalTo([ |
|
| 664 | + 'timeout' => 120, |
|
| 665 | + ]) |
|
| 666 | + ) |
|
| 667 | + ->willReturn($response); |
|
| 668 | + $response->method('getStatusCode') |
|
| 669 | + ->willReturn(200); |
|
| 670 | + $response |
|
| 671 | + ->expects($this->once()) |
|
| 672 | + ->method('getBody') |
|
| 673 | + ->willReturn('[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}]'); |
|
| 674 | + $response->method('getHeader') |
|
| 675 | + ->with($this->equalTo('ETag')) |
|
| 676 | + ->willReturn('"newETag"'); |
|
| 677 | + $this->timeFactory |
|
| 678 | + ->expects($this->once()) |
|
| 679 | + ->method('getTime') |
|
| 680 | + ->willReturn(1501); |
|
| 681 | + |
|
| 682 | + $expected = [ |
|
| 683 | + [ |
|
| 684 | + 'id' => 'MyNewApp', |
|
| 685 | + 'foo' => 'foo', |
|
| 686 | + ], |
|
| 687 | + [ |
|
| 688 | + 'id' => 'bar', |
|
| 689 | + ], |
|
| 690 | + ]; |
|
| 691 | + $this->assertSame($expected, $this->fetcher->get()); |
|
| 692 | + } |
|
| 693 | 693 | } |
@@ -22,210 +22,210 @@ |
||
| 22 | 22 | use Psr\Log\LoggerInterface; |
| 23 | 23 | |
| 24 | 24 | abstract class Fetcher { |
| 25 | - public const INVALIDATE_AFTER_SECONDS = 3600; |
|
| 26 | - public const INVALIDATE_AFTER_SECONDS_UNSTABLE = 900; |
|
| 27 | - public const RETRY_AFTER_FAILURE_SECONDS = 300; |
|
| 28 | - public const APP_STORE_URL = 'https://apps.nextcloud.com/api/v1'; |
|
| 29 | - |
|
| 30 | - /** @var IAppData */ |
|
| 31 | - protected $appData; |
|
| 32 | - |
|
| 33 | - /** @var string */ |
|
| 34 | - protected $fileName; |
|
| 35 | - /** @var string */ |
|
| 36 | - protected $endpointName; |
|
| 37 | - /** @var ?string */ |
|
| 38 | - protected $version = null; |
|
| 39 | - /** @var ?string */ |
|
| 40 | - protected $channel = null; |
|
| 41 | - |
|
| 42 | - public function __construct( |
|
| 43 | - Factory $appDataFactory, |
|
| 44 | - protected IClientService $clientService, |
|
| 45 | - protected ITimeFactory $timeFactory, |
|
| 46 | - protected IConfig $config, |
|
| 47 | - protected LoggerInterface $logger, |
|
| 48 | - protected IRegistry $registry, |
|
| 49 | - ) { |
|
| 50 | - $this->appData = $appDataFactory->get('appstore'); |
|
| 51 | - } |
|
| 52 | - |
|
| 53 | - /** |
|
| 54 | - * Fetches the response from the server |
|
| 55 | - * |
|
| 56 | - * @param string $ETag |
|
| 57 | - * @param string $content |
|
| 58 | - * |
|
| 59 | - * @return array |
|
| 60 | - */ |
|
| 61 | - protected function fetch($ETag, $content, $allowUnstable = false) { |
|
| 62 | - $appstoreenabled = $this->config->getSystemValueBool('appstoreenabled', true); |
|
| 63 | - if ((int)$this->config->getAppValue('settings', 'appstore-fetcher-lastFailure', '0') > time() - self::RETRY_AFTER_FAILURE_SECONDS) { |
|
| 64 | - return []; |
|
| 65 | - } |
|
| 66 | - |
|
| 67 | - if (!$appstoreenabled) { |
|
| 68 | - return []; |
|
| 69 | - } |
|
| 70 | - |
|
| 71 | - $options = [ |
|
| 72 | - 'timeout' => (int)$this->config->getAppValue('settings', 'appstore-timeout', '120') |
|
| 73 | - ]; |
|
| 74 | - |
|
| 75 | - if ($ETag !== '') { |
|
| 76 | - $options['headers'] = [ |
|
| 77 | - 'If-None-Match' => $ETag, |
|
| 78 | - ]; |
|
| 79 | - } |
|
| 80 | - |
|
| 81 | - if ($this->config->getSystemValueString('appstoreurl', self::APP_STORE_URL) === self::APP_STORE_URL) { |
|
| 82 | - // If we have a valid subscription key, send it to the appstore |
|
| 83 | - $subscriptionKey = $this->config->getAppValue('support', 'subscription_key'); |
|
| 84 | - if ($this->registry->delegateHasValidSubscription() && $subscriptionKey) { |
|
| 85 | - $options['headers'] ??= []; |
|
| 86 | - $options['headers']['X-NC-Subscription-Key'] = $subscriptionKey; |
|
| 87 | - } |
|
| 88 | - } |
|
| 89 | - |
|
| 90 | - $client = $this->clientService->newClient(); |
|
| 91 | - try { |
|
| 92 | - $response = $client->get($this->getEndpoint(), $options); |
|
| 93 | - } catch (ConnectException|ClientException|ServerException $e) { |
|
| 94 | - $this->config->setAppValue('settings', 'appstore-fetcher-lastFailure', (string)time()); |
|
| 95 | - $this->logger->error('Failed to connect to the app store', ['exception' => $e]); |
|
| 96 | - return []; |
|
| 97 | - } |
|
| 98 | - |
|
| 99 | - $responseJson = []; |
|
| 100 | - if ($response->getStatusCode() === Http::STATUS_NOT_MODIFIED) { |
|
| 101 | - $responseJson['data'] = json_decode($content, true); |
|
| 102 | - } else { |
|
| 103 | - $responseJson['data'] = json_decode($response->getBody(), true); |
|
| 104 | - $ETag = $response->getHeader('ETag'); |
|
| 105 | - } |
|
| 106 | - $this->config->deleteAppValue('settings', 'appstore-fetcher-lastFailure'); |
|
| 107 | - |
|
| 108 | - $responseJson['timestamp'] = $this->timeFactory->getTime(); |
|
| 109 | - $responseJson['ncversion'] = $this->getVersion(); |
|
| 110 | - if ($ETag !== '') { |
|
| 111 | - $responseJson['ETag'] = $ETag; |
|
| 112 | - } |
|
| 113 | - |
|
| 114 | - return $responseJson; |
|
| 115 | - } |
|
| 116 | - |
|
| 117 | - /** |
|
| 118 | - * Returns the array with the entries on the appstore server |
|
| 119 | - * |
|
| 120 | - * @param bool [$allowUnstable] Allow unstable releases |
|
| 121 | - * @return array |
|
| 122 | - */ |
|
| 123 | - public function get($allowUnstable = false) { |
|
| 124 | - $appstoreenabled = $this->config->getSystemValueBool('appstoreenabled', true); |
|
| 125 | - $internetavailable = $this->config->getSystemValueBool('has_internet_connection', true); |
|
| 126 | - $isDefaultAppStore = $this->config->getSystemValueString('appstoreurl', self::APP_STORE_URL) === self::APP_STORE_URL; |
|
| 127 | - |
|
| 128 | - if (!$appstoreenabled || (!$internetavailable && $isDefaultAppStore)) { |
|
| 129 | - $this->logger->info('AppStore is disabled or this instance has no Internet connection to access the default app store', ['app' => 'appstoreFetcher']); |
|
| 130 | - return []; |
|
| 131 | - } |
|
| 132 | - |
|
| 133 | - $rootFolder = $this->appData->getFolder('/'); |
|
| 134 | - |
|
| 135 | - $ETag = ''; |
|
| 136 | - $content = ''; |
|
| 137 | - |
|
| 138 | - try { |
|
| 139 | - // File does already exists |
|
| 140 | - $file = $rootFolder->getFile($this->fileName); |
|
| 141 | - $jsonBlob = json_decode($file->getContent(), true); |
|
| 142 | - |
|
| 143 | - if (is_array($jsonBlob)) { |
|
| 144 | - // No caching when the version has been updated |
|
| 145 | - if (isset($jsonBlob['ncversion']) && $jsonBlob['ncversion'] === $this->getVersion()) { |
|
| 146 | - // If the timestamp is older than 3600 seconds request the files new |
|
| 147 | - $invalidateAfterSeconds = self::INVALIDATE_AFTER_SECONDS; |
|
| 148 | - |
|
| 149 | - if ($allowUnstable) { |
|
| 150 | - $invalidateAfterSeconds = self::INVALIDATE_AFTER_SECONDS_UNSTABLE; |
|
| 151 | - } |
|
| 152 | - |
|
| 153 | - if ((int)$jsonBlob['timestamp'] > ($this->timeFactory->getTime() - $invalidateAfterSeconds)) { |
|
| 154 | - return $jsonBlob['data']; |
|
| 155 | - } |
|
| 156 | - |
|
| 157 | - if (isset($jsonBlob['ETag'])) { |
|
| 158 | - $ETag = $jsonBlob['ETag']; |
|
| 159 | - $content = json_encode($jsonBlob['data']); |
|
| 160 | - } |
|
| 161 | - } |
|
| 162 | - } |
|
| 163 | - } catch (NotFoundException $e) { |
|
| 164 | - // File does not already exists |
|
| 165 | - $file = $rootFolder->newFile($this->fileName); |
|
| 166 | - } |
|
| 167 | - |
|
| 168 | - // Refresh the file content |
|
| 169 | - try { |
|
| 170 | - $responseJson = $this->fetch($ETag, $content, $allowUnstable); |
|
| 171 | - |
|
| 172 | - if (empty($responseJson) || empty($responseJson['data'])) { |
|
| 173 | - return []; |
|
| 174 | - } |
|
| 175 | - |
|
| 176 | - $file->putContent(json_encode($responseJson)); |
|
| 177 | - return json_decode($file->getContent(), true)['data']; |
|
| 178 | - } catch (ConnectException $e) { |
|
| 179 | - $this->logger->warning('Could not connect to appstore: ' . $e->getMessage(), ['app' => 'appstoreFetcher']); |
|
| 180 | - return []; |
|
| 181 | - } catch (\Exception $e) { |
|
| 182 | - $this->logger->warning($e->getMessage(), [ |
|
| 183 | - 'exception' => $e, |
|
| 184 | - 'app' => 'appstoreFetcher', |
|
| 185 | - ]); |
|
| 186 | - return []; |
|
| 187 | - } |
|
| 188 | - } |
|
| 189 | - |
|
| 190 | - /** |
|
| 191 | - * Get the currently Nextcloud version |
|
| 192 | - * @return string |
|
| 193 | - */ |
|
| 194 | - protected function getVersion() { |
|
| 195 | - if ($this->version === null) { |
|
| 196 | - $this->version = $this->config->getSystemValueString('version', '0.0.0'); |
|
| 197 | - } |
|
| 198 | - return $this->version; |
|
| 199 | - } |
|
| 200 | - |
|
| 201 | - /** |
|
| 202 | - * Set the current Nextcloud version |
|
| 203 | - * @param string $version |
|
| 204 | - */ |
|
| 205 | - public function setVersion(string $version) { |
|
| 206 | - $this->version = $version; |
|
| 207 | - } |
|
| 208 | - |
|
| 209 | - /** |
|
| 210 | - * Get the currently Nextcloud update channel |
|
| 211 | - * @return string |
|
| 212 | - */ |
|
| 213 | - protected function getChannel() { |
|
| 214 | - if ($this->channel === null) { |
|
| 215 | - $this->channel = Server::get(ServerVersion::class)->getChannel(); |
|
| 216 | - } |
|
| 217 | - return $this->channel; |
|
| 218 | - } |
|
| 219 | - |
|
| 220 | - /** |
|
| 221 | - * Set the current Nextcloud update channel |
|
| 222 | - * @param string $channel |
|
| 223 | - */ |
|
| 224 | - public function setChannel(string $channel) { |
|
| 225 | - $this->channel = $channel; |
|
| 226 | - } |
|
| 227 | - |
|
| 228 | - protected function getEndpoint(): string { |
|
| 229 | - return $this->config->getSystemValueString('appstoreurl', 'https://apps.nextcloud.com/api/v1') . '/' . $this->endpointName; |
|
| 230 | - } |
|
| 25 | + public const INVALIDATE_AFTER_SECONDS = 3600; |
|
| 26 | + public const INVALIDATE_AFTER_SECONDS_UNSTABLE = 900; |
|
| 27 | + public const RETRY_AFTER_FAILURE_SECONDS = 300; |
|
| 28 | + public const APP_STORE_URL = 'https://apps.nextcloud.com/api/v1'; |
|
| 29 | + |
|
| 30 | + /** @var IAppData */ |
|
| 31 | + protected $appData; |
|
| 32 | + |
|
| 33 | + /** @var string */ |
|
| 34 | + protected $fileName; |
|
| 35 | + /** @var string */ |
|
| 36 | + protected $endpointName; |
|
| 37 | + /** @var ?string */ |
|
| 38 | + protected $version = null; |
|
| 39 | + /** @var ?string */ |
|
| 40 | + protected $channel = null; |
|
| 41 | + |
|
| 42 | + public function __construct( |
|
| 43 | + Factory $appDataFactory, |
|
| 44 | + protected IClientService $clientService, |
|
| 45 | + protected ITimeFactory $timeFactory, |
|
| 46 | + protected IConfig $config, |
|
| 47 | + protected LoggerInterface $logger, |
|
| 48 | + protected IRegistry $registry, |
|
| 49 | + ) { |
|
| 50 | + $this->appData = $appDataFactory->get('appstore'); |
|
| 51 | + } |
|
| 52 | + |
|
| 53 | + /** |
|
| 54 | + * Fetches the response from the server |
|
| 55 | + * |
|
| 56 | + * @param string $ETag |
|
| 57 | + * @param string $content |
|
| 58 | + * |
|
| 59 | + * @return array |
|
| 60 | + */ |
|
| 61 | + protected function fetch($ETag, $content, $allowUnstable = false) { |
|
| 62 | + $appstoreenabled = $this->config->getSystemValueBool('appstoreenabled', true); |
|
| 63 | + if ((int)$this->config->getAppValue('settings', 'appstore-fetcher-lastFailure', '0') > time() - self::RETRY_AFTER_FAILURE_SECONDS) { |
|
| 64 | + return []; |
|
| 65 | + } |
|
| 66 | + |
|
| 67 | + if (!$appstoreenabled) { |
|
| 68 | + return []; |
|
| 69 | + } |
|
| 70 | + |
|
| 71 | + $options = [ |
|
| 72 | + 'timeout' => (int)$this->config->getAppValue('settings', 'appstore-timeout', '120') |
|
| 73 | + ]; |
|
| 74 | + |
|
| 75 | + if ($ETag !== '') { |
|
| 76 | + $options['headers'] = [ |
|
| 77 | + 'If-None-Match' => $ETag, |
|
| 78 | + ]; |
|
| 79 | + } |
|
| 80 | + |
|
| 81 | + if ($this->config->getSystemValueString('appstoreurl', self::APP_STORE_URL) === self::APP_STORE_URL) { |
|
| 82 | + // If we have a valid subscription key, send it to the appstore |
|
| 83 | + $subscriptionKey = $this->config->getAppValue('support', 'subscription_key'); |
|
| 84 | + if ($this->registry->delegateHasValidSubscription() && $subscriptionKey) { |
|
| 85 | + $options['headers'] ??= []; |
|
| 86 | + $options['headers']['X-NC-Subscription-Key'] = $subscriptionKey; |
|
| 87 | + } |
|
| 88 | + } |
|
| 89 | + |
|
| 90 | + $client = $this->clientService->newClient(); |
|
| 91 | + try { |
|
| 92 | + $response = $client->get($this->getEndpoint(), $options); |
|
| 93 | + } catch (ConnectException|ClientException|ServerException $e) { |
|
| 94 | + $this->config->setAppValue('settings', 'appstore-fetcher-lastFailure', (string)time()); |
|
| 95 | + $this->logger->error('Failed to connect to the app store', ['exception' => $e]); |
|
| 96 | + return []; |
|
| 97 | + } |
|
| 98 | + |
|
| 99 | + $responseJson = []; |
|
| 100 | + if ($response->getStatusCode() === Http::STATUS_NOT_MODIFIED) { |
|
| 101 | + $responseJson['data'] = json_decode($content, true); |
|
| 102 | + } else { |
|
| 103 | + $responseJson['data'] = json_decode($response->getBody(), true); |
|
| 104 | + $ETag = $response->getHeader('ETag'); |
|
| 105 | + } |
|
| 106 | + $this->config->deleteAppValue('settings', 'appstore-fetcher-lastFailure'); |
|
| 107 | + |
|
| 108 | + $responseJson['timestamp'] = $this->timeFactory->getTime(); |
|
| 109 | + $responseJson['ncversion'] = $this->getVersion(); |
|
| 110 | + if ($ETag !== '') { |
|
| 111 | + $responseJson['ETag'] = $ETag; |
|
| 112 | + } |
|
| 113 | + |
|
| 114 | + return $responseJson; |
|
| 115 | + } |
|
| 116 | + |
|
| 117 | + /** |
|
| 118 | + * Returns the array with the entries on the appstore server |
|
| 119 | + * |
|
| 120 | + * @param bool [$allowUnstable] Allow unstable releases |
|
| 121 | + * @return array |
|
| 122 | + */ |
|
| 123 | + public function get($allowUnstable = false) { |
|
| 124 | + $appstoreenabled = $this->config->getSystemValueBool('appstoreenabled', true); |
|
| 125 | + $internetavailable = $this->config->getSystemValueBool('has_internet_connection', true); |
|
| 126 | + $isDefaultAppStore = $this->config->getSystemValueString('appstoreurl', self::APP_STORE_URL) === self::APP_STORE_URL; |
|
| 127 | + |
|
| 128 | + if (!$appstoreenabled || (!$internetavailable && $isDefaultAppStore)) { |
|
| 129 | + $this->logger->info('AppStore is disabled or this instance has no Internet connection to access the default app store', ['app' => 'appstoreFetcher']); |
|
| 130 | + return []; |
|
| 131 | + } |
|
| 132 | + |
|
| 133 | + $rootFolder = $this->appData->getFolder('/'); |
|
| 134 | + |
|
| 135 | + $ETag = ''; |
|
| 136 | + $content = ''; |
|
| 137 | + |
|
| 138 | + try { |
|
| 139 | + // File does already exists |
|
| 140 | + $file = $rootFolder->getFile($this->fileName); |
|
| 141 | + $jsonBlob = json_decode($file->getContent(), true); |
|
| 142 | + |
|
| 143 | + if (is_array($jsonBlob)) { |
|
| 144 | + // No caching when the version has been updated |
|
| 145 | + if (isset($jsonBlob['ncversion']) && $jsonBlob['ncversion'] === $this->getVersion()) { |
|
| 146 | + // If the timestamp is older than 3600 seconds request the files new |
|
| 147 | + $invalidateAfterSeconds = self::INVALIDATE_AFTER_SECONDS; |
|
| 148 | + |
|
| 149 | + if ($allowUnstable) { |
|
| 150 | + $invalidateAfterSeconds = self::INVALIDATE_AFTER_SECONDS_UNSTABLE; |
|
| 151 | + } |
|
| 152 | + |
|
| 153 | + if ((int)$jsonBlob['timestamp'] > ($this->timeFactory->getTime() - $invalidateAfterSeconds)) { |
|
| 154 | + return $jsonBlob['data']; |
|
| 155 | + } |
|
| 156 | + |
|
| 157 | + if (isset($jsonBlob['ETag'])) { |
|
| 158 | + $ETag = $jsonBlob['ETag']; |
|
| 159 | + $content = json_encode($jsonBlob['data']); |
|
| 160 | + } |
|
| 161 | + } |
|
| 162 | + } |
|
| 163 | + } catch (NotFoundException $e) { |
|
| 164 | + // File does not already exists |
|
| 165 | + $file = $rootFolder->newFile($this->fileName); |
|
| 166 | + } |
|
| 167 | + |
|
| 168 | + // Refresh the file content |
|
| 169 | + try { |
|
| 170 | + $responseJson = $this->fetch($ETag, $content, $allowUnstable); |
|
| 171 | + |
|
| 172 | + if (empty($responseJson) || empty($responseJson['data'])) { |
|
| 173 | + return []; |
|
| 174 | + } |
|
| 175 | + |
|
| 176 | + $file->putContent(json_encode($responseJson)); |
|
| 177 | + return json_decode($file->getContent(), true)['data']; |
|
| 178 | + } catch (ConnectException $e) { |
|
| 179 | + $this->logger->warning('Could not connect to appstore: ' . $e->getMessage(), ['app' => 'appstoreFetcher']); |
|
| 180 | + return []; |
|
| 181 | + } catch (\Exception $e) { |
|
| 182 | + $this->logger->warning($e->getMessage(), [ |
|
| 183 | + 'exception' => $e, |
|
| 184 | + 'app' => 'appstoreFetcher', |
|
| 185 | + ]); |
|
| 186 | + return []; |
|
| 187 | + } |
|
| 188 | + } |
|
| 189 | + |
|
| 190 | + /** |
|
| 191 | + * Get the currently Nextcloud version |
|
| 192 | + * @return string |
|
| 193 | + */ |
|
| 194 | + protected function getVersion() { |
|
| 195 | + if ($this->version === null) { |
|
| 196 | + $this->version = $this->config->getSystemValueString('version', '0.0.0'); |
|
| 197 | + } |
|
| 198 | + return $this->version; |
|
| 199 | + } |
|
| 200 | + |
|
| 201 | + /** |
|
| 202 | + * Set the current Nextcloud version |
|
| 203 | + * @param string $version |
|
| 204 | + */ |
|
| 205 | + public function setVersion(string $version) { |
|
| 206 | + $this->version = $version; |
|
| 207 | + } |
|
| 208 | + |
|
| 209 | + /** |
|
| 210 | + * Get the currently Nextcloud update channel |
|
| 211 | + * @return string |
|
| 212 | + */ |
|
| 213 | + protected function getChannel() { |
|
| 214 | + if ($this->channel === null) { |
|
| 215 | + $this->channel = Server::get(ServerVersion::class)->getChannel(); |
|
| 216 | + } |
|
| 217 | + return $this->channel; |
|
| 218 | + } |
|
| 219 | + |
|
| 220 | + /** |
|
| 221 | + * Set the current Nextcloud update channel |
|
| 222 | + * @param string $channel |
|
| 223 | + */ |
|
| 224 | + public function setChannel(string $channel) { |
|
| 225 | + $this->channel = $channel; |
|
| 226 | + } |
|
| 227 | + |
|
| 228 | + protected function getEndpoint(): string { |
|
| 229 | + return $this->config->getSystemValueString('appstoreurl', 'https://apps.nextcloud.com/api/v1') . '/' . $this->endpointName; |
|
| 230 | + } |
|
| 231 | 231 | } |
@@ -60,7 +60,7 @@ discard block |
||
| 60 | 60 | */ |
| 61 | 61 | protected function fetch($ETag, $content, $allowUnstable = false) { |
| 62 | 62 | $appstoreenabled = $this->config->getSystemValueBool('appstoreenabled', true); |
| 63 | - if ((int)$this->config->getAppValue('settings', 'appstore-fetcher-lastFailure', '0') > time() - self::RETRY_AFTER_FAILURE_SECONDS) { |
|
| 63 | + if ((int) $this->config->getAppValue('settings', 'appstore-fetcher-lastFailure', '0') > time() - self::RETRY_AFTER_FAILURE_SECONDS) { |
|
| 64 | 64 | return []; |
| 65 | 65 | } |
| 66 | 66 | |
@@ -69,7 +69,7 @@ discard block |
||
| 69 | 69 | } |
| 70 | 70 | |
| 71 | 71 | $options = [ |
| 72 | - 'timeout' => (int)$this->config->getAppValue('settings', 'appstore-timeout', '120') |
|
| 72 | + 'timeout' => (int) $this->config->getAppValue('settings', 'appstore-timeout', '120') |
|
| 73 | 73 | ]; |
| 74 | 74 | |
| 75 | 75 | if ($ETag !== '') { |
@@ -90,8 +90,8 @@ discard block |
||
| 90 | 90 | $client = $this->clientService->newClient(); |
| 91 | 91 | try { |
| 92 | 92 | $response = $client->get($this->getEndpoint(), $options); |
| 93 | - } catch (ConnectException|ClientException|ServerException $e) { |
|
| 94 | - $this->config->setAppValue('settings', 'appstore-fetcher-lastFailure', (string)time()); |
|
| 93 | + } catch (ConnectException | ClientException | ServerException $e) { |
|
| 94 | + $this->config->setAppValue('settings', 'appstore-fetcher-lastFailure', (string) time()); |
|
| 95 | 95 | $this->logger->error('Failed to connect to the app store', ['exception' => $e]); |
| 96 | 96 | return []; |
| 97 | 97 | } |
@@ -150,7 +150,7 @@ discard block |
||
| 150 | 150 | $invalidateAfterSeconds = self::INVALIDATE_AFTER_SECONDS_UNSTABLE; |
| 151 | 151 | } |
| 152 | 152 | |
| 153 | - if ((int)$jsonBlob['timestamp'] > ($this->timeFactory->getTime() - $invalidateAfterSeconds)) { |
|
| 153 | + if ((int) $jsonBlob['timestamp'] > ($this->timeFactory->getTime() - $invalidateAfterSeconds)) { |
|
| 154 | 154 | return $jsonBlob['data']; |
| 155 | 155 | } |
| 156 | 156 | |
@@ -176,7 +176,7 @@ discard block |
||
| 176 | 176 | $file->putContent(json_encode($responseJson)); |
| 177 | 177 | return json_decode($file->getContent(), true)['data']; |
| 178 | 178 | } catch (ConnectException $e) { |
| 179 | - $this->logger->warning('Could not connect to appstore: ' . $e->getMessage(), ['app' => 'appstoreFetcher']); |
|
| 179 | + $this->logger->warning('Could not connect to appstore: '.$e->getMessage(), ['app' => 'appstoreFetcher']); |
|
| 180 | 180 | return []; |
| 181 | 181 | } catch (\Exception $e) { |
| 182 | 182 | $this->logger->warning($e->getMessage(), [ |
@@ -226,6 +226,6 @@ discard block |
||
| 226 | 226 | } |
| 227 | 227 | |
| 228 | 228 | protected function getEndpoint(): string { |
| 229 | - return $this->config->getSystemValueString('appstoreurl', 'https://apps.nextcloud.com/api/v1') . '/' . $this->endpointName; |
|
| 229 | + return $this->config->getSystemValueString('appstoreurl', 'https://apps.nextcloud.com/api/v1').'/'.$this->endpointName; |
|
| 230 | 230 | } |
| 231 | 231 | } |