mirror of
https://github.com/PrivateBin/PrivateBin.git
synced 2024-03-22 13:10:41 +08:00
Merge branch 'stevenandres-master'
This commit is contained in:
commit
2b46fdd626
|
@ -8,6 +8,7 @@
|
|||
* ADDED: Configuration option to exempt IPs from the rate-limiter (#787)
|
||||
* ADDED: Google Cloud Storage backend support (#795)
|
||||
* ADDED: Oracle database support (#868)
|
||||
* ADDED: Configuration option to limit paste creation and commenting to certain IPs (#883)
|
||||
* CHANGED: Language selection cookie only transmitted over HTTPS (#472)
|
||||
* CHANGED: Upgrading libraries to: base-x 4.0.0, bootstrap 3.4.1 (JS), DOMpurify 2.3.6, ip-lib 1.18.0, jQuery 3.6.0, random_compat 2.0.21 & Showdown 2.0.0
|
||||
* CHANGED: Removed automatic `.ini` configuration file migration (#808)
|
||||
|
|
|
@ -135,9 +135,17 @@ markdown = "Markdown"
|
|||
; Set this to 0 to disable rate limiting.
|
||||
limit = 10
|
||||
|
||||
; Set ips (v4|v6) which should be exempted for the rate-limit. CIDR also supported. Needed to be comma separated.
|
||||
; Unset for enabling and invalid values will be ignored
|
||||
; eg: exemptedIp = '1.2.3.4,10.10.10/24'
|
||||
; (optional) Set IPs adresses (v4 or v6) or subnets (CIDR) which are exempted
|
||||
; from the rate-limit. Invalid IPs will be ignored. If multiple values are to
|
||||
; be exempted, the list needs to be comma separated. Leave unset to disable
|
||||
; exemptions.
|
||||
; exempted = "1.2.3.4,10.10.10/24"
|
||||
|
||||
; (optional) If you want only some source IP addresses (v4 or v6) or subnets
|
||||
; (CIDR) to be allowed to create pastes, set these here. Invalid IPs will be
|
||||
; ignored. If multiple values are to be exempted, the list needs to be comma
|
||||
; separated. Leave unset to allow anyone to create pastes.
|
||||
; creators = "1.2.3.4,10.10.10/24"
|
||||
|
||||
; (optional) if your website runs behind a reverse proxy or load balancer,
|
||||
; set the HTTP header containing the visitors IP address, i.e. X_FORWARDED_FOR
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Nota cifrata nant’à PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visitate stu liame per vede a nota. Date l’indirizzu à qualunque li permette d’accede à a nota dinù.",
|
||||
"URL shortener may expose your decrypt key in URL.": "Un ammuzzatore d’indirizzu pò palisà a vostra chjave di dicifratura in l’indirizzu.",
|
||||
"Save paste": "Arregistrà l’appiccicu"
|
||||
"Save paste": "Arregistrà l’appiccicu",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Šifrovaná poznámka ve službě PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Navštivte tento odkaz pro zobrazení poznámky. Přeposláním URL umožníte také jiným lidem přístup.",
|
||||
"URL shortener may expose your decrypt key in URL.": "Zkracovač URL může odhalit váš dešifrovací klíč v URL.",
|
||||
"Save paste": "Uložit příspěvek"
|
||||
"Save paste": "Uložit příspěvek",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Verschlüsselte Notiz auf PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Besuche diesen Link um das Dokument zu sehen. Wird die URL an eine andere Person gegeben, so kann diese Person ebenfalls auf dieses Dokument zugreifen.",
|
||||
"URL shortener may expose your decrypt key in URL.": "Der URL-Verkürzer kann den Schlüssel in der URL enthüllen.",
|
||||
"Save paste": "Text speichern"
|
||||
"Save paste": "Text speichern",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Nota cifrada en PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visite este enlace para ver la nota. Dar la URL a cualquier persona también les permite acceder a la nota.",
|
||||
"URL shortener may expose your decrypt key in URL.": "El acortador de URL puede exponer su clave de descifrado en el URL.",
|
||||
"Save paste": "Guardar \"paste\""
|
||||
"Save paste": "Guardar \"paste\"",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Krüpteeritud kiri PrivateBin-is",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Kirja nägemiseks külasta seda linki. Teistele URL-i andmine lubab ka neil ligi pääseda kirjale.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL-i lühendaja võib paljastada sinu dekrüpteerimisvõtme URL-is.",
|
||||
"Save paste": "Salvesta kleebe"
|
||||
"Save paste": "Salvesta kleebe",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Salattu viesti PrivateBinissä",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Käy tässä linkissä nähdäksesi viestin. URL:n antaminen kenellekään antaa heidänkin päästä katsomeen viestiä. ",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL-lyhentäjä voi paljastaa purkuavaimesi URL:ssä.",
|
||||
"Save paste": "Tallenna paste"
|
||||
"Save paste": "Tallenna paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Message chiffré sur PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visiter ce lien pour voir la note. Donner l'URL à une autre personne lui permet également d'accéder à la note.",
|
||||
"URL shortener may expose your decrypt key in URL.": "Raccourcir l'URL peut exposer votre clé de déchiffrement dans l'URL.",
|
||||
"Save paste": "Sauver le paste"
|
||||
"Save paste": "Sauver le paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "הערה מוצפנת ב־PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "נא לבקר בקישור כדי לצפות בהערה. מסירת הקישור לאנשים כלשהם תאפשר גם להם לגשת להערה.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Titkosított jegyzet a PrivateBinen",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Látogasd meg ezt a hivatkozást a bejegyzés megtekintéséhez. Ha mások számára is megadod ezt a linket, azzal hozzáférnek ők is.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Catatan ter-ekrip di PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Kunjungi tautan ini untuk melihat catatan. Memberikan alamat URL pada siapapun juga, akan mengizinkan mereka untuk mengakses catatan, so pasti gitu loh Kaka.",
|
||||
"URL shortener may expose your decrypt key in URL.": "Pemendek URL mungkin akan menampakkan kunci dekrip Anda dalam URL.",
|
||||
"Save paste": "Simpan paste"
|
||||
"Save paste": "Simpan paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Nota crittografata su PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visita questo collegamento per vedere la nota. Dare l'URL a chiunque consente anche a loro di accedere alla nota.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener può esporre la tua chiave decrittografata nell'URL.",
|
||||
"Save paste": "Salva il messagio"
|
||||
"Save paste": "Salva il messagio",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": ".i lo lo notci ku mifra cu zvati sivlolnitvanku'a",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "rejgau fukpi"
|
||||
"Save paste": "rejgau fukpi",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Šifruoti užrašai ties PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Norėdami matyti užrašus, aplankykite šį tinklalapį. Pasidalinus šiuo URL adresu su kitais žmonėmis, jiems taip pat bus leidžiama prieiga prie šių užrašų.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL trumpinimo įrankis gali atskleisti URL adrese jūsų iššifravimo raktą.",
|
||||
"Save paste": "Įrašyti įdėjimą"
|
||||
"Save paste": "Įrašyti įdėjimą",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Kryptert notat på PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Besøk denne lenken for å se notatet. Hvis lenken deles med andre, vil de også kunne se notatet.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL forkorter kan avsløre dekrypteringsnøkkelen.",
|
||||
"Save paste": "Lagre utklipp"
|
||||
"Save paste": "Lagre utklipp",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Nòtas chifradas sus PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visitatz aqueste ligam per veire la nòta. Fornir lo ligam a qualqu’un mai li permet tanben d’accedir a la nòta.",
|
||||
"URL shortener may expose your decrypt key in URL.": "Los espleches d’acorchiment d’URL pòdon expausar la clau de deschiframent dins l’URL.",
|
||||
"Save paste": "Enregistrar lo tèxt"
|
||||
"Save paste": "Enregistrar lo tèxt",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Nota criptografada no PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visite esse link para ver a nota. Dar a URL para qualquer um permite que eles também acessem a nota.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Зашифрованная запись на PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Посетите эту ссылку чтобы просмотреть запись. Передача ссылки кому либо позволит им получить доступ к записи тоже.",
|
||||
"URL shortener may expose your decrypt key in URL.": "Сервис сокращения ссылок может получить ваш ключ расшифровки из ссылки.",
|
||||
"Save paste": "Сохранить запись"
|
||||
"Save paste": "Сохранить запись",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
|
||||
"URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
|
||||
"Save paste": "Save paste"
|
||||
"Save paste": "Save paste",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -185,5 +185,6 @@
|
|||
"Encrypted note on PrivateBin": "PrivateBin 上的加密笔记",
|
||||
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "访问此链接来查看该笔记。将此 URL 发送给任何人即可允许其访问该笔记。",
|
||||
"URL shortener may expose your decrypt key in URL.": "短链接服务可能会暴露您在 URL 中的解密密钥。",
|
||||
"Save paste": "保存内容"
|
||||
"Save paste": "保存内容",
|
||||
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes."
|
||||
}
|
||||
|
|
|
@ -78,9 +78,10 @@ class Configuration
|
|||
'markdown' => 'Markdown',
|
||||
),
|
||||
'traffic' => array(
|
||||
'limit' => 10,
|
||||
'header' => null,
|
||||
'exemptedIp' => null,
|
||||
'limit' => 10,
|
||||
'header' => '',
|
||||
'exempted' => '',
|
||||
'creators' => '',
|
||||
),
|
||||
'purge' => array(
|
||||
'limit' => 300,
|
||||
|
|
|
@ -199,13 +199,10 @@ class Controller
|
|||
ServerSalt::setStore($this->_model->getStore());
|
||||
TrafficLimiter::setConfiguration($this->_conf);
|
||||
TrafficLimiter::setStore($this->_model->getStore());
|
||||
if (!TrafficLimiter::canPass()) {
|
||||
$this->_return_message(
|
||||
1, I18n::_(
|
||||
'Please wait %d seconds between each post.',
|
||||
$this->_conf->getKey('limit', 'traffic')
|
||||
)
|
||||
);
|
||||
try {
|
||||
TrafficLimiter::canPass();
|
||||
} catch (Exception $e) {
|
||||
$this->_return_message(1, $e->getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,11 @@
|
|||
|
||||
namespace PrivateBin\Persistence;
|
||||
|
||||
use Exception;
|
||||
use IPLib\Factory;
|
||||
use IPLib\ParseStringFlag;
|
||||
use PrivateBin\Configuration;
|
||||
use PrivateBin\I18n;
|
||||
|
||||
/**
|
||||
* TrafficLimiter
|
||||
|
@ -24,22 +27,22 @@ use PrivateBin\Configuration;
|
|||
class TrafficLimiter extends AbstractPersistence
|
||||
{
|
||||
/**
|
||||
* time limit in seconds, defaults to 10s
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @var int
|
||||
*/
|
||||
private static $_limit = 10;
|
||||
|
||||
/**
|
||||
* listed ips are exempted from limits, defaults to null
|
||||
* listed IPs are the only ones allowed to create, defaults to null
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @var string|null
|
||||
*/
|
||||
private static $_exemptedIp = null;
|
||||
private static $_creators = null;
|
||||
|
||||
/**
|
||||
* listed IPs are exempted from limits, defaults to null
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @var string|null
|
||||
*/
|
||||
private static $_exempted = null;
|
||||
|
||||
/**
|
||||
* key to fetch IP address
|
||||
|
@ -51,28 +54,13 @@ class TrafficLimiter extends AbstractPersistence
|
|||
private static $_ipKey = 'REMOTE_ADDR';
|
||||
|
||||
/**
|
||||
* set the time limit in seconds
|
||||
* time limit in seconds, defaults to 10s
|
||||
*
|
||||
* @access public
|
||||
* @access private
|
||||
* @static
|
||||
* @param int $limit
|
||||
* @var int
|
||||
*/
|
||||
public static function setLimit($limit)
|
||||
{
|
||||
self::$_limit = $limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* set a list of ip(ranges) as string
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param string $exemptedIps
|
||||
*/
|
||||
public static function setExemptedIp($exemptedIp)
|
||||
{
|
||||
self::$_exemptedIp = $exemptedIp;
|
||||
}
|
||||
private static $_limit = 10;
|
||||
|
||||
/**
|
||||
* set configuration options of the traffic limiter
|
||||
|
@ -83,10 +71,11 @@ class TrafficLimiter extends AbstractPersistence
|
|||
*/
|
||||
public static function setConfiguration(Configuration $conf)
|
||||
{
|
||||
self::setCreators($conf->getKey('creators', 'traffic'));
|
||||
self::setExempted($conf->getKey('exempted', 'traffic'));
|
||||
self::setLimit($conf->getKey('limit', 'traffic'));
|
||||
self::setExemptedIp($conf->getKey('exemptedIp', 'traffic'));
|
||||
|
||||
if (($option = $conf->getKey('header', 'traffic')) !== null) {
|
||||
if (($option = $conf->getKey('header', 'traffic')) !== '') {
|
||||
$httpHeader = 'HTTP_' . $option;
|
||||
if (array_key_exists($httpHeader, $_SERVER) && !empty($_SERVER[$httpHeader])) {
|
||||
self::$_ipKey = $httpHeader;
|
||||
|
@ -94,6 +83,42 @@ class TrafficLimiter extends AbstractPersistence
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set a list of creator IP(-ranges) as string
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param string $creators
|
||||
*/
|
||||
public static function setCreators($creators)
|
||||
{
|
||||
self::$_creators = $creators;
|
||||
}
|
||||
|
||||
/**
|
||||
* set a list of exempted IP(-ranges) as string
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param string $exempted
|
||||
*/
|
||||
public static function setExempted($exempted)
|
||||
{
|
||||
self::$_exempted = $exempted;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the time limit in seconds
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param int $limit
|
||||
*/
|
||||
public static function setLimit($limit)
|
||||
{
|
||||
self::$_limit = $limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* get a HMAC of the current visitors IP address
|
||||
*
|
||||
|
@ -108,7 +133,7 @@ class TrafficLimiter extends AbstractPersistence
|
|||
}
|
||||
|
||||
/**
|
||||
* Validate $_ipKey against configured ipranges. If matched we will ignore the ip
|
||||
* validate $_ipKey against configured ipranges. If matched we will ignore the ip
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
|
@ -120,8 +145,8 @@ class TrafficLimiter extends AbstractPersistence
|
|||
if (is_string($ipRange)) {
|
||||
$ipRange = trim($ipRange);
|
||||
}
|
||||
$address = Factory::addressFromString($_SERVER[self::$_ipKey]);
|
||||
$range = Factory::rangeFromString($ipRange);
|
||||
$address = Factory::parseAddressString($_SERVER[self::$_ipKey]);
|
||||
$range = Factory::parseRangeString($ipRange, ParseStringFlag::IPV4_MAYBE_NON_DECIMAL);
|
||||
|
||||
// address could not be parsed, we might not be in IP space and try a string comparison instead
|
||||
if (is_null($address)) {
|
||||
|
@ -136,24 +161,35 @@ class TrafficLimiter extends AbstractPersistence
|
|||
}
|
||||
|
||||
/**
|
||||
* traffic limiter
|
||||
*
|
||||
* Make sure the IP address makes at most 1 request every 10 seconds.
|
||||
* make sure the IP address is allowed to perfom a request
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
* @return true
|
||||
*/
|
||||
public static function canPass()
|
||||
{
|
||||
// if creators are defined, the traffic limiter will only allow creation
|
||||
// for these, with no limits, and skip any other rules
|
||||
if (!empty(self::$_creators)) {
|
||||
$creatorIps = explode(',', self::$_creators);
|
||||
foreach ($creatorIps as $ipRange) {
|
||||
if (self::matchIp($ipRange) === true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
throw new Exception(I18n::_('Your IP is not authorized to create pastes.'));
|
||||
}
|
||||
|
||||
// disable limits if set to less then 1
|
||||
if (self::$_limit < 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if $_ipKey is exempted from ratelimiting
|
||||
if (!is_null(self::$_exemptedIp)) {
|
||||
$exIp_array = explode(',', self::$_exemptedIp);
|
||||
// check if $_ipKey is exempted from ratelimiting
|
||||
if (!empty(self::$_exempted)) {
|
||||
$exIp_array = explode(',', self::$_exempted);
|
||||
foreach ($exIp_array as $ipRange) {
|
||||
if (self::matchIp($ipRange) === true) {
|
||||
return true;
|
||||
|
@ -161,7 +197,7 @@ class TrafficLimiter extends AbstractPersistence
|
|||
}
|
||||
}
|
||||
|
||||
// this hash is used as an array key, hence a shorter algo is used
|
||||
// used as array key, which are limited in length, hence using algo with shorter range
|
||||
$hash = self::getHash('sha256');
|
||||
$now = time();
|
||||
$tl = (int) self::$_store->getValue('traffic_limiter', $hash);
|
||||
|
@ -175,6 +211,12 @@ class TrafficLimiter extends AbstractPersistence
|
|||
if (!self::$_store->setValue((string) $tl, 'traffic_limiter', $hash)) {
|
||||
error_log('failed to store the traffic limiter, it probably contains outdated information');
|
||||
}
|
||||
return $result;
|
||||
if ($result) {
|
||||
return true;
|
||||
}
|
||||
throw new Exception(I18n::_(
|
||||
'Please wait %d seconds between each post.',
|
||||
self::$_limit
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ endif;
|
|||
?>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/purify-2.3.6.js" integrity="sha512-N1GGPjbqLbwK821ZN7C925WuTwU4aDxz2CEEOXQ6/s6m6MBwVj8fh5fugiE2hzsm0xud3q7jpjZQ4ILnpMREYQ==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-PTOcxIWIPWCnb5vC4fmQDMqYGerwsu3AndVyPxn9NlQffIWYMPf/p28Z9SIygXsmcYjmTRmUiW5y7df63mNTfg==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-EdUms2nI12Cmtv014stIEBlyPjeKMHlkg7NiBJup1b7jJF5amKhev2RwTaldINXK4UaWbZtQ6hGuMPNvvNQZFA==" crossorigin="anonymous"></script>
|
||||
<!-- icon -->
|
||||
<link rel="apple-touch-icon" href="<?php echo I18n::encode($BASEPATH); ?>img/apple-touch-icon.png" sizes="180x180" />
|
||||
<link rel="icon" type="image/png" href="img/favicon-32x32.png" sizes="32x32" />
|
||||
|
|
|
@ -50,7 +50,7 @@ endif;
|
|||
?>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/purify-2.3.6.js" integrity="sha512-N1GGPjbqLbwK821ZN7C925WuTwU4aDxz2CEEOXQ6/s6m6MBwVj8fh5fugiE2hzsm0xud3q7jpjZQ4ILnpMREYQ==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-PTOcxIWIPWCnb5vC4fmQDMqYGerwsu3AndVyPxn9NlQffIWYMPf/p28Z9SIygXsmcYjmTRmUiW5y7df63mNTfg==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-EdUms2nI12Cmtv014stIEBlyPjeKMHlkg7NiBJup1b7jJF5amKhev2RwTaldINXK4UaWbZtQ6hGuMPNvvNQZFA==" crossorigin="anonymous"></script>
|
||||
<!-- icon -->
|
||||
<link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
|
||||
<link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />
|
||||
|
|
|
@ -38,27 +38,74 @@ class TrafficLimiterTest extends PHPUnit_Framework_TestCase
|
|||
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
||||
$this->assertTrue(TrafficLimiter::canPass(), 'first request may pass');
|
||||
sleep(1);
|
||||
$this->assertFalse(TrafficLimiter::canPass(), 'second request is to fast, may not pass');
|
||||
try {
|
||||
$this->assertFalse(TrafficLimiter::canPass(), 'expected an exception');
|
||||
} catch (Exception $e) {
|
||||
$this->assertEquals($e->getMessage(), 'Please wait 4 seconds between each post.', 'second request is to fast, may not pass');
|
||||
}
|
||||
sleep(4);
|
||||
$this->assertTrue(TrafficLimiter::canPass(), 'third request waited long enough and may pass');
|
||||
$_SERVER['REMOTE_ADDR'] = '2001:1620:2057:dead:beef::cafe:babe';
|
||||
$this->assertTrue(TrafficLimiter::canPass(), 'fourth request has different ip and may pass');
|
||||
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
||||
$this->assertFalse(TrafficLimiter::canPass(), 'fifth request is to fast, may not pass');
|
||||
try {
|
||||
$this->assertFalse(TrafficLimiter::canPass(), 'expected an exception');
|
||||
} catch (Exception $e) {
|
||||
$this->assertEquals($e->getMessage(), 'Please wait 4 seconds between each post.', 'fifth request is to fast, may not pass');
|
||||
}
|
||||
}
|
||||
|
||||
// exempted IPs configuration
|
||||
TrafficLimiter::setExemptedIp('1.2.3.4,10.10.10.0/24,2001:1620:2057::/48');
|
||||
$this->assertFalse(TrafficLimiter::canPass(), 'still too fast and not exempted');
|
||||
public function testTrafficLimitExempted()
|
||||
{
|
||||
TrafficLimiter::setExempted('1.2.3.4,10.10.10.0/24,2001:1620:2057::/48');
|
||||
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
||||
$this->assertTrue(TrafficLimiter::canPass(), 'first request may pass');
|
||||
try {
|
||||
$this->assertFalse(TrafficLimiter::canPass(), 'expected an exception');
|
||||
} catch (Exception $e) {
|
||||
$this->assertEquals($e->getMessage(), 'Please wait 4 seconds between each post.', 'not exempted');
|
||||
}
|
||||
$_SERVER['REMOTE_ADDR'] = '10.10.10.10';
|
||||
$this->assertTrue(TrafficLimiter::canPass(), 'IPv4 in exempted range');
|
||||
$this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but IPv4 in exempted range');
|
||||
$_SERVER['REMOTE_ADDR'] = '2001:1620:2057:dead:beef::cafe:babe';
|
||||
$this->assertTrue(TrafficLimiter::canPass(), 'IPv6 in exempted range');
|
||||
$this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but IPv6 in exempted range');
|
||||
TrafficLimiter::setExemptedIp('127.*,foobar');
|
||||
$this->assertFalse(TrafficLimiter::canPass(), 'request is to fast, invalid range');
|
||||
TrafficLimiter::setExempted('127.*,foobar');
|
||||
$this->assertTrue(TrafficLimiter::canPass(), 'first cached request may pass');
|
||||
try {
|
||||
$this->assertFalse(TrafficLimiter::canPass(), 'expected an exception');
|
||||
} catch (Exception $e) {
|
||||
$this->assertEquals($e->getMessage(), 'Please wait 4 seconds between each post.', 'request is too fast, invalid range');
|
||||
}
|
||||
$_SERVER['REMOTE_ADDR'] = 'foobar';
|
||||
$this->assertTrue(TrafficLimiter::canPass(), 'non-IP address');
|
||||
$this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but non-IP address matches exempted range');
|
||||
$this->assertTrue(TrafficLimiter::canPass(), 'request is too fast, but non-IP address matches exempted range');
|
||||
}
|
||||
|
||||
public function testTrafficLimitCreators()
|
||||
{
|
||||
TrafficLimiter::setCreators('1.2.3.4,10.10.10.0/24,2001:1620:2057::/48');
|
||||
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
||||
try {
|
||||
$this->assertFalse(TrafficLimiter::canPass(), 'expected an exception');
|
||||
} catch (Exception $e) {
|
||||
$this->assertEquals($e->getMessage(), 'Your IP is not authorized to create pastes.', 'not a creator');
|
||||
}
|
||||
$_SERVER['REMOTE_ADDR'] = '10.10.10.10';
|
||||
$this->assertTrue(TrafficLimiter::canPass(), 'IPv4 in creator range');
|
||||
$this->assertTrue(TrafficLimiter::canPass(), 'request is too fast, but IPv4 in creator range');
|
||||
$_SERVER['REMOTE_ADDR'] = '2001:1620:2057:dead:beef::cafe:babe';
|
||||
$this->assertTrue(TrafficLimiter::canPass(), 'IPv6 in creator range');
|
||||
$this->assertTrue(TrafficLimiter::canPass(), 'request is too fast, but IPv6 in creator range');
|
||||
TrafficLimiter::setCreators('127.*,foobar');
|
||||
try {
|
||||
$this->assertFalse(TrafficLimiter::canPass(), 'expected an exception');
|
||||
} catch (Exception $e) {
|
||||
$this->assertEquals($e->getMessage(), 'Your IP is not authorized to create pastes.', 'request is to fast, not a creator');
|
||||
}
|
||||
$_SERVER['REMOTE_ADDR'] = 'foobar';
|
||||
$this->assertTrue(TrafficLimiter::canPass(), 'non-IP address');
|
||||
$this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but non-IP address matches creator');
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user