├── .htaccess.disabled ├── CHANGELOG.md ├── CREDITS.md ├── LICENSE.md ├── Procfile ├── README.md ├── SECURITY.md ├── bin ├── administration └── migrate ├── browserconfig.xml ├── cfg ├── .htaccess └── conf.sample.php ├── css ├── bootstrap │ ├── bootstrap-3.4.1.css │ ├── bootstrap-theme-3.4.1.css │ ├── darkstrap-0.9.3.css │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ └── privatebin.css ├── noscript.css ├── prettify │ ├── desert.css │ ├── doxy.css │ ├── prettify.css │ ├── sons-of-obsidian.css │ └── sunburst.css └── privatebin.css ├── i18n ├── ar.json ├── bg.json ├── ca.json ├── co.json ├── cs.json ├── de.json ├── el.json ├── en.json ├── es.json ├── et.json ├── fi.json ├── fr.json ├── he.json ├── hi.json ├── hu.json ├── id.json ├── it.json ├── ja.json ├── jbo.json ├── ku.json ├── la.json ├── languages.json ├── lt.json ├── nl.json ├── no.json ├── oc.json ├── pl.json ├── pt.json ├── ru.json ├── sk.json ├── sl.json ├── sv.json ├── th.json ├── tr.json ├── uk.json └── zh.json ├── img ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── apple-touch-icon.png ├── busy.gif ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon.ico ├── icon.svg ├── icon_clone.png ├── icon_email.png ├── icon_new.png ├── icon_qr.png ├── icon_raw.png ├── icon_send.png ├── icon_shorten.png ├── logo.svg ├── mstile-144x144.png ├── mstile-150x150.png ├── mstile-310x150.png ├── mstile-310x310.png ├── mstile-70x70.png └── safari-pinned-tab.svg ├── index.php ├── js ├── base-x-4.0.0.js ├── base64-1.7.js ├── bootstrap-3.4.1.js ├── comment.jsonld ├── commentmeta.jsonld ├── jquery-3.7.0.js ├── kjua-0.9.0.js ├── legacy.js ├── package-lock.json ├── package.json ├── paste.jsonld ├── pastemeta.jsonld ├── prettify.js ├── privatebin.js ├── purify-3.0.4.js ├── rawinflate-0.3.js ├── showdown-2.1.0.js ├── types.jsonld ├── zlib-1.2.13.js └── zlib-1.2.13.wasm ├── lib ├── .htaccess ├── Configuration.php ├── Controller.php ├── Data │ ├── AbstractData.php │ ├── Database.php │ ├── Filesystem.php │ ├── GoogleCloudStorage.php │ └── S3Storage.php ├── Filter.php ├── FormatV2.php ├── I18n.php ├── Json.php ├── Model.php ├── Model │ ├── AbstractModel.php │ ├── Comment.php │ └── Paste.php ├── Persistence │ ├── AbstractPersistence.php │ ├── PurgeLimiter.php │ ├── ServerSalt.php │ └── TrafficLimiter.php ├── Request.php ├── View.php ├── Vizhash16x16.php └── YourlsProxy.php ├── manifest.json ├── robots.txt ├── tpl ├── .htaccess ├── bootstrap.php ├── page.php └── yourlsproxy.php └── vendor ├── .htaccess ├── autoload.php ├── composer ├── ClassLoader.php ├── InstalledVersions.php ├── autoload_classmap.php ├── autoload_namespaces.php ├── autoload_psr4.php ├── autoload_real.php ├── autoload_static.php ├── installed.php └── platform_check.php ├── jdenticon └── jdenticon │ └── src │ ├── Canvas │ ├── Canvas.php │ ├── CanvasContext.php │ ├── ColorUtils.php │ ├── Matrix.php │ ├── Png │ │ ├── PngBuffer.php │ │ ├── PngEncoder.php │ │ └── PngPalette.php │ ├── Point.php │ └── Rasterization │ │ ├── Edge.php │ │ ├── EdgeIntersection.php │ │ ├── EdgeSuperSampleIntersection.php │ │ ├── EdgeTable.php │ │ ├── Layer.php │ │ ├── LayerManager.php │ │ ├── Rasterizer.php │ │ ├── SuperSampleBuffer.php │ │ └── SuperSampleRange.php │ ├── Color.php │ ├── Identicon.php │ ├── IdenticonStyle.php │ ├── Rendering │ ├── AbstractRenderer.php │ ├── ColorTheme.php │ ├── IconGenerator.php │ ├── ImagickRenderer.php │ ├── InternalPngRenderer.php │ ├── Point.php │ ├── Rectangle.php │ ├── RendererInterface.php │ ├── SvgPath.php │ ├── SvgRenderer.php │ ├── Transform.php │ └── TriangleDirection.php │ └── Shapes │ ├── Shape.php │ ├── ShapeCategory.php │ ├── ShapeDefinitions.php │ └── ShapePosition.php ├── mlocati └── ip-lib │ ├── ip-lib.php │ └── src │ ├── Address │ ├── AddressInterface.php │ ├── AssignedRange.php │ ├── IPv4.php │ ├── IPv6.php │ └── Type.php │ ├── Factory.php │ ├── ParseStringFlag.php │ ├── Range │ ├── AbstractRange.php │ ├── Pattern.php │ ├── RangeInterface.php │ ├── Single.php │ ├── Subnet.php │ └── Type.php │ └── Service │ ├── BinaryMath.php │ ├── RangesFromBoundaryCalculator.php │ └── UnsignedIntegerMath.php └── yzalis └── identicon └── src └── Identicon ├── Generator ├── BaseGenerator.php ├── GdGenerator.php ├── GeneratorInterface.php ├── ImageMagickGenerator.php └── SvgGenerator.php └── Identicon.php /.htaccess.disabled: -------------------------------------------------------------------------------- 1 | RewriteEngine on 2 | RewriteCond !%{HTTP_USER_AGENT} "Let's Encrypt validation server" [NC] 3 | RewriteCond %{HTTP_USER_AGENT} ^.*(bot|spider|crawl|https?://|WhatsApp|SkypeUriPreview|facebookexternalhit) [NC] 4 | RewriteRule .* - [R=403,L] 5 | 6 | 7 | php_value max_execution_time 30 8 | php_value post_max_size 10M 9 | php_value upload_max_size 10M 10 | php_value upload_max_filesize 10M 11 | php_value max_file_uploads 100 12 | 13 | -------------------------------------------------------------------------------- /CREDITS.md: -------------------------------------------------------------------------------- 1 | # Credits 2 | 3 | ## Active contributors 4 | 5 | * Simon Rupf - current developer and maintainer 6 | * rugk - security review, doc improvment, JS refactoring & various other stuff 7 | * R4SAS - python client, compression, blob URI to support larger attachments 8 | 9 | ## Past contributions 10 | 11 | * Sébastien Sauvage - original idea and main developer 12 | * Alexey Gladkov - syntax highlighting 13 | * Greg Knaddison - robots.txt 14 | * MrKooky - HTML5 markup, CSS cleanup 15 | * Simon Rupf - WebCrypto, unit tests, container images, database backend, MVC, configuration, i18n 16 | * Hexalyse - Password protection 17 | * Viktor Stanchev - File upload support 18 | * azlux - Tab character input support 19 | * Adam Fisher - old Favicons 20 | * rugk - new logo/icons 21 | * Sobak - PSR-4 and PSR-2 refactoring 22 | * Nathaniel Olsen - jQuery upgrade 23 | * Alexander Demenshin - modal password dialog 24 | * PunKeel - first docker container 25 | * thororm - Display of video, audio & PDF, drag & drop, preview of attachments 26 | * Harald Leithner - base58 encoding of key 27 | * Haocen - lots of bugfixes and UI improvements 28 | * Lucas Savva - configurable config file location, NixOS packaging 29 | * rodehoed - option to exempt ips from the rate-limiter 30 | * Mark van Holsteijn - Google Cloud Storage backend 31 | * Austin Huang - Oracle database support 32 | * Felix J. Ogris - S3 Storage backend, script for data backend migrations, dropped singleton behaviour of data backends 33 | * Mounir Idrassi & J. Mozdzen - secure YOURLS integration 34 | * Felipe Nakandakari - enabled AWS SDK to use default credential provider chain in the S3 Storage backend 35 | 36 | ## Translations 37 | * Hexalyse - French 38 | * Kuba Niewiarowski - Polish 39 | * Gabbalo - German 40 | * Draky50110 - French 41 | * Filip Muki Dobranić - Slovene 42 | * Jiawei Zhou - Chinese 43 | * Stefano Marty - Italian 44 | * R4SAS - Russian 45 | * Alfredo Fabián Altamirano Tena - Spanish 46 | * Quent-in - Occitan 47 | * idarlund - Norwegian 48 | * Tulio Leao - Portuguese 49 | * Michael van Schaik - Dutch 50 | * Péter Tabajdi - Hungarian 51 | * info-path - Czech 52 | * BigWax - Bulgarian 53 | * AndriiZ - Ukrainian 54 | * Yaron Shahrabani - Hebrew 55 | * Moo - Lithuanian 56 | * whenwesober - Indonesian 57 | * retiolus - Catalan 58 | * sarnane - Estonian 59 | * foxsouns - Lojban 60 | * Patriccollu di Santa Maria è Sichè - Corsican 61 | * Markus Mikkonen - Finnish 62 | * Emir Ensar Rahmanlar - Turkish 63 | * Stevo984 - Slovak 64 | * Christos Karamolegkos - Greek 65 | * jaideejung007 - Thai 66 | * Nicolas Le Gall - Japanese 67 | * lazerns - Arabic 68 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: vendor/bin/heroku-php-apache2 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [![PrivateBin](https://cdn.rawgit.com/PrivateBin/assets/master/images/preview/logoSmall.png)](https://privatebin.info/) 2 | 3 | *Current version: 1.6.0* 4 | 5 | **PrivateBin** is a minimalist, open source online 6 | [pastebin](https://en.wikipedia.org/wiki/Pastebin) 7 | where the server has zero knowledge of pasted data. 8 | 9 | Data is encrypted and decrypted in the browser using 256bit AES in 10 | [Galois Counter mode](https://en.wikipedia.org/wiki/Galois/Counter_Mode). 11 | 12 | This is a fork of ZeroBin, originally developed by 13 | [Sébastien Sauvage](https://github.com/sebsauvage/ZeroBin). PrivateBin was 14 | refactored to allow easier and cleaner extensions and has many additional 15 | features. It is, however, still fully compatible to the original ZeroBin 0.19 16 | data storage scheme. Therefore, such installations can be upgraded to PrivateBin 17 | without losing any data. 18 | 19 | ## What PrivateBin provides 20 | 21 | + As a server administrator you don't have to worry if your users post content 22 | that is considered illegal in your country. You have plausible deniability of 23 | any of the pastes content. If requested or enforced, you can delete any paste 24 | from your system. 25 | 26 | + Pastebin-like system to store text documents, code samples, etc. 27 | 28 | + Encryption of data sent to server. 29 | 30 | + Possibility to set a password which is required to read the paste. It further 31 | protects a paste and prevents people stumbling upon your paste's link 32 | from being able to read it without the password. 33 | 34 | ## What it doesn't provide 35 | 36 | - As a user you have to trust the server administrator not to inject any 37 | malicious code. For security, a PrivateBin installation *has to be used over* 38 | *HTTPS*! Otherwise you would also have to trust your internet provider, and 39 | any jurisdiction the traffic passes through. Additionally the instance should 40 | be secured by 41 | [HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security). It can 42 | use traditional certificate authorities and/or use a 43 | [DNSSEC](https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions) 44 | protected 45 | [DANE](https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities) 46 | record. 47 | 48 | - The "key" used to encrypt the paste is part of the URL. If you publicly post 49 | the URL of a paste that is not password-protected, anyone can read it. 50 | Use a password if you want your paste to remain private. In that case, make 51 | sure to use a strong password and share it privately and end-to-end-encrypted. 52 | 53 | - A server admin can be forced to hand over access logs to the authorities. 54 | PrivateBin encrypts your text and the discussion contents, but who accessed a 55 | paste (first) might still be disclosed via access logs. 56 | 57 | - In case of a server breach your data is secure as it is only stored encrypted 58 | on the server. However, the server could be absused or the server admin could 59 | be legally forced into sending malicious code to their users, which logs 60 | the decryption key and sends it to a server when a user accesses a paste. 61 | Therefore, do not access any PrivateBin instance if you think it has been 62 | compromised. As long as no user accesses this instance with a previously 63 | generated URL, the content can't be decrypted. 64 | 65 | ## Options 66 | 67 | Some features are optional and can be enabled or disabled in the [configuration 68 | file](https://github.com/PrivateBin/PrivateBin/wiki/Configuration): 69 | 70 | * Password protection 71 | 72 | * Discussions, anonymous or with nicknames and IP based identicons or vizhashes 73 | 74 | * Expiration times, including a "forever" and "burn after reading" option 75 | 76 | * Markdown format support for HTML formatted pastes, including preview function 77 | 78 | * Syntax highlighting for source code using prettify.js, including 4 prettify 79 | themes 80 | 81 | * File upload support, image, media and PDF preview (disabled by default, size 82 | limit adjustable) 83 | 84 | * Templates: By default there are bootstrap CSS, darkstrap and "classic ZeroBin" 85 | to choose from and it is easy to adapt these to your own websites layout or 86 | create your own. 87 | 88 | * Translation system and automatic browser language detection (if enabled in 89 | browser) 90 | 91 | * Language selection (disabled by default, as it uses a session cookie) 92 | 93 | * QR code for paste URLs, to easily transfer them over to mobile devices 94 | 95 | ## Further resources 96 | 97 | * [FAQ](https://github.com/PrivateBin/PrivateBin/wiki/FAQ) 98 | 99 | * [Installation guide](https://github.com/PrivateBin/PrivateBin/blob/master/doc/Installation.md#installation) 100 | 101 | * [Configuration guide](https://github.com/PrivateBin/PrivateBin/wiki/Configuration) 102 | 103 | * [Templates](https://github.com/PrivateBin/PrivateBin/wiki/Templates) 104 | 105 | * [Translation guide](https://github.com/PrivateBin/PrivateBin/wiki/Translation) 106 | 107 | * [Developer guide](https://github.com/PrivateBin/PrivateBin/wiki/Development) 108 | 109 | Run into any issues? Have ideas for further developments? Please 110 | [report](https://github.com/PrivateBin/PrivateBin/issues) them! 111 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | | ------- | ------------------ | 7 | | 1.6.0 | :heavy_check_mark: | 8 | | < 1.6.0 | :x: | 9 | 10 | ## Reporting a Vulnerability 11 | 12 | You can send us email at security@privatebin.org. You should be able to get 13 | a response within a week (usually during the next weekend). The respondee will 14 | reply from their personal address and can offer you their GPG public key to 15 | support end-to-end encrypted communication on sensitive topics or attachments. 16 | 17 | You can also contact us via the regular issue tracker if the risk of early 18 | publication is low or you would request input from other PrivateBin users. 19 | -------------------------------------------------------------------------------- /browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | #ffc40d 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /cfg/.htaccess: -------------------------------------------------------------------------------- 1 | Require all denied 2 | -------------------------------------------------------------------------------- /css/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/css/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /css/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/css/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /css/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/css/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /css/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/css/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /css/bootstrap/privatebin.css: -------------------------------------------------------------------------------- 1 | /** 2 | * PrivateBin 3 | * 4 | * a zero-knowledge paste bin 5 | * 6 | * @link https://github.com/PrivateBin/PrivateBin 7 | * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) 8 | * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License 9 | * @version 1.6.0 10 | */ 11 | 12 | body { 13 | padding: 0 0 30px; 14 | } 15 | 16 | body.navbar-spacing { 17 | padding-top: 70px; 18 | } 19 | 20 | body.loading { 21 | cursor: wait; 22 | } 23 | 24 | .buttondisabled { 25 | opacity: 0.3; 26 | } 27 | 28 | .navbar-nav { 29 | margin: 0 8px; 30 | } 31 | 32 | .nav.navbar-nav > li { 33 | margin-left: 8px; 34 | } 35 | 36 | .navbar-brand { 37 | padding: 6px 4px 0 8px; 38 | } 39 | 40 | .navbar-form { 41 | padding: 0; 42 | } 43 | 44 | .dropdown-menu > li > label, .dropdown-menu > li > div { 45 | clear: both; 46 | display: block; 47 | font-weight: normal; 48 | line-height: 1.42857; 49 | white-space: nowrap; 50 | } 51 | 52 | .dropdown-menu > li > label { 53 | color: #333; 54 | padding: 3px 20px 3px 40px; 55 | } 56 | 57 | .dropdown-menu > li > div { 58 | color: #777; 59 | padding: 3px 20px; 60 | cursor: default; 61 | } 62 | 63 | .pull-right .dropdown-menu { 64 | margin-left: -5em; 65 | } 66 | 67 | #language { 68 | margin-right: 8px; 69 | } 70 | 71 | #attachmentPreview img { 72 | max-width: 100%; 73 | height: auto; 74 | margin-bottom: 20px; 75 | } 76 | 77 | #attachmentPreview .pdfPreview { 78 | width: 100%; 79 | height: 100vh; 80 | margin-bottom: 20px; 81 | } 82 | 83 | #dropzone { 84 | text-align: center; 85 | position: fixed; 86 | top: 0; 87 | left: 0; 88 | width: 100%; 89 | height: 100%; 90 | z-index: 1000; 91 | opacity: 0.6; 92 | background-color: #99ccff; 93 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z'/%3E%3C/svg%3E"); 94 | background-repeat: no-repeat; 95 | background-position: center; 96 | background-size: 25vh; 97 | outline: 2px dashed #228bff; 98 | outline-offset: -50px; 99 | } 100 | 101 | .dragAndDropFile{ 102 | color: #777; 103 | font-size: 1em; 104 | display: inline; 105 | white-space: normal; 106 | } 107 | 108 | #deletelink { 109 | float: right; 110 | margin-left: 5px; 111 | } 112 | 113 | #qrcodemodalClose { 114 | float: right; 115 | } 116 | #qrcode-display { 117 | width: 200px; 118 | height: 200px; 119 | margin: auto; 120 | } 121 | 122 | #pastelink { 123 | display: inline; 124 | } 125 | 126 | #pastelink > a { 127 | word-wrap: break-word; 128 | } 129 | 130 | #preview { 131 | margin-bottom: 10px; 132 | } 133 | 134 | #message, .replymessage { 135 | font-family: monospace; 136 | resize: vertical; 137 | } 138 | 139 | #nickname { 140 | margin: 5px 0; 141 | } 142 | 143 | #comments, #comments button { 144 | margin-bottom: 10px; 145 | } 146 | 147 | #filewrap { 148 | transition: background-color 0.75s ease-out; 149 | } 150 | 151 | .comment { 152 | border-left: 1px solid #ccc; 153 | padding: 5px 0 5px 10px; 154 | white-space: pre-wrap; 155 | transition: background-color 0.75s ease-out; 156 | } 157 | 158 | .highlight { 159 | background-color: #ffdd86; 160 | transition: background-color 0.2s ease-in; 161 | } 162 | 163 | footer h4 { 164 | margin-top: 0; 165 | } 166 | 167 | li.L0, li.L1, li.L2, li.L3, li.L5, li.L6, li.L7, li.L8 { 168 | list-style-type: decimal !important; 169 | } 170 | 171 | .dark-theme .alert-info .alert-link { 172 | color: #fff; 173 | } 174 | 175 | /* address 2K or 4K monitors when using bootstrap 3 */ 176 | @media (min-width: 1280px) { 177 | .container { 178 | width: 100%; 179 | padding-left: 4ch; 180 | padding-right: 4ch; 181 | } 182 | } 183 | 184 | .modal-dialog { 185 | margin: auto !important; 186 | } 187 | 188 | /* makeup for the original margin on modal-dialog */ 189 | @media (min-width: 768px) { 190 | .modal-content { 191 | margin: 30px 0; 192 | } 193 | } 194 | 195 | .modal-content { 196 | margin: 10px; 197 | } 198 | 199 | .modal-body { 200 | display: flex; 201 | justify-content: center; 202 | align-items: center; 203 | } 204 | 205 | .modal .modal-content button { 206 | margin: 0.5em 0; 207 | } 208 | -------------------------------------------------------------------------------- /css/noscript.css: -------------------------------------------------------------------------------- 1 | /** 2 | * PrivateBin 3 | * 4 | * CSS file only loaded when no JavaScript available. 5 | * 6 | * @link https://github.com/PrivateBin/PrivateBin 7 | * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) 8 | * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License 9 | * @version 1.6.0 10 | */ 11 | 12 | /* When there is no script at all other */ 13 | .noscript-hide { 14 | display: none; 15 | } 16 | -------------------------------------------------------------------------------- /css/prettify/desert.css: -------------------------------------------------------------------------------- 1 | pre .atn,pre .kwd,pre .tag{font-weight:700}pre.prettyprint{display:block;background-color:#333}pre .nocode{background-color:none;color:#000}pre .str{color:#ffa0a0}pre .kwd{color:khaki}pre .com{color:#87ceeb}pre .typ{color:#98fb98}pre .lit{color:#cd5c5c}pre .pln,pre .pun{color:#fff}pre .tag{color:khaki}pre .atn{color:#bdb76b}pre .atv{color:#ffa0a0}pre .dec{color:#98fb98}ol.linenums{margin-top:0;margin-bottom:0;color:#AEAEAE}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}@media print{pre.prettyprint{background-color:none}code .str,pre .str{color:#060}code .kwd,pre .kwd{color:#006;font-weight:700}code .com,pre .com{color:#600;font-style:italic}code .typ,pre .typ{color:#404;font-weight:700}code .lit,pre .lit{color:#044}code .pun,pre .pun{color:#440}code .pln,pre .pln{color:#000}code .tag,pre .tag{color:#006;font-weight:700}code .atn,pre .atn{color:#404}code .atv,pre .atv{color:#060}} -------------------------------------------------------------------------------- /css/prettify/doxy.css: -------------------------------------------------------------------------------- 1 | a,code.prettyprint a,pre.prettyprint a{text-decoration:none}code .str,pre .str{color:#fec243}code .kwd,pre .kwd{color:#8470FF}code .com,pre .com{color:#32cd32;font-style:italic}code .typ,pre .typ{color:#6ecbcc}code .lit,pre .lit{color:#d06}code .pun,pre .pun{color:#8B8970}code .pln,pre .pln{color:#f0f0f0}code .tag,pre .tag{color:#9c9cff}code .htm,pre .htm{color:plum}code .xsl,pre .xsl{color:#d0a0d0}code .atn,pre .atn{color:#46eeee;font-weight:400}code .atv,pre .atv{color:#EEB4B4}code .dec,pre .dec{color:#3387CC}code.prettyprint,pre.prettyprint{font-family:'Droid Sans Mono','CPMono_v07 Bold','Droid Sans';font-weight:700;font-size:9pt;background-color:#0f0f0f;-moz-border-radius:8px;-webkit-border-radius:8px;-o-border-radius:8px;-ms-border-radius:8px;-khtml-border-radius:8px;border-radius:8px}pre.prettyprint{width:95%;margin:1em auto;padding:1em;white-space:pre-wrap}ol.linenums{margin-top:0;margin-bottom:0;color:#8B8970}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}@media print{code.prettyprint,pre.prettyprint{background-color:#fff}code .str,pre .str{color:#088}code .kwd,pre .kwd{color:#006;font-weight:700}code .com,pre .com{color:#oc3;font-style:italic}code .typ,pre .typ{color:#404;font-weight:700}code .lit,pre .lit{color:#044}code .pun,pre .pun{color:#440}code .pln,pre .pln{color:#000}code .tag,pre .tag{color:#b66ff7;font-weight:700}code .htm,code .xsl,pre .htm,pre .xsl{color:#606;font-weight:700}code .atn,pre .atn{color:#c71585;font-weight:400}code .atv,pre .atv{color:#088;font-weight:400}} -------------------------------------------------------------------------------- /css/prettify/prettify.css: -------------------------------------------------------------------------------- 1 | .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.clo,.opn,.pun{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.kwd,.tag,.typ{font-weight:700}.str{color:#060}.kwd{color:#006}.com{color:#600;font-style:italic}.typ{color:#404}.lit{color:#044}.clo,.opn,.pun{color:#440}.tag{color:#006}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} -------------------------------------------------------------------------------- /css/prettify/sons-of-obsidian.css: -------------------------------------------------------------------------------- 1 | .str{color:#EC7600}.kwd{color:#93C763}.com{color:#66747B}.typ{color:#678CB1}.lit{color:#FACD22}.pln,.pun{color:#F1F2F3}.tag{color:#8AC763}.atn{color:#E0E2E4}.atv{color:#EC7600}.dec{color:purple}pre.prettyprint{border:0 solid #888}ol.linenums{margin-top:0;margin-bottom:0}.prettyprint{background:#000}li.L0,li.L1,li.L2,li.L3,li.L4,li.L5,li.L6,li.L7,li.L8,li.L9{color:#555;list-style-type:decimal}li.L1,li.L3,li.L5,li.L7,li.L9{background:#111}@media print{.kwd,.tag,.typ{font-weight:700}.str{color:#060}.kwd{color:#006}.com{color:#600;font-style:italic}.typ{color:#404}.lit{color:#044}.pun{color:#440}.pln{color:#000}.tag{color:#006}.atn{color:#404}.atv{color:#060}} -------------------------------------------------------------------------------- /css/prettify/sunburst.css: -------------------------------------------------------------------------------- 1 | code .str,pre .str{color:#65B042}code .kwd,pre .kwd{color:#E28964}code .com,pre .com{color:#AEAEAE;font-style:italic}code .typ,pre .typ{color:#89bdff}code .lit,pre .lit{color:#3387CC}code .pln,code .pun,pre .pln,pre .pun{color:#fff}code .tag,pre .tag{color:#89bdff}code .atn,pre .atn{color:#bdb76b}code .atv,pre .atv{color:#65B042}code .dec,pre .dec{color:#3387CC}code.prettyprint,pre.prettyprint{background-color:#000;border-radius:8px}pre.prettyprint{width:95%;margin:1em auto;padding:1em;white-space:pre-wrap}ol.linenums{margin-top:0;margin-bottom:0;color:#AEAEAE}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}@media print{code .str,pre .str{color:#060}code .kwd,pre .kwd{color:#006;font-weight:700}code .com,pre .com{color:#600;font-style:italic}code .typ,pre .typ{color:#404;font-weight:700}code .lit,pre .lit{color:#044}code .pun,pre .pun{color:#440}code .pln,pre .pln{color:#000}code .tag,pre .tag{color:#006;font-weight:700}code .atn,pre .atn{color:#404}code .atv,pre .atv{color:#060}} -------------------------------------------------------------------------------- /img/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/img/android-chrome-192x192.png -------------------------------------------------------------------------------- /img/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/img/android-chrome-512x512.png -------------------------------------------------------------------------------- /img/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/img/apple-touch-icon.png -------------------------------------------------------------------------------- /img/busy.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/img/busy.gif -------------------------------------------------------------------------------- /img/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/img/favicon-16x16.png -------------------------------------------------------------------------------- /img/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/img/favicon-32x32.png -------------------------------------------------------------------------------- /img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/img/favicon.ico -------------------------------------------------------------------------------- /img/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /img/icon_clone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/img/icon_clone.png -------------------------------------------------------------------------------- /img/icon_email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/img/icon_email.png -------------------------------------------------------------------------------- /img/icon_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/img/icon_new.png -------------------------------------------------------------------------------- /img/icon_qr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/img/icon_qr.png -------------------------------------------------------------------------------- /img/icon_raw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/img/icon_raw.png -------------------------------------------------------------------------------- /img/icon_send.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/img/icon_send.png -------------------------------------------------------------------------------- /img/icon_shorten.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/img/icon_shorten.png -------------------------------------------------------------------------------- /img/logo.svg: -------------------------------------------------------------------------------- 1 | PrivateBin 2 | -------------------------------------------------------------------------------- /img/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/img/mstile-144x144.png -------------------------------------------------------------------------------- /img/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/img/mstile-150x150.png -------------------------------------------------------------------------------- /img/mstile-310x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/img/mstile-310x150.png -------------------------------------------------------------------------------- /img/mstile-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/img/mstile-310x310.png -------------------------------------------------------------------------------- /img/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/img/mstile-70x70.png -------------------------------------------------------------------------------- /img/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | = 255) { throw new TypeError('Alphabet too long') } 10 | var BASE_MAP = new Uint8Array(256) 11 | for (var j = 0; j < BASE_MAP.length; j++) { 12 | BASE_MAP[j] = 255 13 | } 14 | for (var i = 0; i < ALPHABET.length; i++) { 15 | var x = ALPHABET.charAt(i) 16 | var xc = x.charCodeAt(0) 17 | if (BASE_MAP[xc] !== 255) { throw new TypeError(x + ' is ambiguous') } 18 | BASE_MAP[xc] = i 19 | } 20 | var BASE = ALPHABET.length 21 | var LEADER = ALPHABET.charAt(0) 22 | var FACTOR = Math.log(BASE) / Math.log(256) // log(BASE) / log(256), rounded up 23 | var iFACTOR = Math.log(256) / Math.log(BASE) // log(256) / log(BASE), rounded up 24 | function encode (source) { 25 | if (source instanceof Uint8Array) { 26 | } else if (ArrayBuffer.isView(source)) { 27 | source = new Uint8Array(source.buffer, source.byteOffset, source.byteLength) 28 | } else if (Array.isArray(source)) { 29 | source = Uint8Array.from(source) 30 | } 31 | if (!(source instanceof Uint8Array)) { throw new TypeError('Expected Uint8Array') } 32 | if (source.length === 0) { return '' } 33 | // Skip & count leading zeroes. 34 | var zeroes = 0 35 | var length = 0 36 | var pbegin = 0 37 | var pend = source.length 38 | while (pbegin !== pend && source[pbegin] === 0) { 39 | pbegin++ 40 | zeroes++ 41 | } 42 | // Allocate enough space in big-endian base58 representation. 43 | var size = ((pend - pbegin) * iFACTOR + 1) >>> 0 44 | var b58 = new Uint8Array(size) 45 | // Process the bytes. 46 | while (pbegin !== pend) { 47 | var carry = source[pbegin] 48 | // Apply "b58 = b58 * 256 + ch". 49 | var i = 0 50 | for (var it1 = size - 1; (carry !== 0 || i < length) && (it1 !== -1); it1--, i++) { 51 | carry += (256 * b58[it1]) >>> 0 52 | b58[it1] = (carry % BASE) >>> 0 53 | carry = (carry / BASE) >>> 0 54 | } 55 | if (carry !== 0) { throw new Error('Non-zero carry') } 56 | length = i 57 | pbegin++ 58 | } 59 | // Skip leading zeroes in base58 result. 60 | var it2 = size - length 61 | while (it2 !== size && b58[it2] === 0) { 62 | it2++ 63 | } 64 | // Translate the result into a string. 65 | var str = LEADER.repeat(zeroes) 66 | for (; it2 < size; ++it2) { str += ALPHABET.charAt(b58[it2]) } 67 | return str 68 | } 69 | function decodeUnsafe (source) { 70 | if (typeof source !== 'string') { throw new TypeError('Expected String') } 71 | if (source.length === 0) { return new Uint8Array() } 72 | var psz = 0 73 | // Skip and count leading '1's. 74 | var zeroes = 0 75 | var length = 0 76 | while (source[psz] === LEADER) { 77 | zeroes++ 78 | psz++ 79 | } 80 | // Allocate enough space in big-endian base256 representation. 81 | var size = (((source.length - psz) * FACTOR) + 1) >>> 0 // log(58) / log(256), rounded up. 82 | var b256 = new Uint8Array(size) 83 | // Process the characters. 84 | while (source[psz]) { 85 | // Decode character 86 | var carry = BASE_MAP[source.charCodeAt(psz)] 87 | // Invalid character 88 | if (carry === 255) { return } 89 | var i = 0 90 | for (var it3 = size - 1; (carry !== 0 || i < length) && (it3 !== -1); it3--, i++) { 91 | carry += (BASE * b256[it3]) >>> 0 92 | b256[it3] = (carry % 256) >>> 0 93 | carry = (carry / 256) >>> 0 94 | } 95 | if (carry !== 0) { throw new Error('Non-zero carry') } 96 | length = i 97 | psz++ 98 | } 99 | // Skip leading zeroes in b256. 100 | var it4 = size - length 101 | while (it4 !== size && b256[it4] === 0) { 102 | it4++ 103 | } 104 | var vch = new Uint8Array(zeroes + (size - it4)) 105 | var j = zeroes 106 | while (it4 !== size) { 107 | vch[j++] = b256[it4++] 108 | } 109 | return vch 110 | } 111 | function decode (string) { 112 | var buffer = decodeUnsafe(string) 113 | if (buffer) { return buffer } 114 | throw new Error('Non-base' + BASE + ' character') 115 | } 116 | return { 117 | encode: encode, 118 | decodeUnsafe: decodeUnsafe, 119 | decode: decode 120 | } 121 | } 122 | }).call(this); 123 | -------------------------------------------------------------------------------- /js/comment.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "so": "https://schema.org/", 4 | "pb": "?jsonld=types#", 5 | "cm": "?jsonld=commentmeta#", 6 | "status": { 7 | "@type": "so:Integer" 8 | }, 9 | "id": { 10 | "@type": "so:name" 11 | }, 12 | "pasteid": { 13 | "@type": "so:name" 14 | }, 15 | "parentid": { 16 | "@type": "so:name" 17 | }, 18 | "url": { 19 | "@type": "so:url" 20 | }, 21 | "v": { 22 | "@type": "so:Integer", 23 | "@value": 2 24 | }, 25 | "ct": { 26 | "@type": "pb:CipherText" 27 | }, 28 | "adata": { 29 | "@type": "pb:CipherParameters" 30 | }, 31 | "meta": { 32 | "@type": "cm:MetaData" 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /js/commentmeta.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "so": "https://schema.org/", 4 | "pb": "?jsonld=types#" 5 | }, 6 | "MetaData": { 7 | "created": { 8 | "@type": "CreationTime" 9 | }, 10 | "icon": { 11 | "@type": "so:url" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "privatebin", 3 | "version": "1.6.0", 4 | "description": "PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bit AES in Galois Counter mode (GCM).", 5 | "main": "privatebin.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "dependencies": {}, 10 | "devDependencies": { 11 | "jsdom": "^9.12.0", 12 | "jsdom-global": "^2.1.1", 13 | "jsdom-url": "^2.2.1", 14 | "jsverify": "^0.8.3", 15 | "@peculiar/webcrypto": "^1.1.1" 16 | }, 17 | "scripts": { 18 | "test": "mocha" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/PrivateBin/PrivateBin.git" 23 | }, 24 | "keywords": [ 25 | "private", 26 | "secure", 27 | "end-to-end-encrypted", 28 | "e2e", 29 | "paste", 30 | "pastebin", 31 | "zero", 32 | "zero-knowledge", 33 | "encryption", 34 | "encrypted", 35 | "AES" 36 | ], 37 | "author": "", 38 | "license": "zlib-acknowledgement", 39 | "bugs": { 40 | "url": "https://github.com/PrivateBin/PrivateBin/issues" 41 | }, 42 | "homepage": "https://privatebin.info/" 43 | } 44 | -------------------------------------------------------------------------------- /js/paste.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "so": "https://schema.org/", 4 | "pb": "?jsonld=types#", 5 | "pm": "?jsonld=pastemeta#", 6 | "status": { 7 | "@type": "so:Integer" 8 | }, 9 | "id": { 10 | "@type": "so:name" 11 | }, 12 | "deletetoken": { 13 | "@type": "so:Text" 14 | }, 15 | "url": { 16 | "@type": "so:url" 17 | }, 18 | "v": { 19 | "@type": "so:Integer", 20 | "@value": 2 21 | }, 22 | "ct": { 23 | "@type": "pb:CipherText" 24 | }, 25 | "adata": { 26 | "@type": "pm:AuthenticatedData" 27 | }, 28 | "meta": { 29 | "@type": "pm:MetaData" 30 | }, 31 | "comments": { 32 | "@type": "?jsonld=comment", 33 | "@container": "@list" 34 | }, 35 | "comment_count": { 36 | "@type": "so:Integer" 37 | }, 38 | "comment_offset": { 39 | "@type": "so:Integer" 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /js/pastemeta.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "so": "https://schema.org/", 4 | "pb": "?jsonld=types#" 5 | }, 6 | "AuthenticatedData": { 7 | "@container": "@list", 8 | "@value": [ 9 | { 10 | "@type": "pb:CipherParameters" 11 | }, 12 | { 13 | "@type": "pb:Formatter" 14 | }, 15 | { 16 | "@type": "pb:OpenDiscussion" 17 | }, 18 | { 19 | "@type": "pb:BurnAfterReading" 20 | } 21 | ] 22 | }, 23 | "MetaData": { 24 | "expire": { 25 | "@type": "pb:Expiration" 26 | }, 27 | "time_to_live": { 28 | "@type": "pb:RemainingSeconds" 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /js/types.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "so": "https://schema.org/", 4 | "dp": "http://dbpedia.org/resource/", 5 | "pb": "?jsonld=types#" 6 | }, 7 | "Base64": { 8 | "@type": "so:Text" 9 | }, 10 | "CipherText": { 11 | "@type": "pb:Base64" 12 | }, 13 | "PasteCipherMessage": { 14 | "paste": { 15 | "@type": "so:Text" 16 | }, 17 | "attachment": { 18 | "@type": "so:MediaObject" 19 | }, 20 | "attachment_name": { 21 | "@type": "so:Text" 22 | } 23 | }, 24 | "CommentCipherMessage": { 25 | "comment": { 26 | "@type": "so:Text" 27 | }, 28 | "nickname": { 29 | "@type": "so:Text" 30 | } 31 | }, 32 | "InitializationVector": { 33 | "@type": "pb:Base64" 34 | }, 35 | "Salt": { 36 | "@type": "pb:Base64" 37 | }, 38 | "Iterations": { 39 | "@type": "so:Integer", 40 | "@minimum": 1 41 | }, 42 | "KeySize": { 43 | "@type": "so:Integer", 44 | "@value": 256, 45 | "@minimum": 128, 46 | "@maximum": 256, 47 | "@enum": [128, 196, 256] 48 | }, 49 | "TagSize": { 50 | "@type": "so:Integer", 51 | "@value": 128, 52 | "@minimum": 32, 53 | "@maximum": 128, 54 | "@enum": [32, 64, 96, 104, 112, 120, 128] 55 | }, 56 | "Algorithm": { 57 | "@type": "so:Text", 58 | "@value": "aes" 59 | }, 60 | "Mode": { 61 | "@type": "so:Text", 62 | "@value": "gcm", 63 | "@enum": ["ctr", "cbc", "gcm"] 64 | }, 65 | "Compression": { 66 | "@type": "so:Text", 67 | "@value": "zlib", 68 | "@enum": ["zlib", "none"] 69 | }, 70 | "Formatter": { 71 | "@type": "so:Text", 72 | "@value": "plaintext", 73 | "@enum": ["plaintext", "syntaxhighlighting", "markdown"] 74 | }, 75 | "Expiration": { 76 | "@type": "so:Text", 77 | "@value": "1week", 78 | "@enum": ["5min", "10min", "1hour", "1day", "1week", "1month", "1year", "never"] 79 | }, 80 | "OpenDiscussion": { 81 | "@type": "so:Boolean", 82 | "@enum": [false, true] 83 | }, 84 | "BurnAfterReading": { 85 | "@type": "so:Boolean", 86 | "@enum": [false, true] 87 | }, 88 | "CreationTime": { 89 | "@type": "dp:Unix_time" 90 | }, 91 | "RemainingSeconds": { 92 | "@type": "dp:Second", 93 | "@minimum": 1 94 | }, 95 | "CipherParameters": { 96 | "@container": "@list", 97 | "@value": [ 98 | { 99 | "@type": "pb:InitializationVector" 100 | }, 101 | { 102 | "@type": "pb:Salt" 103 | }, 104 | { 105 | "@type": "pb:Iterations" 106 | }, 107 | { 108 | "@type": "pb:KeySize" 109 | }, 110 | { 111 | "@type": "pb:TagSize" 112 | }, 113 | { 114 | "@type": "pb:Algorithm" 115 | }, 116 | { 117 | "@type": "pb:Mode" 118 | }, 119 | { 120 | "@type": "pb:Compression" 121 | } 122 | ] 123 | } 124 | } -------------------------------------------------------------------------------- /js/zlib-1.2.13.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | (function() { 4 | let ret; 5 | 6 | async function initialize() { 7 | if (ret) return ret; 8 | 9 | const COMPRESSION_LEVEL = 7; 10 | const NO_ZLIB_HEADER = -1; 11 | const CHUNK_SIZE = 32 * 1024; 12 | const map = {}; 13 | const memory = new WebAssembly.Memory({ 14 | initial: 1, 15 | maximum: 1024, // 64MB 16 | }); 17 | const env = { 18 | memory, 19 | writeToJs(ptr, size) { 20 | const o = map[ptr]; 21 | o.onData(new Uint8Array(memory.buffer, dstPtr, size)); 22 | }, 23 | _abort: errno => { console.error(`Error: ${errno}`) }, 24 | _grow: () => { }, 25 | }; 26 | 27 | let buff; 28 | if (typeof fetch === 'undefined') { 29 | buff = fs.readFileSync('zlib-1.2.13.wasm'); 30 | } else { 31 | const resp = await fetch('js/zlib-1.2.13.wasm'); 32 | buff = await resp.arrayBuffer(); 33 | } 34 | const module = await WebAssembly.compile(buff); 35 | const ins = await WebAssembly.instantiate(module, { env }); 36 | 37 | const srcPtr = ins.exports._malloc(CHUNK_SIZE); 38 | const dstPtr = ins.exports._malloc(CHUNK_SIZE); 39 | 40 | class RawDef { 41 | constructor() { 42 | this.zstreamPtr = ins.exports._createDeflateContext(COMPRESSION_LEVEL, NO_ZLIB_HEADER); 43 | map[this.zstreamPtr] = this; 44 | this.offset = 0; 45 | this.buff = new Uint8Array(CHUNK_SIZE); 46 | } 47 | 48 | deflate(chunk, flush) { 49 | const src = new Uint8Array(memory.buffer, srcPtr, chunk.length); 50 | src.set(chunk); 51 | ins.exports._deflate(this.zstreamPtr, srcPtr, dstPtr, chunk.length, CHUNK_SIZE, flush); 52 | } 53 | 54 | onData(chunk) { 55 | if (this.buff.length < this.offset + chunk.length) { 56 | const buff = this.buff; 57 | this.buff = new Uint8Array(this.buff.length * 2); 58 | this.buff.set(buff); 59 | } 60 | this.buff.set(chunk, this.offset); 61 | this.offset += chunk.length; 62 | } 63 | 64 | destroy() { 65 | ins.exports._freeDeflateContext(this.zstreamPtr); 66 | delete map[this.zstreamPtr]; 67 | this.buff = null; 68 | } 69 | 70 | getBuffer() { 71 | const res = new Uint8Array(this.offset); 72 | for (let i = 0; i < this.offset; ++i) { 73 | res[i] = this.buff[i]; 74 | } 75 | return res; 76 | } 77 | } 78 | 79 | class RawInf { 80 | constructor() { 81 | this.zstreamPtr = ins.exports._createInflateContext(NO_ZLIB_HEADER); 82 | map[this.zstreamPtr] = this; 83 | this.offset = 0; 84 | this.buff = new Uint8Array(CHUNK_SIZE); 85 | } 86 | 87 | inflate(chunk) { 88 | const src = new Uint8Array(memory.buffer, srcPtr, chunk.length); 89 | src.set(chunk); 90 | ins.exports._inflate(this.zstreamPtr, srcPtr, dstPtr, chunk.length, CHUNK_SIZE); 91 | } 92 | 93 | onData(chunk) { 94 | if (this.buff.length < this.offset + chunk.length) { 95 | const buff = this.buff; 96 | this.buff = new Uint8Array(this.buff.length * 2); 97 | this.buff.set(buff); 98 | } 99 | this.buff.set(chunk, this.offset); 100 | this.offset += chunk.length; 101 | } 102 | 103 | destroy() { 104 | ins.exports._freeInflateContext(this.zstreamPtr); 105 | delete map[this.zstreamPtr]; 106 | this.buff = null; 107 | } 108 | 109 | getBuffer() { 110 | const res = new Uint8Array(this.offset); 111 | for (let i = 0; i < this.offset; ++i) { 112 | res[i] = this.buff[i]; 113 | } 114 | return res; 115 | } 116 | } 117 | 118 | ret = { 119 | inflate(rawDeflateBuffer) { 120 | const rawInf = new RawInf(); 121 | for (let offset = 0; offset < rawDeflateBuffer.length; offset += CHUNK_SIZE) { 122 | const end = Math.min(offset + CHUNK_SIZE, rawDeflateBuffer.length); 123 | const chunk = rawDeflateBuffer.subarray(offset, end); 124 | rawInf.inflate(chunk); 125 | } 126 | const ret = rawInf.getBuffer(); 127 | rawInf.destroy(); 128 | return ret; 129 | }, 130 | deflate(rawInflateBuffer) { 131 | const rawDef = new RawDef(); 132 | for (let offset = 0; offset < rawInflateBuffer.length; offset += CHUNK_SIZE) { 133 | const end = Math.min(offset + CHUNK_SIZE, rawInflateBuffer.length); 134 | const chunk = rawInflateBuffer.subarray(offset, end); 135 | rawDef.deflate(chunk, rawInflateBuffer.length <= offset + CHUNK_SIZE); 136 | } 137 | const ret = rawDef.getBuffer(); 138 | rawDef.destroy(); 139 | return ret; 140 | }, 141 | } 142 | 143 | return ret; 144 | } 145 | this.zlib = initialize(); 146 | }).call(this); 147 | -------------------------------------------------------------------------------- /js/zlib-1.2.13.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elrido/ZeroBin/f862e062cd85e3bc150bac29d0f9ee4a188a633d/js/zlib-1.2.13.wasm -------------------------------------------------------------------------------- /lib/.htaccess: -------------------------------------------------------------------------------- 1 | Require all denied 2 | -------------------------------------------------------------------------------- /lib/Data/AbstractData.php: -------------------------------------------------------------------------------- 1 | _last_cache as $key => $last_submission) { 110 | if ($last_submission <= $time) { 111 | unset($this->_last_cache[$key]); 112 | } 113 | } 114 | } 115 | } 116 | 117 | /** 118 | * Save a value. 119 | * 120 | * @access public 121 | * @param string $value 122 | * @param string $namespace 123 | * @param string $key 124 | * @return bool 125 | */ 126 | abstract public function setValue($value, $namespace, $key = ''); 127 | 128 | /** 129 | * Load a value. 130 | * 131 | * @access public 132 | * @param string $namespace 133 | * @param string $key 134 | * @return string 135 | */ 136 | abstract public function getValue($namespace, $key = ''); 137 | 138 | /** 139 | * Returns up to batch size number of paste ids that have expired 140 | * 141 | * @access protected 142 | * @param int $batchsize 143 | * @return array 144 | */ 145 | abstract protected function _getExpiredPastes($batchsize); 146 | 147 | /** 148 | * Perform a purge of old pastes, at most the given batchsize is deleted. 149 | * 150 | * @access public 151 | * @param int $batchsize 152 | */ 153 | public function purge($batchsize) 154 | { 155 | if ($batchsize < 1) { 156 | return; 157 | } 158 | $pastes = $this->_getExpiredPastes($batchsize); 159 | if (count($pastes)) { 160 | foreach ($pastes as $pasteid) { 161 | $this->delete($pasteid); 162 | } 163 | } 164 | } 165 | 166 | /** 167 | * Returns all paste ids 168 | * 169 | * @access public 170 | * @return array 171 | */ 172 | abstract public function getAllPastes(); 173 | 174 | /** 175 | * Get next free slot for comment from postdate. 176 | * 177 | * @access protected 178 | * @param array $comments 179 | * @param int|string $postdate 180 | * @return int|string 181 | */ 182 | protected function getOpenSlot(array &$comments, $postdate) 183 | { 184 | if (array_key_exists($postdate, $comments)) { 185 | $parts = explode('.', $postdate, 2); 186 | if (!array_key_exists(1, $parts)) { 187 | $parts[1] = 0; 188 | } 189 | ++$parts[1]; 190 | return $this->getOpenSlot($comments, implode('.', $parts)); 191 | } 192 | return $postdate; 193 | } 194 | 195 | /** 196 | * Upgrade pre-version 1 pastes with attachment to version 1 format. 197 | * 198 | * @access protected 199 | * @static 200 | * @param array $paste 201 | * @return array 202 | */ 203 | protected static function upgradePreV1Format(array $paste) 204 | { 205 | if (array_key_exists('attachment', $paste['meta'])) { 206 | $paste['attachment'] = $paste['meta']['attachment']; 207 | unset($paste['meta']['attachment']); 208 | if (array_key_exists('attachmentname', $paste['meta'])) { 209 | $paste['attachmentname'] = $paste['meta']['attachmentname']; 210 | unset($paste['meta']['attachmentname']); 211 | } 212 | } 213 | return $paste; 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /lib/Filter.php: -------------------------------------------------------------------------------- 1 | = 1) { 66 | $size = $size / 1024; 67 | ++$i; 68 | } 69 | return number_format($size, $i ? 2 : 0, '.', ' ') . ' ' . I18n::_($iec[$i]); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /lib/FormatV2.php: -------------------------------------------------------------------------------- 1 | 24) { 79 | return false; 80 | } 81 | // - salt 82 | if (strlen($cipherParams[1]) > 14) { 83 | return false; 84 | } 85 | 86 | // Make sure some fields contain no unsupported values: 87 | // - version 88 | if (!(is_int($message['v']) || is_float($message['v'])) || (float) $message['v'] < 2) { 89 | return false; 90 | } 91 | // - iterations, refuse less then 10000 iterations (minimum NIST recommendation) 92 | if (!is_int($cipherParams[2]) || $cipherParams[2] <= 10000) { 93 | return false; 94 | } 95 | // - key size 96 | if (!in_array($cipherParams[3], array(128, 192, 256), true)) { 97 | return false; 98 | } 99 | // - tag size 100 | if (!in_array($cipherParams[4], array(64, 96, 128), true)) { 101 | return false; 102 | } 103 | // - algorithm, must be AES 104 | if ($cipherParams[5] !== 'aes') { 105 | return false; 106 | } 107 | // - mode 108 | if (!in_array($cipherParams[6], array('ctr', 'cbc', 'gcm'), true)) { 109 | return false; 110 | } 111 | // - compression 112 | if (!in_array($cipherParams[7], array('zlib', 'none'), true)) { 113 | return false; 114 | } 115 | 116 | // Reject data if entropy is too low 117 | if (strlen($ct) > strlen(gzdeflate($ct))) { 118 | return false; 119 | } 120 | 121 | // require only the key 'expire' in the metadata of pastes 122 | if (!$isComment && ( 123 | count($message['meta']) === 0 || 124 | !array_key_exists('expire', $message['meta']) || 125 | count($message['meta']) > 1 126 | )) { 127 | return false; 128 | } 129 | 130 | return true; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /lib/Json.php: -------------------------------------------------------------------------------- 1 | _conf = $conf; 47 | } 48 | 49 | /** 50 | * Get a paste, optionally a specific instance. 51 | * 52 | * @param string $pasteId 53 | * @return Paste 54 | */ 55 | public function getPaste($pasteId = null) 56 | { 57 | $paste = new Paste($this->_conf, $this->getStore()); 58 | if ($pasteId !== null) { 59 | $paste->setId($pasteId); 60 | } 61 | return $paste; 62 | } 63 | 64 | /** 65 | * Checks if a purge is necessary and triggers it if yes. 66 | */ 67 | public function purge() 68 | { 69 | PurgeLimiter::setConfiguration($this->_conf); 70 | PurgeLimiter::setStore($this->getStore()); 71 | if (PurgeLimiter::canPurge()) { 72 | $this->getStore()->purge($this->_conf->getKey('batchsize', 'purge')); 73 | } 74 | } 75 | 76 | /** 77 | * Gets, and creates if neccessary, a store object 78 | * 79 | * @return Data\AbstractData 80 | */ 81 | public function getStore() 82 | { 83 | if ($this->_store === null) { 84 | $class = 'PrivateBin\\Data\\' . $this->_conf->getKey('class', 'model'); 85 | $this->_store = new $class($this->_conf->getSection('model_options')); 86 | } 87 | return $this->_store; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /lib/Model/AbstractModel.php: -------------------------------------------------------------------------------- 1 | array()); 41 | 42 | /** 43 | * Configuration. 44 | * 45 | * @access protected 46 | * @var Configuration 47 | */ 48 | protected $_conf; 49 | 50 | /** 51 | * Data storage. 52 | * 53 | * @access protected 54 | * @var AbstractData 55 | */ 56 | protected $_store; 57 | 58 | /** 59 | * Instance constructor. 60 | * 61 | * @access public 62 | * @param Configuration $configuration 63 | * @param AbstractData $storage 64 | */ 65 | public function __construct(Configuration $configuration, AbstractData $storage) 66 | { 67 | $this->_conf = $configuration; 68 | $this->_store = $storage; 69 | } 70 | 71 | /** 72 | * Get ID. 73 | * 74 | * @access public 75 | * @return string 76 | */ 77 | public function getId() 78 | { 79 | return $this->_id; 80 | } 81 | 82 | /** 83 | * Set ID. 84 | * 85 | * @access public 86 | * @param string $id 87 | * @throws Exception 88 | */ 89 | public function setId($id) 90 | { 91 | if (!self::isValidId($id)) { 92 | throw new Exception('Invalid paste ID.', 60); 93 | } 94 | $this->_id = $id; 95 | } 96 | 97 | /** 98 | * Set data and recalculate ID. 99 | * 100 | * @access public 101 | * @param array $data 102 | * @throws Exception 103 | */ 104 | public function setData(array $data) 105 | { 106 | $data = $this->_sanitize($data); 107 | $this->_validate($data); 108 | $this->_data = $data; 109 | 110 | // calculate a 64 bit checksum to avoid collisions 111 | $this->setId(hash(version_compare(PHP_VERSION, '5.6', '<') ? 'fnv164' : 'fnv1a64', $data['ct'])); 112 | } 113 | 114 | /** 115 | * Get instance data. 116 | * 117 | * @access public 118 | * @return array 119 | */ 120 | public function get() 121 | { 122 | return $this->_data; 123 | } 124 | 125 | /** 126 | * Store the instance's data. 127 | * 128 | * @access public 129 | * @throws Exception 130 | */ 131 | abstract public function store(); 132 | 133 | /** 134 | * Delete the current instance. 135 | * 136 | * @access public 137 | * @throws Exception 138 | */ 139 | abstract public function delete(); 140 | 141 | /** 142 | * Test if current instance exists in store. 143 | * 144 | * @access public 145 | * @return bool 146 | */ 147 | abstract public function exists(); 148 | 149 | /** 150 | * Validate ID. 151 | * 152 | * @access public 153 | * @static 154 | * @param string $id 155 | * @return bool 156 | */ 157 | public static function isValidId($id) 158 | { 159 | return (bool) preg_match('#\A[a-f\d]{16}\z#', (string) $id); 160 | } 161 | 162 | /** 163 | * Sanitizes data to conform with current configuration. 164 | * 165 | * @access protected 166 | * @param array $data 167 | * @return array 168 | */ 169 | abstract protected function _sanitize(array $data); 170 | 171 | /** 172 | * Validate data. 173 | * 174 | * @access protected 175 | * @param array $data 176 | * @throws Exception 177 | */ 178 | protected function _validate(array $data) 179 | { 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /lib/Model/Comment.php: -------------------------------------------------------------------------------- 1 | getPaste()->getId(); 46 | if (!$this->getPaste()->exists()) { 47 | throw new Exception('Invalid data.', 67); 48 | } 49 | 50 | // Make sure the discussion is opened in this paste and in configuration. 51 | if (!$this->getPaste()->isOpendiscussion() || !$this->_conf->getKey('discussion')) { 52 | throw new Exception('Invalid data.', 68); 53 | } 54 | 55 | // Check for improbable collision. 56 | if ($this->exists()) { 57 | throw new Exception('You are unlucky. Try again.', 69); 58 | } 59 | 60 | $this->_data['meta']['created'] = time(); 61 | 62 | // store comment 63 | if ( 64 | $this->_store->createComment( 65 | $pasteid, 66 | $this->getParentId(), 67 | $this->getId(), 68 | $this->_data 69 | ) === false 70 | ) { 71 | throw new Exception('Error saving comment. Sorry.', 70); 72 | } 73 | } 74 | 75 | /** 76 | * Delete the comment. 77 | * 78 | * @access public 79 | * @throws Exception 80 | */ 81 | public function delete() 82 | { 83 | throw new Exception('To delete a comment, delete its parent paste', 64); 84 | } 85 | 86 | /** 87 | * Test if comment exists in store. 88 | * 89 | * @access public 90 | * @return bool 91 | */ 92 | public function exists() 93 | { 94 | return $this->_store->existsComment( 95 | $this->getPaste()->getId(), 96 | $this->getParentId(), 97 | $this->getId() 98 | ); 99 | } 100 | 101 | /** 102 | * Set paste. 103 | * 104 | * @access public 105 | * @param Paste $paste 106 | * @throws Exception 107 | */ 108 | public function setPaste(Paste $paste) 109 | { 110 | $this->_paste = $paste; 111 | $this->_data['pasteid'] = $paste->getId(); 112 | } 113 | 114 | /** 115 | * Get paste. 116 | * 117 | * @access public 118 | * @return Paste 119 | */ 120 | public function getPaste() 121 | { 122 | return $this->_paste; 123 | } 124 | 125 | /** 126 | * Set parent ID. 127 | * 128 | * @access public 129 | * @param string $id 130 | * @throws Exception 131 | */ 132 | public function setParentId($id) 133 | { 134 | if (!self::isValidId($id)) { 135 | throw new Exception('Invalid paste ID.', 65); 136 | } 137 | $this->_data['parentid'] = $id; 138 | } 139 | 140 | /** 141 | * Get parent ID. 142 | * 143 | * @access public 144 | * @return string 145 | */ 146 | public function getParentId() 147 | { 148 | if (!array_key_exists('parentid', $this->_data)) { 149 | $this->_data['parentid'] = $this->getPaste()->getId(); 150 | } 151 | return $this->_data['parentid']; 152 | } 153 | 154 | /** 155 | * Sanitizes data to conform with current configuration. 156 | * 157 | * @access protected 158 | * @param array $data 159 | * @return array 160 | */ 161 | protected function _sanitize(array $data) 162 | { 163 | // we generate an icon based on a SHA512 HMAC of the users IP, if configured 164 | $icon = $this->_conf->getKey('icon'); 165 | if ($icon != 'none') { 166 | $pngdata = ''; 167 | $hmac = TrafficLimiter::getHash(); 168 | if ($icon == 'identicon') { 169 | $identicon = new Identicon(); 170 | $pngdata = $identicon->getImageDataUri($hmac, 16); 171 | } elseif ($icon == 'jdenticon') { 172 | $jdenticon = new Jdenticon(array( 173 | 'hash' => $hmac, 174 | 'size' => 16, 175 | 'style' => array( 176 | 'backgroundColor' => '#fff0', // fully transparent, for dark mode 177 | 'padding' => 0, 178 | ), 179 | )); 180 | $pngdata = $jdenticon->getImageDataUri('png'); 181 | } elseif ($icon == 'vizhash') { 182 | $vh = new Vizhash16x16(); 183 | $pngdata = 'data:image/png;base64,' . base64_encode( 184 | $vh->generate($hmac) 185 | ); 186 | } 187 | if ($pngdata != '') { 188 | if (!array_key_exists('meta', $data)) { 189 | $data['meta'] = array(); 190 | } 191 | $data['meta']['icon'] = $pngdata; 192 | } 193 | } 194 | return $data; 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /lib/Persistence/AbstractPersistence.php: -------------------------------------------------------------------------------- 1 | getKey('limit', 'purge')); 55 | } 56 | 57 | /** 58 | * check if the purge can be performed 59 | * 60 | * @access public 61 | * @static 62 | * @return bool 63 | */ 64 | public static function canPurge() 65 | { 66 | // disable limits if set to less then 1 67 | if (self::$_limit < 1) { 68 | return true; 69 | } 70 | 71 | $now = time(); 72 | $pl = (int) self::$_store->getValue('purge_limiter'); 73 | if ($pl + self::$_limit >= $now) { 74 | return false; 75 | } 76 | $hasStored = self::$_store->setValue((string) $now, 'purge_limiter'); 77 | if (!$hasStored) { 78 | error_log('failed to store the purge limiter, skipping purge cycle to avoid getting stuck in a purge loop'); 79 | } 80 | return $hasStored; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /lib/Persistence/ServerSalt.php: -------------------------------------------------------------------------------- 1 | getValue('salt'); 64 | if ($salt) { 65 | self::$_salt = $salt; 66 | } else { 67 | self::$_salt = self::generate(); 68 | if (!self::$_store->setValue(self::$_salt, 'salt')) { 69 | error_log('failed to store the server salt, delete tokens, traffic limiter and user icons won\'t work'); 70 | } 71 | } 72 | return self::$_salt; 73 | } 74 | 75 | /** 76 | * set the path 77 | * 78 | * @access public 79 | * @static 80 | * @param AbstractData $store 81 | */ 82 | public static function setStore(AbstractData $store) 83 | { 84 | self::$_salt = ''; 85 | parent::setStore($store); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /lib/View.php: -------------------------------------------------------------------------------- 1 | _variables[$name] = $value; 42 | } 43 | 44 | /** 45 | * render a template 46 | * 47 | * @access public 48 | * @param string $template 49 | * @throws Exception 50 | */ 51 | public function draw($template) 52 | { 53 | $file = substr($template, 0, 9) === 'bootstrap' ? 'bootstrap' : $template; 54 | $path = PATH . 'tpl' . DIRECTORY_SEPARATOR . $file . '.php'; 55 | if (!file_exists($path)) { 56 | throw new Exception('Template ' . $template . ' not found!', 80); 57 | } 58 | extract($this->_variables); 59 | include $path; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/YourlsProxy.php: -------------------------------------------------------------------------------- 1 | getKey('basepath') . '?') === false) { 52 | $this->_error = 'Trying to shorten a URL that isn\'t pointing at our instance.'; 53 | return; 54 | } 55 | 56 | $yourls_api_url = $conf->getKey('apiurl', 'yourls'); 57 | if (empty($yourls_api_url)) { 58 | $this->_error = 'Error calling YOURLS. Probably a configuration issue, like wrong or missing "apiurl" or "signature".'; 59 | return; 60 | } 61 | 62 | $data = file_get_contents( 63 | $yourls_api_url, false, stream_context_create( 64 | array( 65 | 'http' => array( 66 | 'method' => 'POST', 67 | 'header' => "Content-Type: application/x-www-form-urlencoded\r\n", 68 | 'content' => http_build_query( 69 | array( 70 | 'signature' => $conf->getKey('signature', 'yourls'), 71 | 'format' => 'json', 72 | 'action' => 'shorturl', 73 | 'url' => $link, 74 | ) 75 | ), 76 | ), 77 | ) 78 | ) 79 | ); 80 | try { 81 | $data = Json::decode($data); 82 | } catch (Exception $e) { 83 | $this->_error = 'Error calling YOURLS. Probably a configuration issue, like wrong or missing "apiurl" or "signature".'; 84 | error_log('Error calling YOURLS: ' . $e->getMessage()); 85 | return; 86 | } 87 | 88 | if ( 89 | !is_null($data) && 90 | array_key_exists('statusCode', $data) && 91 | $data['statusCode'] == 200 && 92 | array_key_exists('shorturl', $data) 93 | ) { 94 | $this->_url = $data['shorturl']; 95 | } else { 96 | $this->_error = 'Error parsing YOURLS response.'; 97 | } 98 | } 99 | 100 | /** 101 | * Returns the (untranslated) error message 102 | * 103 | * @access public 104 | * @return string 105 | */ 106 | public function getError() 107 | { 108 | return $this->_error; 109 | } 110 | 111 | /** 112 | * Returns the shortened URL 113 | * 114 | * @access public 115 | * @return string 116 | */ 117 | public function getUrl() 118 | { 119 | return $this->_url; 120 | } 121 | 122 | /** 123 | * Returns true if any error has occurred 124 | * 125 | * @access public 126 | * @return bool 127 | */ 128 | public function isError() 129 | { 130 | return !empty($this->_error); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PrivateBin", 3 | "icons": [ 4 | { 5 | "src": "img/android-chrome-192x192.png", 6 | "sizes": "192x192", 7 | "type": "image\/png" 8 | }, 9 | { 10 | "src": "img/android-chrome-512x512.png", 11 | "sizes": "512x512", 12 | "type": "image\/png" 13 | } 14 | ], 15 | "theme_color": "#ffe57e", 16 | "display": "standalone" 17 | } 18 | -------------------------------------------------------------------------------- /robots.txt: -------------------------------------------------------------------------------- 1 | # "A robots.txt a day keeps the robots away." 2 | # (for performance and privacy reasons) 3 | # 4 | # Note: To be effective this robots.txt must be put into the root of your server 5 | # directory. 6 | 7 | User-agent: * 8 | Disallow: / 9 | 10 | # If you don't want this instance to be listed on https://privatebin.info/directory/ 11 | # uncomment the following lines: 12 | #User-agent: PrivateBinDirectoryBot 13 | #Disallow: / -------------------------------------------------------------------------------- /tpl/.htaccess: -------------------------------------------------------------------------------- 1 | Require all denied 2 | -------------------------------------------------------------------------------- /tpl/yourlsproxy.php: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | <?php echo I18n::_($NAME); ?> 11 | 12 | 13 | 16 |

%s (Hit [Ctrl]+[c] to copy)', $SHORTURL, $SHORTURL); ?>

17 | 20 |
21 |

22 |
23 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /vendor/.htaccess: -------------------------------------------------------------------------------- 1 | Require all denied 2 | -------------------------------------------------------------------------------- /vendor/autoload.php: -------------------------------------------------------------------------------- 1 | array($baseDir . '/lib'), 10 | 'Jdenticon\\' => array($vendorDir . '/jdenticon/jdenticon/src'), 11 | 'Identicon\\' => array($vendorDir . '/yzalis/identicon/src/Identicon'), 12 | 'IPLib\\' => array($vendorDir . '/mlocati/ip-lib/src'), 13 | ); 14 | -------------------------------------------------------------------------------- /vendor/composer/autoload_real.php: -------------------------------------------------------------------------------- 1 | register(true); 35 | 36 | return $loader; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /vendor/composer/installed.php: -------------------------------------------------------------------------------- 1 | array( 3 | 'name' => 'privatebin/privatebin', 4 | 'pretty_version' => 'dev-master', 5 | 'version' => 'dev-master', 6 | 'reference' => 'c1b3bffe8c5214f69f663b6fb59736a6f5fafa86', 7 | 'type' => 'project', 8 | 'install_path' => __DIR__ . '/../../', 9 | 'aliases' => array(), 10 | 'dev' => false, 11 | ), 12 | 'versions' => array( 13 | 'jdenticon/jdenticon' => array( 14 | 'pretty_version' => '1.0.2', 15 | 'version' => '1.0.2.0', 16 | 'reference' => 'cabb7a44c413c318392a341c5d3ca30fcdd57a6f', 17 | 'type' => 'library', 18 | 'install_path' => __DIR__ . '/../jdenticon/jdenticon', 19 | 'aliases' => array(), 20 | 'dev_requirement' => false, 21 | ), 22 | 'mlocati/ip-lib' => array( 23 | 'pretty_version' => '1.18.0', 24 | 'version' => '1.18.0.0', 25 | 'reference' => 'c77bd0b1f3e3956c7e9661e75cb1f54ed67d95d2', 26 | 'type' => 'library', 27 | 'install_path' => __DIR__ . '/../mlocati/ip-lib', 28 | 'aliases' => array(), 29 | 'dev_requirement' => false, 30 | ), 31 | 'privatebin/privatebin' => array( 32 | 'pretty_version' => 'dev-master', 33 | 'version' => 'dev-master', 34 | 'reference' => 'c1b3bffe8c5214f69f663b6fb59736a6f5fafa86', 35 | 'type' => 'project', 36 | 'install_path' => __DIR__ . '/../../', 37 | 'aliases' => array(), 38 | 'dev_requirement' => false, 39 | ), 40 | 'yzalis/identicon' => array( 41 | 'pretty_version' => '2.0.0', 42 | 'version' => '2.0.0.0', 43 | 'reference' => 'ff5ed090129cab9bfa2a322857d4a01d107aa0ae', 44 | 'type' => 'library', 45 | 'install_path' => __DIR__ . '/../yzalis/identicon', 46 | 'aliases' => array(), 47 | 'dev_requirement' => false, 48 | ), 49 | ), 50 | ); 51 | -------------------------------------------------------------------------------- /vendor/composer/platform_check.php: -------------------------------------------------------------------------------- 1 | = 70300)) { 8 | $issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.0". You are running ' . PHP_VERSION . '.'; 9 | } 10 | 11 | if ($issues) { 12 | if (!headers_sent()) { 13 | header('HTTP/1.1 500 Internal Server Error'); 14 | } 15 | if (!ini_get('display_errors')) { 16 | if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { 17 | fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL); 18 | } elseif (!headers_sent()) { 19 | echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; 20 | } 21 | } 22 | trigger_error( 23 | 'Composer detected issues in your platform: ' . implode(' ', $issues), 24 | E_USER_ERROR 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Canvas/Canvas.php: -------------------------------------------------------------------------------- 1 | width = $width; 35 | $this->height = $height; 36 | $this->edges = new EdgeTable($width, $height); 37 | } 38 | 39 | /** 40 | * The width of the canvas in pixels. 41 | * 42 | * @var integer 43 | */ 44 | public $width = 0; 45 | 46 | /** 47 | * The height of the canvas in pixels. 48 | * 49 | * @var integer 50 | */ 51 | public $height = 0; 52 | 53 | /** 54 | * Specifies the background color. Allowed values are: 55 | * - 32 bit integers on the format 0xRRGGBBAA 56 | * - strings on the format #RGB 57 | * - strings on the format #RRGGBB 58 | * - strings on the format #RRGGBBAA 59 | * 60 | * @var integer|string 61 | */ 62 | public $backColor = 0x00000000; 63 | 64 | /** 65 | * Gets a context used to draw polygons on this canvas. 66 | * 67 | * @returns \Jdenticon\Canvas\CanvasContext 68 | */ 69 | public function getContext() 70 | { 71 | return new CanvasContext($this, $this->edges); 72 | } 73 | 74 | /** 75 | * Renders the canvas as a PNG data stream. 76 | * 77 | * @param array $keywords Keywords to be written to the PNG stream. 78 | * See https://www.w3.org/TR/PNG/#11keywords. 79 | * @returns string 80 | */ 81 | public function toPng($keywords = array()) 82 | { 83 | $colorRanges = array(); 84 | 85 | Rasterizer::rasterize( 86 | $colorRanges, $this->edges, 87 | $this->width, $this->height); 88 | 89 | $backColor = ColorUtils::parse($this->backColor); 90 | if (ColorUtils::alpha($backColor) > 0) { 91 | $isColor = false; 92 | 93 | foreach ($colorRanges as & $value) { 94 | if ($isColor) { 95 | $value = ColorUtils::over($value, $backColor); 96 | $isColor = false; 97 | } else { 98 | $isColor = true; 99 | } 100 | } 101 | 102 | unset($value); 103 | } 104 | 105 | $palette = new PngPalette($colorRanges); 106 | $png = new PngEncoder(); 107 | 108 | $png->writeImageHeader($this->width, $this->height, $palette->isValid ? 109 | PngEncoder::INDEXED_COLOR : PngEncoder::TRUE_COLOR_WITH_ALPHA); 110 | 111 | $png->writeImageGamma(); 112 | 113 | foreach ($keywords as $key => $value) { 114 | $png->writeTextualData($key, $value); 115 | } 116 | 117 | if ($palette && $palette->isValid) { 118 | $png->writePalette($palette); 119 | $png->writeTransparency($palette); 120 | $png->writeIndexed($colorRanges, $palette, 121 | $this->width, $this->height); 122 | } else { 123 | $png->writeTrueColorWithAlpha($colorRanges, 124 | $this->width, $this->height); 125 | } 126 | 127 | $png->writeImageEnd(); 128 | return $png->getBuffer(); 129 | } 130 | } -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Canvas/Matrix.php: -------------------------------------------------------------------------------- 1 | a = $a; 31 | $this->b = $b; 32 | $this->c = $c; 33 | $this->d = $d; 34 | $this->e = $e; 35 | $this->f = $f; 36 | } 37 | 38 | /** 39 | * Gets a value determining if this matrix has skewing values. 40 | * 41 | * @return boolean 42 | */ 43 | public function hasSkewing() 44 | { 45 | return $this->b || $this->c; 46 | } 47 | 48 | /** 49 | * Gets a value determining if this matrix has translation values. 50 | * 51 | * @return boolean 52 | */ 53 | public function hasTranslation() 54 | { 55 | return $this->e || $this->f; 56 | } 57 | 58 | /** 59 | * Gets a value determining if this matrix has scaling values. 60 | * 61 | * @return boolean 62 | */ 63 | public function hasScaling() 64 | { 65 | return $this->a != 1 || $this->d != 1; 66 | } 67 | 68 | /** 69 | * Returns a new matrix based on the current matrix multiplied with the 70 | * specified matrix values. 71 | * 72 | * @return \Jdenticon\Canvas\Matrix 73 | */ 74 | public function multiply($a, $b, $c, $d, $e, $f) 75 | { 76 | return new Matrix( 77 | $this->a * $a + $this->c * $b, 78 | $this->b * $a + $this->d * $b, 79 | $this->a * $c + $this->c * $d, 80 | $this->b * $c + $this->d * $d, 81 | $this->a * $e + $this->c * $f + $this->e, 82 | $this->b * $e + $this->d * $f + $this->f 83 | ); 84 | } 85 | 86 | /** 87 | * Multiplies the specified point with the current matrix and returns the 88 | * resulting point. 89 | * 90 | * @param float $x X coordinate. 91 | * @param float $y Y coordinate. 92 | * @return \Jdenticon\Canvas\Point 93 | */ 94 | public function multiplyPoint($x, $y) 95 | { 96 | return new Point( 97 | $this->a * $x + $this->c * $y + $this->e, 98 | $this->b * $x + $this->d * $y + $this->f 99 | ); 100 | } 101 | 102 | /** 103 | * Returns a new matrix based on the current matrix with a rotation 104 | * transformation applied. 105 | * 106 | * @param float $angle Rotation angle in radians. 107 | * @return \Jdenticon\Canvas\Matrix 108 | */ 109 | public function rotate($angle) 110 | { 111 | $sin = sin($angle); 112 | $cos = cos($angle); 113 | return $this->multiply($cos, $sin, -$sin, $cos, 0, 0); 114 | } 115 | 116 | /** 117 | * Returns a new matrix based on the current matrix with a translation 118 | * transformation applied. 119 | * 120 | * @param float $x Horizontal move distance. 121 | * @param float $y Vertical move distance. 122 | * @return \Jdenticon\Canvas\Matrix 123 | */ 124 | public function translate($x, $y) 125 | { 126 | return $this->multiply(1, 0, 0, 1, $x, $y); 127 | } 128 | 129 | /** 130 | * Returns a new matrix based on the current matrix with a scaling 131 | * transformation applied. 132 | * 133 | * @param float $x Horizontal scale. 134 | * @param float $y Vertical scale. 135 | * @return \Jdenticon\Canvas\Matrix 136 | */ 137 | public function scale($x, $y) 138 | { 139 | return $this->multiply($x, 0, 0, $y, 0, 0); 140 | } 141 | } -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Canvas/Png/PngBuffer.php: -------------------------------------------------------------------------------- 1 | buffer .= $str; 27 | } 28 | 29 | /** 30 | * Writes a 32 bit unsigned int to the buffer in Big Endian format. 31 | * 32 | * @param integer $value Value to write. 33 | */ 34 | public function writeUInt32BE($value) 35 | { 36 | $this->buffer .= pack('N', $value); 37 | } 38 | 39 | /** 40 | * Writes an 8 bit unsigned int to the buffer. 41 | * 42 | * @param integer $value Value to write. 43 | */ 44 | public function writeUInt8($value) 45 | { 46 | $this->buffer .= pack('C', $value); 47 | } 48 | 49 | /** 50 | * Starts a new PNG chunk. 51 | * 52 | * @param string $type Name of the chunk. Must contain exactly 4 53 | * ASCII characters. 54 | */ 55 | public function startChunk($type) 56 | { 57 | $this->chunkPreviousBuffer = $this->buffer; 58 | $this->buffer = $type; 59 | } 60 | 61 | /** 62 | * Closes the current PNG chunk. 63 | */ 64 | public function endChunk() 65 | { 66 | // Compute Crc32 for type + data 67 | $data = $this->buffer; 68 | $crc = crc32($data); 69 | 70 | $this->buffer = 71 | $this->chunkPreviousBuffer . 72 | 73 | // Length 74 | pack('N', strlen($data) - 4) . 75 | 76 | // Content 77 | $data . 78 | 79 | // Crc32 80 | pack('N', $crc); 81 | } 82 | 83 | /** 84 | * Gets a string containing the PNG encoded data. 85 | * 86 | * @return string 87 | */ 88 | public function getBuffer() 89 | { 90 | return $this->buffer; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Canvas/Png/PngPalette.php: -------------------------------------------------------------------------------- 1 | 0 && !isset($lookup[$value])) { 42 | if (!$hasAlphaChannel && ($value & 0xff) < 255) { 43 | $hasAlphaChannel = true; 44 | } 45 | 46 | $lookup[$value] = $colorsCount++; 47 | $colors[] = $value; 48 | 49 | if ($colorsCount > 256) { 50 | break; 51 | } 52 | } 53 | 54 | $count = -1; 55 | } 56 | } 57 | 58 | $this->hasAlphaChannel = $hasAlphaChannel; 59 | $this->colors = & $colors; 60 | $this->lookup = & $lookup; 61 | $this->isValid = $colorsCount <= 256; 62 | } 63 | 64 | /** 65 | * Specifies if the palette is valid to be used for encoding a PNG image. 66 | * 67 | * @var boolean 68 | */ 69 | public $isValid; 70 | 71 | /** 72 | * Specifies if the palette has any partial or fully transparent 73 | * colors. 74 | * 75 | * @var boolean 76 | */ 77 | public $hasAlphaChannel; 78 | 79 | /** 80 | * Array of colors in the palette. 81 | * 82 | * @var array 83 | */ 84 | public $colors; 85 | 86 | /** 87 | * Lookup table from 32-bit color value to color index. 88 | * 89 | * @var array 90 | */ 91 | public $lookup; 92 | } 93 | -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Canvas/Point.php: -------------------------------------------------------------------------------- 1 | x = $x; 39 | $this->y = $y; 40 | } 41 | } -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Canvas/Rasterization/Edge.php: -------------------------------------------------------------------------------- 1 | polygonId = $polygonId; 28 | $this->x0 = $x0; 29 | $this->x1 = $x1; 30 | $this->y0 = $y0; 31 | $this->y1 = $y1; 32 | $this->color = $color; 33 | $this->windingRule = $windingRule; 34 | } 35 | 36 | public function intersection($y) 37 | { 38 | $dx = 39 | ($this->x1 - $this->x0) * ($this->y0 - $y) / 40 | ($this->y0 - $this->y1); 41 | return $this->x0 + $dx; 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeIntersection.php: -------------------------------------------------------------------------------- 1 | fromX = $fromX; 23 | $this->width = $width; 24 | $this->edge = $edge; 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeSuperSampleIntersection.php: -------------------------------------------------------------------------------- 1 | x = $x; 22 | $this->edge = $edge; 23 | } 24 | } -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Canvas/Rasterization/EdgeTable.php: -------------------------------------------------------------------------------- 1 | width = $width; 30 | $this->height = $height; 31 | $this->clear(); 32 | } 33 | 34 | /** 35 | * Sorts the edges of each scanline in ascending x coordinates. 36 | */ 37 | public function clear() 38 | { 39 | $this->scanlines = array(); 40 | $this->nextPolygonId = 1; 41 | } 42 | 43 | /** 44 | * Gets an id for the next polygon. 45 | * 46 | * @return int 47 | */ 48 | public function getNextPolygonId() 49 | { 50 | return $this->nextPolygonId++; 51 | } 52 | 53 | /** 54 | * Gets the scaline for the specified Y coordinate, or NULL if there are 55 | * no edges for the specified Y coordinate. 56 | * 57 | * @return array|null. 58 | */ 59 | public function getScanline($y) 60 | { 61 | return isset($this->scanlines[$y]) ? $this->scanlines[$y] : null; 62 | } 63 | 64 | /** 65 | * Adds an edge to the table. 66 | * 67 | * @param \Jdenticon\Canvas\Rasterization\Edge $edge 68 | */ 69 | public function add(\Jdenticon\Canvas\Rasterization\Edge $edge) 70 | { 71 | $minY = 0; 72 | $maxY = 0; 73 | 74 | if ($edge->y0 == $edge->y1) { 75 | // Skip horizontal lines 76 | return; 77 | } elseif ($edge->y0 < $edge->y1) { 78 | $minY = (int)($edge->y0); 79 | $maxY = (int)($edge->y1 + 0.996 /* 1/255 */); 80 | } else { 81 | $minY = (int)($edge->y1); 82 | $maxY = (int)($edge->y0 + 0.996 /* 1/255 */); 83 | } 84 | 85 | if ($maxY < 0 || $minY >= $this->height) { 86 | return; 87 | } 88 | 89 | if ($minY < 0) { 90 | $minY = 0; 91 | } 92 | if ($maxY > $this->height) { 93 | $maxY = $this->height; 94 | } 95 | 96 | if ($minY < $maxY) { 97 | $y = $minY; 98 | $x1 = $edge->intersection($y); 99 | 100 | while ($y < $maxY) { 101 | $x2 = $edge->intersection($y + 1); 102 | 103 | $fromX; 104 | $width; 105 | if ($x1 < $x2) { 106 | $fromX = (int)($x1); 107 | $width = (int)($x2 + 0.9999) - $fromX; 108 | } else { 109 | $fromX = (int)($x2); 110 | $width = (int)($x1 + 0.9999) - $fromX; 111 | } 112 | 113 | if ($fromX < 0) { 114 | $width += $fromX; 115 | $fromX = 0; 116 | 117 | if ($width < 0) { 118 | $width = 0; 119 | } 120 | } 121 | 122 | if ($fromX < $this->width) { 123 | if (!isset($this->scanlines[$y])) { 124 | $this->scanlines[$y] = array(); 125 | } 126 | 127 | $this->scanlines[$y][] = new EdgeIntersection( 128 | $fromX, $width, $edge); 129 | } 130 | 131 | $x1 = $x2; 132 | $y++; 133 | } 134 | } 135 | } 136 | 137 | private static function edge_cmp($x, $y) 138 | { 139 | if ($x->fromX < $y->fromX) { 140 | return -1; 141 | } 142 | if ($x->fromX > $y->fromX) { 143 | return 1; 144 | } 145 | return 0; 146 | } 147 | 148 | /** 149 | * Sorts the edges of each scanline in ascending x coordinates. 150 | */ 151 | public function sort() 152 | { 153 | foreach ($this->scanlines as $i => &$scanline) { 154 | usort($scanline, array( 155 | 'Jdenticon\\Canvas\\Rasterization\\EdgeTable', 'edge_cmp')); 156 | } 157 | } 158 | } -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Canvas/Rasterization/Layer.php: -------------------------------------------------------------------------------- 1 | polygonId = $polygonId; 26 | $this->color = $color; 27 | $this->winding = $winding; 28 | $this->windingRule = $windingRule; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Canvas/Rasterization/LayerManager.php: -------------------------------------------------------------------------------- 1 | color = ColorUtils::TRANSPARENT; 35 | } 36 | 37 | /** 38 | * Copies all layers in this manager to another LayerManager. 39 | * 40 | * @param \Jdenticon\Canvas\Rasterization\LayerManager $other The 41 | * LayerManager to copy all layers to. 42 | */ 43 | public function copyTo(LayerManager $other) 44 | { 45 | $other->color = $this->color; 46 | 47 | $layer = $this->topLayer; 48 | $previousCopy = null; 49 | 50 | while ($layer !== null) { 51 | $copy = new Layer( 52 | $layer->polygonId, 53 | $layer->color, 54 | $layer->winding, 55 | $layer->windingRule 56 | ); 57 | 58 | if ($previousCopy === null) { 59 | $other->topLayer = $copy; 60 | } 61 | else { 62 | $previousCopy->nextLayer = $copy; 63 | } 64 | 65 | $previousCopy = $copy; 66 | $layer = $layer->nextLayer; 67 | } 68 | } 69 | 70 | /** 71 | * Adds a layer for the specified edge. The z-order is defined by its id. 72 | * 73 | * @param \Jdenticon\Canvas\Rasterization\Edge edge 74 | */ 75 | public function add(Edge $edge) 76 | { 77 | $dwinding = $edge->y0 < $edge->y1 ? 1 : -1; 78 | 79 | $layer = $this->topLayer; 80 | $previousLayer = null; 81 | 82 | while ($layer !== null) { 83 | if ($layer->polygonId === $edge->polygonId) { 84 | $layer->winding += $dwinding; 85 | 86 | $inPath = $layer->windingRule == 'evenodd' ? 87 | ($layer->winding % 2 === 1) : ($layer->winding !== 0); 88 | 89 | if (!$inPath) { 90 | // Remove layer 91 | if ($previousLayer === null) { 92 | $this->topLayer = $layer->nextLayer; 93 | } 94 | else { 95 | $previousLayer->nextLayer = $layer->nextLayer; 96 | } 97 | } 98 | break; 99 | } elseif ($layer->polygonId < $edge->polygonId) { 100 | // Insert here 101 | $newLayer = new Layer( 102 | $edge->polygonId, 103 | $edge->color, 104 | $dwinding, 105 | $edge->windingRule 106 | ); 107 | $newLayer->nextLayer = $layer; 108 | 109 | if ($previousLayer === null) { 110 | $this->topLayer = $newLayer; 111 | } else { 112 | $previousLayer->nextLayer = $newLayer; 113 | } 114 | break; 115 | } 116 | 117 | $previousLayer = $layer; 118 | $layer = $layer->nextLayer; 119 | } 120 | 121 | if ($layer === null) { 122 | $newLayer = new Layer( 123 | $edge->polygonId, 124 | $edge->color, 125 | $dwinding, 126 | $edge->windingRule 127 | ); 128 | 129 | if ($previousLayer === null) { 130 | $this->topLayer = $newLayer; 131 | } else { 132 | $previousLayer->nextLayer = $newLayer; 133 | } 134 | } 135 | 136 | // Update current color 137 | $color = ColorUtils::TRANSPARENT; 138 | $layer = $this->topLayer; 139 | 140 | while ($layer !== null && ($color & 0xff) < 255) { 141 | if ($layer->color === ColorUtils::FORCE_TRANSPARENT) { 142 | break; 143 | } 144 | 145 | $color = ColorUtils::over($layer->color, $color); 146 | } 147 | 148 | $this->color = $color; 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Canvas/Rasterization/SuperSampleRange.php: -------------------------------------------------------------------------------- 1 | fromX = $fromX; 24 | $this->toXExcl = $toXExcl; 25 | $this->edges = array(); 26 | } 27 | } -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Rendering/ColorTheme.php: -------------------------------------------------------------------------------- 1 | getGrayscaleLightness(); 37 | $colorLightness = $style->getColorLightness(); 38 | $hues = $style->getHues(); 39 | 40 | if ($hues !== null) { 41 | // $hue is in the range [0, 1] 42 | // Multiply with 0.999 to change the range to [0, 1) 43 | $hueIndex = (int)($hue * 0.999 * count($hues)); 44 | $hue = (float)$hues[$hueIndex] / 360; 45 | } 46 | 47 | $this->darkGray = Color::fromHslCompensated( 48 | $hue, $style->getGrayscaleSaturation(), $grayscaleLightness[0]); 49 | $this->midColor = Color::fromHslCompensated( 50 | $hue, $style->getColorSaturation(), ($colorLightness[0] + $colorLightness[1]) / 2); 51 | $this->lightGray = Color::fromHslCompensated( 52 | $hue, $style->getGrayscaleSaturation(), $grayscaleLightness[1]); 53 | $this->lightColor = Color::fromHslCompensated( 54 | $hue, $style->getColorSaturation(), $colorLightness[1]); 55 | $this->darkColor = Color::fromHslCompensated( 56 | $hue, $style->getColorSaturation(), $colorLightness[0]); 57 | } 58 | 59 | /** 60 | * Gets a color from this color theme by index. 61 | * 62 | * @param int $index Color index in the range [0, getCount()). 63 | * @return Jdenticon\Color 64 | */ 65 | public function getByIndex($index) 66 | { 67 | if ($index === 0) return $this->darkGray; 68 | if ($index === 1) return $this->midColor; 69 | if ($index === 2) return $this->lightGray; 70 | if ($index === 3) return $this->lightColor; 71 | if ($index === 4) return $this->darkColor; 72 | return null; 73 | } 74 | 75 | /** 76 | * Gets the number of available colors in this theme. 77 | * 78 | * @return int 79 | */ 80 | public function getCount() 81 | { 82 | return 5; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Rendering/InternalPngRenderer.php: -------------------------------------------------------------------------------- 1 | canvas = new Canvas($width, $height); 34 | $this->ctx = $this->canvas->getContext(); 35 | } 36 | 37 | /** 38 | * Gets the MIME type of the renderer output. 39 | * 40 | * @return string 41 | */ 42 | public function getMimeType() 43 | { 44 | return 'image/png'; 45 | } 46 | 47 | /** 48 | * Adds a circle without translating its coordinates. 49 | * 50 | * @param float $x The x-coordinate of the bounding rectangle 51 | * upper-left corner. 52 | * @param float $y The y-coordinate of the bounding rectangle 53 | * upper-left corner. 54 | * @param float $size The size of the bounding rectangle. 55 | * @param bool $counterClockwise If true the circle will be drawn 56 | * counter clockwise. 57 | */ 58 | protected function addCircleNoTransform($x, $y, $size, $counterClockwise) 59 | { 60 | $radius = $size / 2; 61 | $this->ctx->moveTo($x + $size, $y + $radius); 62 | $this->ctx->arc( 63 | $x + $radius, $y + $radius, 64 | $radius, 0, M_PI * 2, 65 | $counterClockwise); 66 | $this->ctx->closePath(); 67 | } 68 | 69 | /** 70 | * Adds a polygon without translating its coordinates. 71 | * 72 | * @param array $points An array of the points that the polygon consists of. 73 | */ 74 | protected function addPolygonNoTransform($points) 75 | { 76 | $pointCount = count($points); 77 | $this->ctx->moveTo($points[0]->x, $points[0]->y); 78 | for ($i = 1; $i < $pointCount; $i++) { 79 | $this->ctx->lineTo($points[$i]->x, $points[$i]->y); 80 | } 81 | $this->ctx->closePath(); 82 | } 83 | 84 | /** 85 | * Sets the background color of the icon. 86 | * 87 | * @param \Jdenticon\Color $color The background color. 88 | */ 89 | public function setBackgroundColor(\Jdenticon\Color $color) 90 | { 91 | parent::setBackgroundColor($color); 92 | $this->canvas->backColor = $this->backgroundColor->toRgba(); 93 | } 94 | 95 | /** 96 | * Begins a new shape. The shape should be ended with a call to endShape. 97 | * 98 | * @param \Jdenticon\Color $color The color of the shape. 99 | */ 100 | public function beginShape(\Jdenticon\Color $color) 101 | { 102 | $this->ctx->fillStyle = $color->toRgba(); 103 | $this->ctx->beginPath(); 104 | } 105 | 106 | /** 107 | * Ends the currently drawn shape. 108 | */ 109 | public function endShape() 110 | { 111 | $this->ctx->fill(); 112 | } 113 | 114 | /** 115 | * Gets the output from the renderer. 116 | * 117 | * @return string 118 | */ 119 | public function getData() 120 | { 121 | return $this->canvas->toPng(array('Software' => 'Jdenticon')); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Rendering/Point.php: -------------------------------------------------------------------------------- 1 | x = $x; 28 | $this->y = $y; 29 | } 30 | 31 | /** 32 | * The X coordinate of this point. 33 | * 34 | * @var float 35 | */ 36 | public $x; 37 | 38 | /** 39 | * The Y coordinate of this point. 40 | * 41 | * @var float 42 | */ 43 | public $y; 44 | 45 | /** 46 | * Gets a string representation of the point. 47 | * 48 | * @return string 49 | */ 50 | public function __toString() 51 | { 52 | return $this->x + ", " + $this->y; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Rendering/Rectangle.php: -------------------------------------------------------------------------------- 1 | x = $x; 56 | $this->y = $y; 57 | $this->width = $width; 58 | $this->height = $height; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Rendering/RendererInterface.php: -------------------------------------------------------------------------------- 1 | dataString = ''; 24 | } 25 | 26 | /** 27 | * Adds a circle to the SVG. 28 | * 29 | * @param float $x X coordinate of the left side of the containing rectangle. 30 | * @param float $y Y coordinate of the top side of the containing rectangle. 31 | * @param float $size The diameter of the circle. 32 | * @param bool $counterClockwise If true the circle will be drawn counter 33 | * clockwise. This affects the rendering since the evenodd filling rule 34 | * is used by Jdenticon. 35 | */ 36 | public function addCircle($x, $y, $size, $counterClockwise) 37 | { 38 | $sweepFlag = $counterClockwise ? '0' : '1'; 39 | $radiusAsString = number_format($size / 2, 2, '.', ''); 40 | 41 | $this->dataString .= 42 | 'M'. number_format($x, 2, '.', '') .' '. 43 | number_format($y + $size / 2, 2, '.', ''). 44 | 'a'. $radiusAsString .','. $radiusAsString .' 0 1,'. 45 | $sweepFlag .' '. number_format($size, 2, '.', '') .',0'. 46 | 'a'. $radiusAsString .','. $radiusAsString .' 0 1,'. 47 | $sweepFlag .' '. number_format(-$size, 2, '.', '') .',0'; 48 | } 49 | 50 | /** 51 | * Adds a polygon to the SVG. 52 | * 53 | * @param array(\Jdenticon\Rendering\Point) $points The corners of the 54 | * polygon. 55 | */ 56 | public function addPolygon($points) 57 | { 58 | $pointCount = count($points); 59 | 60 | $this->dataString .= 'M'. 61 | number_format($points[0]->x, 2, '.', '') .' '. 62 | number_format($points[0]->y, 2, '.', ''); 63 | 64 | for ($i = 1; $i < $pointCount; $i++) { 65 | $this->dataString .= 'L'. 66 | number_format($points[$i]->x, 2, '.', '') .' '. 67 | number_format($points[$i]->y, 2, '.', ''); 68 | } 69 | 70 | $this->dataString .= 'Z'; 71 | } 72 | 73 | /** 74 | * Gets the path as a SVG path string. 75 | * 76 | * @return string 77 | */ 78 | public function __toString() 79 | { 80 | return $this->dataString; 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Rendering/SvgRenderer.php: -------------------------------------------------------------------------------- 1 | width = $width; 33 | $this->height = $height; 34 | } 35 | 36 | /** 37 | * Gets the MIME type of the renderer output. 38 | * 39 | * @return string 40 | */ 41 | public function getMimeType() 42 | { 43 | return 'image/svg+xml'; 44 | } 45 | 46 | /** 47 | * Adds a circle without translating its coordinates. 48 | * 49 | * @param float $x The x-coordinate of the bounding rectangle 50 | * upper-left corner. 51 | * @param float $y The y-coordinate of the bounding rectangle 52 | * upper-left corner. 53 | * @param float $size The size of the bounding rectangle. 54 | * @param bool $counterClockwise If true the circle will be drawn 55 | * counter clockwise. 56 | */ 57 | protected function addCircleNoTransform($x, $y, $size, $counterClockwise) 58 | { 59 | $this->path->addCircle($x, $y, $size, $counterClockwise); 60 | } 61 | 62 | /** 63 | * Adds a polygon without translating its coordinates. 64 | * 65 | * @param array $points An array of the points that the polygon consists of. 66 | */ 67 | protected function addPolygonNoTransform($points) 68 | { 69 | $this->path->addPolygon($points); 70 | } 71 | 72 | /** 73 | * Begins a new shape. The shape should be ended with a call to endShape. 74 | * 75 | * @param \Jdenticon\Color $color The color of the shape. 76 | */ 77 | public function beginShape(\Jdenticon\Color $color) 78 | { 79 | $colorString = $color->toHexString(6); 80 | 81 | if (isset($this->pathsByColor[$colorString])) { 82 | $this->path = $this->pathsByColor[$colorString]; 83 | } else { 84 | $this->path = new SvgPath(); 85 | $this->pathsByColor[$colorString] = $this->path; 86 | } 87 | } 88 | 89 | /** 90 | * Ends the currently drawn shape. 91 | */ 92 | public function endShape() 93 | { 94 | } 95 | 96 | /** 97 | * Generates an SVG string of the renderer output. 98 | * 99 | * @param bool $fragment If true an SVG string without the root svg element 100 | * will be rendered. 101 | */ 102 | public function getData($fragment = false) 103 | { 104 | $svg = ''; 105 | $widthAsString = number_format($this->width, 0, '.', ''); 106 | $heightAsString = number_format($this->height, 0, '.', ''); 107 | 108 | if (!$fragment) { 109 | $svg .= ''; 113 | } 114 | 115 | if ($this->backgroundColor->a > 0) { 116 | $opacity = (float)$this->backgroundColor->a / 255; 117 | $svg .= ''; 121 | } 122 | 123 | foreach ($this->pathsByColor as $color => $path) { 124 | $svg .= ""; 125 | } 126 | 127 | if (!$fragment) { 128 | $svg .= ''; 129 | } 130 | 131 | return $svg; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Rendering/Transform.php: -------------------------------------------------------------------------------- 1 | x = $x; 38 | $this->y = $y; 39 | $this->size = $size; 40 | $this->rotation = $rotation; 41 | } 42 | 43 | /** 44 | * Gets a noop transform. 45 | * 46 | * @return \Jdenticon\Rendering\Transform 47 | */ 48 | public static function getEmpty() 49 | { 50 | return new Transform(0, 0, 0, 0); 51 | } 52 | 53 | /** 54 | * Transforms the specified point based on the translation and rotation 55 | * specification for this Transform. 56 | * 57 | * @param float $x x-coordinate 58 | * @param float $y y-coordinate 59 | * @param float $width The width of the transformed rectangle. If greater 60 | * than 0, this will ensure the returned point is of the upper left 61 | * corner of the transformed rectangle. 62 | * @param float $height The height of the transformed rectangle. If greater 63 | * than 0, this will ensure the returned point is of the upper left 64 | * corner of the transformed rectangle. 65 | * @return \Jdenticon\Rendering\Point 66 | */ 67 | public function transformPoint($x, $y, $width = 0, $height = 0) 68 | { 69 | $right = $this->x + $this->size; 70 | $bottom = $this->y + $this->size; 71 | 72 | switch ($this->rotation) { 73 | case 1: return new Point($right - $y - $height, $this->y + $x); 74 | case 2: return new Point($right - $x - $width, $bottom - $y - $height); 75 | case 3: return new Point($this->x + $y, $bottom - $x - $width); 76 | default: return new Point($this->x + $x, $this->y + $y); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Rendering/TriangleDirection.php: -------------------------------------------------------------------------------- 1 | definition = $definition; 58 | $this->color = $color; 59 | $this->positions = $positions; 60 | $this->startRotationIndex = $startRotationIndex; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Shapes/ShapeCategory.php: -------------------------------------------------------------------------------- 1 | colorIndex = $colorIndex; 65 | $this->shapes = $shapes; 66 | $this->shapeIndex = $shapeIndex; 67 | $this->rotationIndex = $rotationIndex; 68 | $this->positions = $positions; 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /vendor/jdenticon/jdenticon/src/Shapes/ShapePosition.php: -------------------------------------------------------------------------------- 1 | x = $x; 42 | $this->y = $y; 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /vendor/mlocati/ip-lib/ip-lib.php: -------------------------------------------------------------------------------- 1 | range = $range; 45 | $this->type = $type; 46 | $this->exceptions = $exceptions; 47 | } 48 | 49 | /** 50 | * Get the range definition. 51 | * 52 | * @return \IPLib\Range\RangeInterface 53 | */ 54 | public function getRange() 55 | { 56 | return $this->range; 57 | } 58 | 59 | /** 60 | * Get the range type. 61 | * 62 | * @return int one of the \IPLib\Range\Type::T_ constants 63 | */ 64 | public function getType() 65 | { 66 | return $this->type; 67 | } 68 | 69 | /** 70 | * Get the list of exceptions for this range type. 71 | * 72 | * @return \IPLib\Address\AssignedRange[] 73 | */ 74 | public function getExceptions() 75 | { 76 | return $this->exceptions; 77 | } 78 | 79 | /** 80 | * Get the assigned type for a specific address. 81 | * 82 | * @param \IPLib\Address\AddressInterface $address 83 | * 84 | * @return int|null return NULL of the address is outside this address; a \IPLib\Range\Type::T_ constant otherwise 85 | */ 86 | public function getAddressType(AddressInterface $address) 87 | { 88 | $result = null; 89 | if ($this->range->contains($address)) { 90 | foreach ($this->exceptions as $exception) { 91 | $result = $exception->getAddressType($address); 92 | if ($result !== null) { 93 | break; 94 | } 95 | } 96 | if ($result === null) { 97 | $result = $this->type; 98 | } 99 | } 100 | 101 | return $result; 102 | } 103 | 104 | /** 105 | * Get the assigned type for a specific address range. 106 | * 107 | * @param \IPLib\Range\RangeInterface $range 108 | * 109 | * @return int|false|null return NULL of the range is fully outside this range; false if it's partly crosses this range (or it contains mixed types); a \IPLib\Range\Type::T_ constant otherwise 110 | */ 111 | public function getRangeType(RangeInterface $range) 112 | { 113 | $myStart = $this->range->getComparableStartString(); 114 | $rangeEnd = $range->getComparableEndString(); 115 | if ($myStart > $rangeEnd) { 116 | $result = null; 117 | } else { 118 | $myEnd = $this->range->getComparableEndString(); 119 | $rangeStart = $range->getComparableStartString(); 120 | if ($myEnd < $rangeStart) { 121 | $result = null; 122 | } elseif ($rangeStart < $myStart || $rangeEnd > $myEnd) { 123 | $result = false; 124 | } else { 125 | $result = null; 126 | foreach ($this->exceptions as $exception) { 127 | $result = $exception->getRangeType($range); 128 | if ($result !== null) { 129 | break; 130 | } 131 | } 132 | if ($result === null) { 133 | $result = $this->getType(); 134 | } 135 | } 136 | } 137 | 138 | return $result; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /vendor/mlocati/ip-lib/src/Address/Type.php: -------------------------------------------------------------------------------- 1 | 5.0.0.1 33 | * @example 5.256 => 5.0.1.0 34 | * @example 5.0.256 => 5.0.1.0 35 | * @example 123456789 => 7.91.205.21 36 | */ 37 | const IPV4_MAYBE_NON_DECIMAL = 4; 38 | 39 | /** 40 | * Use this flag if IPv4 subnet ranges may be in compact form. 41 | * 42 | * @example 127/24 => 127.0.0.0/24 43 | * @example 10/8 => 10.0.0.0/8 44 | * @example 10/24 => 10.0.0.0/24 45 | * @example 10.10.10/24 => 10.10.10.0/24 46 | * 47 | * @var int 48 | */ 49 | const IPV4SUBNET_MAYBE_COMPACT = 8; 50 | 51 | /** 52 | * Use this flag if IPv4 addresses may be in non quad-dotted notation. 53 | * This notation is accepted by the implementation of inet_aton and inet_addr of the libc implementation of GNU, Windows and Mac (but not Musl), but not by inet_pton and ip2long. 54 | * 55 | * @var int 56 | * 57 | * @example 5.1 => 5.0.0.1 58 | * @example 5.256 => 5.0.1.0 59 | * @example 5.0.256 => 5.0.1.0 60 | * @example 123456789 => 7.91.205.21 61 | * 62 | * @see https://man7.org/linux/man-pages/man3/inet_addr.3.html#DESCRIPTION 63 | * @see https://www.freebsd.org/cgi/man.cgi?query=inet_net&sektion=3&apropos=0&manpath=FreeBSD+12.2-RELEASE+and+Ports#end 64 | * @see http://git.musl-libc.org/cgit/musl/tree/src/network/inet_aton.c?h=v1.2.2 65 | */ 66 | const IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED = 16; 67 | 68 | /** 69 | * Use this flag if you want to accept parsing IPv4/IPv6 addresses in Reverse DNS Lookup Address format. 70 | * 71 | * @var int 72 | * 73 | * @since 1.18.0 74 | * 75 | * @example 140.13.12.10.in-addr.arpa => 10.12.13.140 76 | * @example b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.ip6.arpa => 4321:0:1:2:3:4:567:89ab 77 | */ 78 | const ADDRESS_MAYBE_RDNS = 32; 79 | } 80 | -------------------------------------------------------------------------------- /vendor/mlocati/ip-lib/src/Range/AbstractRange.php: -------------------------------------------------------------------------------- 1 | rangeType === null) { 24 | $addressType = $this->getAddressType(); 25 | if ($addressType === AddressType::T_IPv6 && Subnet::get6to4()->containsRange($this)) { 26 | $this->rangeType = Factory::getRangeFromBoundaries($this->fromAddress->toIPv4(), $this->toAddress->toIPv4())->getRangeType(); 27 | } else { 28 | switch ($addressType) { 29 | case AddressType::T_IPv4: 30 | $defaultType = IPv4::getDefaultReservedRangeType(); 31 | $reservedRanges = IPv4::getReservedRanges(); 32 | break; 33 | case AddressType::T_IPv6: 34 | $defaultType = IPv6::getDefaultReservedRangeType(); 35 | $reservedRanges = IPv6::getReservedRanges(); 36 | break; 37 | default: 38 | throw new \Exception('@todo'); // @codeCoverageIgnore 39 | } 40 | $rangeType = null; 41 | foreach ($reservedRanges as $reservedRange) { 42 | $rangeType = $reservedRange->getRangeType($this); 43 | if ($rangeType !== null) { 44 | break; 45 | } 46 | } 47 | $this->rangeType = $rangeType === null ? $defaultType : $rangeType; 48 | } 49 | } 50 | 51 | return $this->rangeType === false ? null : $this->rangeType; 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | * 57 | * @see \IPLib\Range\RangeInterface::getAddressAtOffset() 58 | */ 59 | public function getAddressAtOffset($n) 60 | { 61 | if (!is_int($n)) { 62 | return null; 63 | } 64 | 65 | $address = null; 66 | if ($n >= 0) { 67 | $start = Factory::parseAddressString($this->getComparableStartString()); 68 | $address = $start->getAddressAtOffset($n); 69 | } else { 70 | $end = Factory::parseAddressString($this->getComparableEndString()); 71 | $address = $end->getAddressAtOffset($n + 1); 72 | } 73 | 74 | if ($address === null) { 75 | return null; 76 | } 77 | 78 | return $this->contains($address) ? $address : null; 79 | } 80 | 81 | /** 82 | * {@inheritdoc} 83 | * 84 | * @see \IPLib\Range\RangeInterface::contains() 85 | */ 86 | public function contains(AddressInterface $address) 87 | { 88 | $result = false; 89 | if ($address->getAddressType() === $this->getAddressType()) { 90 | $cmp = $address->getComparableString(); 91 | $from = $this->getComparableStartString(); 92 | if ($cmp >= $from) { 93 | $to = $this->getComparableEndString(); 94 | if ($cmp <= $to) { 95 | $result = true; 96 | } 97 | } 98 | } 99 | 100 | return $result; 101 | } 102 | 103 | /** 104 | * {@inheritdoc} 105 | * 106 | * @see \IPLib\Range\RangeInterface::containsRange() 107 | */ 108 | public function containsRange(RangeInterface $range) 109 | { 110 | $result = false; 111 | if ($range->getAddressType() === $this->getAddressType()) { 112 | $myStart = $this->getComparableStartString(); 113 | $itsStart = $range->getComparableStartString(); 114 | if ($itsStart >= $myStart) { 115 | $myEnd = $this->getComparableEndString(); 116 | $itsEnd = $range->getComparableEndString(); 117 | if ($itsEnd <= $myEnd) { 118 | $result = true; 119 | } 120 | } 121 | } 122 | 123 | return $result; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /vendor/mlocati/ip-lib/src/Range/RangeInterface.php: -------------------------------------------------------------------------------- 1 | toSameLength($a, $b); 37 | 38 | return $a < $b ? -1 : ($a > $b ? 1 : 0); 39 | } 40 | 41 | /** 42 | * Add 1 to a non-negative integer represented in binary form. 43 | * 44 | * @param string $value 45 | * 46 | * @return string 47 | */ 48 | public function increment($value) 49 | { 50 | $lastZeroIndex = strrpos($value, '0'); 51 | if ($lastZeroIndex === false) { 52 | return '1' . str_repeat('0', strlen($value)); 53 | } 54 | 55 | return ltrim(substr($value, 0, $lastZeroIndex), '0') . '1' . str_repeat('0', strlen($value) - $lastZeroIndex - 1); 56 | } 57 | 58 | /** 59 | * Calculate the bitwise AND of two non-negative integers represented in binary form. 60 | * 61 | * @param string $operand1 62 | * @param string $operand2 63 | * 64 | * @return string 65 | */ 66 | public function andX($operand1, $operand2) 67 | { 68 | $operand1 = $this->reduce($operand1); 69 | $operand2 = $this->reduce($operand2); 70 | $numBits = min(strlen($operand1), strlen($operand2)); 71 | $operand1 = substr(str_pad($operand1, $numBits, '0', STR_PAD_LEFT), -$numBits); 72 | $operand2 = substr(str_pad($operand2, $numBits, '0', STR_PAD_LEFT), -$numBits); 73 | $result = ''; 74 | for ($index = 0; $index < $numBits; $index++) { 75 | $result .= $operand1[$index] === '1' && $operand2[$index] === '1' ? '1' : '0'; 76 | } 77 | 78 | return $this->reduce($result); 79 | } 80 | 81 | /** 82 | * Calculate the bitwise OR of two non-negative integers represented in binary form. 83 | * 84 | * @param string $operand1 85 | * @param string $operand2 86 | * 87 | * @return string 88 | */ 89 | public function orX($operand1, $operand2) 90 | { 91 | list($operand1, $operand2, $numBits) = $this->toSameLength($operand1, $operand2); 92 | $result = ''; 93 | for ($index = 0; $index < $numBits; $index++) { 94 | $result .= $operand1[$index] === '1' || $operand2[$index] === '1' ? '1' : '0'; 95 | } 96 | 97 | return $result; 98 | } 99 | 100 | /** 101 | * Zero-padding of two non-negative integers represented in binary form, so that they have the same length. 102 | * 103 | * @param string $num1 104 | * @param string $num2 105 | * 106 | * @return string[],int[] The first array element is $num1 (padded), the first array element is $num2 (padded), the third array element is the number of bits 107 | */ 108 | private function toSameLength($num1, $num2) 109 | { 110 | $num1 = $this->reduce($num1); 111 | $num2 = $this->reduce($num2); 112 | $numBits = max(strlen($num1), strlen($num2)); 113 | 114 | return array( 115 | str_pad($num1, $numBits, '0', STR_PAD_LEFT), 116 | str_pad($num2, $numBits, '0', STR_PAD_LEFT), 117 | $numBits, 118 | ); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /vendor/mlocati/ip-lib/src/Service/RangesFromBoundaryCalculator.php: -------------------------------------------------------------------------------- 1 | math = new BinaryMath(); 54 | $this->setNumBits($numBits); 55 | } 56 | 57 | /** 58 | * Calculate the subnets describing all (and only all) the addresses between two boundaries. 59 | * 60 | * @param \IPLib\Address\AddressInterface $from 61 | * @param \IPLib\Address\AddressInterface $to 62 | * 63 | * @return \IPLib\Range\Subnet[]|null return NULL if the two addresses have an invalid number of bits (that is, different from the one passed to the constructor of this class) 64 | */ 65 | public function getRanges(AddressInterface $from, AddressInterface $to) 66 | { 67 | if ($from->getNumberOfBits() !== $this->numBits || $to->getNumberOfBits() !== $this->numBits) { 68 | return null; 69 | } 70 | if ($from->getComparableString() > $to->getComparableString()) { 71 | list($from, $to) = array($to, $from); 72 | } 73 | $result = array(); 74 | $this->calculate($this->math->reduce($from->getBits()), $this->math->reduce($to->getBits()), $this->numBits, $result); 75 | 76 | return $result; 77 | } 78 | 79 | /** 80 | * Set the number of bits used to represent addresses (32 for IPv4, 128 for IPv6). 81 | * 82 | * @param int $numBits 83 | */ 84 | private function setNumBits($numBits) 85 | { 86 | $numBits = (int) $numBits; 87 | $masks = array(); 88 | $unmasks = array(); 89 | for ($bit = 0; $bit < $numBits; $bit++) { 90 | $masks[$bit] = str_repeat('1', $numBits - $bit) . str_repeat('0', $bit); 91 | $unmasks[$bit] = $bit === 0 ? '0' : str_repeat('1', $bit); 92 | } 93 | $this->numBits = $numBits; 94 | $this->masks = $masks; 95 | $this->unmasks = $unmasks; 96 | } 97 | 98 | /** 99 | * Calculate the subnets. 100 | * 101 | * @param string $start the start address (represented in reduced bit form) 102 | * @param string $end the end address (represented in reduced bit form) 103 | * @param int $position the number of bits in the mask we are comparing at this cycle 104 | * @param \IPLib\Range\Subnet[] $result found ranges will be added to this variable 105 | */ 106 | private function calculate($start, $end, $position, array &$result) 107 | { 108 | if ($start === $end) { 109 | $result[] = $this->subnetFromBits($start, $this->numBits); 110 | 111 | return; 112 | } 113 | for ($index = $position - 1; $index >= 0; $index--) { 114 | $startMasked = $this->math->andX($start, $this->masks[$index]); 115 | $endMasked = $this->math->andX($end, $this->masks[$index]); 116 | if ($startMasked !== $endMasked) { 117 | $position = $index; 118 | break; 119 | } 120 | } 121 | if ($startMasked === $start && $this->math->andX($this->math->increment($end), $this->unmasks[$position]) === '0') { 122 | $result[] = $this->subnetFromBits($start, $this->numBits - 1 - $position); 123 | 124 | return; 125 | } 126 | $middleAddress = $this->math->orX($start, $this->unmasks[$position]); 127 | $this->calculate($start, $middleAddress, $position, $result); 128 | $this->calculate($this->math->increment($middleAddress), $end, $position, $result); 129 | } 130 | 131 | /** 132 | * Create an address instance starting from its bits. 133 | * 134 | * @param string $bits the bits of the address (represented in reduced bit form) 135 | * 136 | * @return \IPLib\Address\AddressInterface 137 | */ 138 | private function addressFromBits($bits) 139 | { 140 | $bits = str_pad($bits, $this->numBits, '0', STR_PAD_LEFT); 141 | $bytes = array(); 142 | foreach (explode("\n", trim(chunk_split($bits, 8, "\n"))) as $byteBits) { 143 | $bytes[] = bindec($byteBits); 144 | } 145 | 146 | return Factory::addressFromBytes($bytes); 147 | } 148 | 149 | /** 150 | * Create an range instance starting from the bits if the address and the length of the network prefix. 151 | * 152 | * @param string $bits the bits of the address (represented in reduced bit form) 153 | * @param int $networkPrefix the length of the network prefix 154 | * 155 | * @return \IPLib\Range\Subnet 156 | */ 157 | private function subnetFromBits($bits, $networkPrefix) 158 | { 159 | $startAddress = $this->addressFromBits($bits); 160 | $numOnes = $this->numBits - $networkPrefix; 161 | if ($numOnes === 0) { 162 | return new Subnet($startAddress, $startAddress, $networkPrefix); 163 | } 164 | $endAddress = $this->addressFromBits(substr($bits, 0, -$numOnes) . str_repeat('1', $numOnes)); 165 | 166 | return new Subnet($startAddress, $endAddress, $networkPrefix); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /vendor/mlocati/ip-lib/src/Service/UnsignedIntegerMath.php: -------------------------------------------------------------------------------- 1 | getBytesFromDecimal($m[1], $numBytes); 27 | } 28 | } else { 29 | if (preg_match('/^0[Xx]0*([0-9A-Fa-f]+)$/', $value, $m)) { 30 | return $this->getBytesFromHexadecimal($m[1], $numBytes); 31 | } 32 | if (preg_match('/^0+([0-7]*)$/', $value, $m)) { 33 | return $this->getBytesFromOctal($m[1], $numBytes); 34 | } 35 | if (preg_match('/^[1-9][0-9]*$/', $value)) { 36 | return $this->getBytesFromDecimal($value, $numBytes); 37 | } 38 | } 39 | 40 | // Not a valid number 41 | return null; 42 | } 43 | 44 | /** 45 | * @return int 46 | */ 47 | protected function getMaxSignedInt() 48 | { 49 | return PHP_INT_MAX; 50 | } 51 | 52 | /** 53 | * @param string $value never zero-length, never extra leading zeroes 54 | * @param int $numBytes 55 | * 56 | * @return int[]|null 57 | */ 58 | private function getBytesFromBits($value, $numBytes) 59 | { 60 | $valueLength = strlen($value); 61 | if ($valueLength > $numBytes << 3) { 62 | // overflow 63 | return null; 64 | } 65 | $remainderBits = $valueLength % 8; 66 | if ($remainderBits !== 0) { 67 | $value = str_pad($value, $valueLength + 8 - $remainderBits, '0', STR_PAD_LEFT); 68 | } 69 | $bytes = array_map('bindec', str_split($value, 8)); 70 | 71 | return array_pad($bytes, -$numBytes, 0); 72 | } 73 | 74 | /** 75 | * @param string $value may be zero-length, never extra leading zeroes 76 | * @param int $numBytes 77 | * 78 | * @return int[]|null 79 | */ 80 | private function getBytesFromOctal($value, $numBytes) 81 | { 82 | if ($value === '') { 83 | return array_fill(0, $numBytes, 0); 84 | } 85 | $bits = implode( 86 | '', 87 | array_map( 88 | function ($octalDigit) { 89 | return str_pad(decbin(octdec($octalDigit)), 3, '0', STR_PAD_LEFT); 90 | }, 91 | str_split($value, 1) 92 | ) 93 | ); 94 | $bits = ltrim($bits, '0'); 95 | 96 | return $bits === '' ? array_fill(0, $numBytes, 0) : static::getBytesFromBits($bits, $numBytes); 97 | } 98 | 99 | /** 100 | * @param string $value never zero-length, never extra leading zeroes 101 | * @param int $numBytes 102 | * 103 | * @return int[]|null 104 | */ 105 | private function getBytesFromDecimal($value, $numBytes) 106 | { 107 | $valueLength = strlen($value); 108 | $maxSignedIntLength = strlen((string) $this->getMaxSignedInt()); 109 | if ($valueLength < $maxSignedIntLength) { 110 | return $this->getBytesFromBits(decbin((int) $value), $numBytes); 111 | } 112 | // Divide by two, so that we have 1 less bit 113 | $carry = 0; 114 | $halfValue = ltrim( 115 | implode( 116 | '', 117 | array_map( 118 | function ($digit) use (&$carry) { 119 | $number = $carry + (int) $digit; 120 | $carry = ($number % 2) * 10; 121 | 122 | return (string) $number >> 1; 123 | }, 124 | str_split($value, 1) 125 | ) 126 | ), 127 | '0' 128 | ); 129 | $halfValueBytes = $this->getBytesFromDecimal($halfValue, $numBytes); 130 | if ($halfValueBytes === null) { 131 | return null; 132 | } 133 | $carry = $carry === 0 ? 0 : 1; 134 | $result = array_fill(0, $numBytes, 0); 135 | for ($index = $numBytes - 1; $index >= 0; $index--) { 136 | $byte = $carry + ($halfValueBytes[$index] << 1); 137 | if ($byte <= 0xFF) { 138 | $carry = 0; 139 | } else { 140 | $carry = ($byte & ~0xFF) >> 8; 141 | $byte -= 0x100; 142 | } 143 | $result[$index] = $byte; 144 | } 145 | if ($carry !== 0) { 146 | // Overflow 147 | return null; 148 | } 149 | 150 | return $result; 151 | } 152 | 153 | /** 154 | * @param string $value never zero-length, never extra leading zeroes 155 | * @param int $numBytes 156 | * 157 | * @return int[]|null 158 | */ 159 | private function getBytesFromHexadecimal($value, $numBytes) 160 | { 161 | $valueLength = strlen($value); 162 | if ($valueLength > $numBytes << 1) { 163 | // overflow 164 | return null; 165 | } 166 | $value = str_pad($value, $valueLength + $valueLength % 2, '0', STR_PAD_LEFT); 167 | $bytes = array_map('hexdec', str_split($value, 2)); 168 | 169 | return array_pad($bytes, -$numBytes, 0); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /vendor/yzalis/identicon/src/Identicon/Generator/BaseGenerator.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class BaseGenerator 11 | { 12 | /** 13 | * @var mixed 14 | */ 15 | protected $generatedImage; 16 | 17 | /** 18 | * @var array 19 | */ 20 | protected $color; 21 | 22 | /** 23 | * @var array 24 | */ 25 | protected $backgroundColor; 26 | 27 | /** 28 | * @var int 29 | */ 30 | protected $size; 31 | 32 | /** 33 | * @var int 34 | */ 35 | protected $pixelRatio; 36 | 37 | /** 38 | * @var string 39 | */ 40 | private $hash; 41 | 42 | /** 43 | * @var array 44 | */ 45 | private $arrayOfSquare = []; 46 | 47 | /** 48 | * Set the image color. 49 | * 50 | * @param string|array $color The color in hexa (3 or 6 chars) or rgb array 51 | * 52 | * @return $this 53 | */ 54 | public function setColor($color) 55 | { 56 | if (null === $color) { 57 | return $this; 58 | } 59 | 60 | $this->color = $this->convertColor($color); 61 | 62 | return $this; 63 | } 64 | 65 | /** 66 | * Set the image background color. 67 | * 68 | * @param string|array $backgroundColor The color in hexa (3 or 6 chars) or rgb array 69 | * 70 | * @return $this 71 | */ 72 | public function setBackgroundColor($backgroundColor) 73 | { 74 | if (null === $backgroundColor) { 75 | return $this; 76 | } 77 | 78 | $this->backgroundColor = $this->convertColor($backgroundColor); 79 | 80 | return $this; 81 | } 82 | 83 | /** 84 | * @param array|string $color 85 | * 86 | * @return array 87 | */ 88 | private function convertColor($color) 89 | { 90 | if (is_array($color)) { 91 | return $color; 92 | } 93 | 94 | if (preg_match('/^#?([a-z\d])([a-z\d])([a-z\d])$/i', $color, $matches)) { 95 | $color = $matches[1].$matches[1]; 96 | $color .= $matches[2].$matches[2]; 97 | $color .= $matches[3].$matches[3]; 98 | } 99 | 100 | preg_match('/#?([a-z\d]{2})([a-z\d]{2})([a-z\d]{2})$/i', $color, $matches); 101 | 102 | return array_map(function ($value) { 103 | return hexdec($value); 104 | }, array_slice($matches, 1, 3)); 105 | } 106 | 107 | /** 108 | * Get the color. 109 | * 110 | * @return array 111 | */ 112 | public function getColor() 113 | { 114 | return $this->color; 115 | } 116 | 117 | /** 118 | * Get the background color. 119 | * 120 | * @return array 121 | */ 122 | public function getBackgroundColor() 123 | { 124 | return $this->backgroundColor; 125 | } 126 | 127 | /** 128 | * Convert the hash into an multidimensional array of boolean. 129 | * 130 | * @return $this 131 | */ 132 | private function convertHashToArrayOfBoolean() 133 | { 134 | preg_match_all('/(\w)(\w)/', $this->hash, $chars); 135 | 136 | foreach ($chars[1] as $i => $char) { 137 | $index = (int) ($i / 3); 138 | $data = $this->convertHexaToBoolean($char); 139 | 140 | $items = [ 141 | 0 => [0, 4], 142 | 1 => [1, 3], 143 | 2 => [2], 144 | ]; 145 | 146 | foreach ($items[$i % 3] as $item) { 147 | $this->arrayOfSquare[$index][$item] = $data; 148 | } 149 | 150 | ksort($this->arrayOfSquare[$index]); 151 | } 152 | 153 | $this->color = array_map(function ($data) { 154 | return hexdec($data) * 16; 155 | }, array_reverse($chars[1])); 156 | 157 | return $this; 158 | } 159 | 160 | /** 161 | * Convert an hexadecimal number into a boolean. 162 | * 163 | * @param string $hexa 164 | * 165 | * @return bool 166 | */ 167 | private function convertHexaToBoolean($hexa) 168 | { 169 | return (bool) round(hexdec($hexa) / 10); 170 | } 171 | 172 | /** 173 | * @return array 174 | */ 175 | public function getArrayOfSquare() 176 | { 177 | return $this->arrayOfSquare; 178 | } 179 | 180 | /** 181 | * Get the identicon string hash. 182 | * 183 | * @return string 184 | */ 185 | public function getHash() 186 | { 187 | return $this->hash; 188 | } 189 | 190 | /** 191 | * Generate a hash from the original string. 192 | * 193 | * @param string $string 194 | * 195 | * @throws \Exception 196 | * 197 | * @return $this 198 | */ 199 | public function setString($string) 200 | { 201 | if (null === $string) { 202 | throw new Exception('The string cannot be null.'); 203 | } 204 | 205 | $this->hash = md5($string); 206 | 207 | $this->convertHashToArrayOfBoolean(); 208 | 209 | return $this; 210 | } 211 | 212 | /** 213 | * Set the image size. 214 | * 215 | * @param int $size 216 | * 217 | * @return $this 218 | */ 219 | public function setSize($size) 220 | { 221 | if (null === $size) { 222 | return $this; 223 | } 224 | 225 | $this->size = $size; 226 | $this->pixelRatio = (int) round($size / 5); 227 | 228 | return $this; 229 | } 230 | 231 | /** 232 | * Get the image size. 233 | * 234 | * @return int 235 | */ 236 | public function getSize() 237 | { 238 | return $this->size; 239 | } 240 | 241 | /** 242 | * Get the pixel ratio. 243 | * 244 | * @return int 245 | */ 246 | public function getPixelRatio() 247 | { 248 | return $this->pixelRatio; 249 | } 250 | } 251 | -------------------------------------------------------------------------------- /vendor/yzalis/identicon/src/Identicon/Generator/GdGenerator.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class GdGenerator extends BaseGenerator implements GeneratorInterface 11 | { 12 | /** 13 | * GdGenerator constructor. 14 | */ 15 | public function __construct() 16 | { 17 | if (!extension_loaded('gd') && !extension_loaded('ext-gd')) { 18 | throw new Exception('GD does not appear to be available in your PHP installation. Please try another generator'); 19 | } 20 | } 21 | 22 | /** 23 | * @return string 24 | */ 25 | public function getMimeType() 26 | { 27 | return 'image/png'; 28 | } 29 | 30 | /** 31 | * @return $this 32 | */ 33 | private function generateImage() 34 | { 35 | // prepare image 36 | $this->generatedImage = imagecreatetruecolor($this->getPixelRatio() * 5, $this->getPixelRatio() * 5); 37 | 38 | $rgbBackgroundColor = $this->getBackgroundColor(); 39 | if (null === $rgbBackgroundColor) { 40 | $background = imagecolorallocate($this->generatedImage, 0, 0, 0); 41 | imagecolortransparent($this->generatedImage, $background); 42 | } else { 43 | $background = imagecolorallocate($this->generatedImage, $rgbBackgroundColor[0], $rgbBackgroundColor[1], $rgbBackgroundColor[2]); 44 | imagefill($this->generatedImage, 0, 0, $background); 45 | } 46 | 47 | // prepare color 48 | $rgbColor = $this->getColor(); 49 | $gdColor = imagecolorallocate($this->generatedImage, $rgbColor[0], $rgbColor[1], $rgbColor[2]); 50 | 51 | // draw content 52 | foreach ($this->getArrayOfSquare() as $lineKey => $lineValue) { 53 | foreach ($lineValue as $colKey => $colValue) { 54 | if (true === $colValue) { 55 | imagefilledrectangle($this->generatedImage, $colKey * $this->getPixelRatio(), $lineKey * $this->getPixelRatio(), ($colKey + 1) * $this->getPixelRatio(), ($lineKey + 1) * $this->getPixelRatio(), $gdColor); 56 | } 57 | } 58 | } 59 | 60 | return $this; 61 | } 62 | 63 | /** 64 | * {@inheritdoc} 65 | */ 66 | public function getImageBinaryData($string, $size = null, $color = null, $backgroundColor = null) 67 | { 68 | ob_start(); 69 | imagepng($this->getImageResource($string, $size, $color, $backgroundColor)); 70 | $imageData = ob_get_contents(); 71 | ob_end_clean(); 72 | 73 | return $imageData; 74 | } 75 | 76 | /** 77 | * {@inheritdoc} 78 | */ 79 | public function getImageResource($string, $size = null, $color = null, $backgroundColor = null) 80 | { 81 | $this 82 | ->setString($string) 83 | ->setSize($size) 84 | ->setColor($color) 85 | ->setBackgroundColor($backgroundColor) 86 | ->generateImage(); 87 | 88 | return $this->generatedImage; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /vendor/yzalis/identicon/src/Identicon/Generator/GeneratorInterface.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | interface GeneratorInterface 9 | { 10 | /** 11 | * @param string $string 12 | * @param int $size 13 | * @param array|string $color 14 | * @param array|string $backgroundColor 15 | * 16 | * @return mixed 17 | */ 18 | public function getImageBinaryData($string, $size = null, $color = null, $backgroundColor = null); 19 | 20 | /** 21 | * @param string $string 22 | * @param int $size 23 | * @param array|string $color 24 | * @param array|string $backgroundColor 25 | * 26 | * @return string 27 | */ 28 | public function getImageResource($string, $size = null, $color = null, $backgroundColor = null); 29 | 30 | /** 31 | * Return the mime-type of this identicon. 32 | * 33 | * @return string 34 | */ 35 | public function getMimeType(); 36 | 37 | /** 38 | * Return the color of the created identicon. 39 | * 40 | * @return array 41 | */ 42 | public function getColor(); 43 | } 44 | -------------------------------------------------------------------------------- /vendor/yzalis/identicon/src/Identicon/Generator/ImageMagickGenerator.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class ImageMagickGenerator extends BaseGenerator implements GeneratorInterface 13 | { 14 | /** 15 | * ImageMagickGenerator constructor. 16 | * 17 | * @throws \Exception 18 | */ 19 | public function __construct() 20 | { 21 | if (!extension_loaded('imagick')) { 22 | throw new Exception('ImageMagick does not appear to be avaliable in your PHP installation. Please try another generator'); 23 | } 24 | } 25 | 26 | /** 27 | * @return string 28 | */ 29 | public function getMimeType() 30 | { 31 | return 'image/png'; 32 | } 33 | 34 | /** 35 | * @return $this 36 | */ 37 | private function generateImage() 38 | { 39 | $this->generatedImage = new \Imagick(); 40 | $rgbBackgroundColor = $this->getBackgroundColor(); 41 | 42 | if (null === $rgbBackgroundColor) { 43 | $background = 'none'; 44 | } else { 45 | $background = new ImagickPixel("rgb($rgbBackgroundColor[0],$rgbBackgroundColor[1],$rgbBackgroundColor[2])"); 46 | } 47 | 48 | $this->generatedImage->newImage($this->pixelRatio * 5, $this->pixelRatio * 5, $background, 'png'); 49 | 50 | // prepare color 51 | $rgbColor = $this->getColor(); 52 | $color = new ImagickPixel("rgb($rgbColor[0],$rgbColor[1],$rgbColor[2])"); 53 | 54 | $draw = new ImagickDraw(); 55 | $draw->setFillColor($color); 56 | 57 | // draw the content 58 | foreach ($this->getArrayOfSquare() as $lineKey => $lineValue) { 59 | foreach ($lineValue as $colKey => $colValue) { 60 | if (true === $colValue) { 61 | $draw->rectangle($colKey * $this->pixelRatio, $lineKey * $this->pixelRatio, ($colKey + 1) * $this->pixelRatio, ($lineKey + 1) * $this->pixelRatio); 62 | } 63 | } 64 | } 65 | 66 | $this->generatedImage->drawImage($draw); 67 | 68 | return $this; 69 | } 70 | 71 | /** 72 | * {@inheritdoc} 73 | */ 74 | public function getImageBinaryData($string, $size = null, $color = null, $backgroundColor = null) 75 | { 76 | ob_start(); 77 | echo $this->getImageResource($string, $size, $color, $backgroundColor); 78 | $imageData = ob_get_contents(); 79 | ob_end_clean(); 80 | 81 | return $imageData; 82 | } 83 | 84 | /** 85 | * {@inheritdoc} 86 | */ 87 | public function getImageResource($string, $size = null, $color = null, $backgroundColor = null) 88 | { 89 | $this 90 | ->setString($string) 91 | ->setSize($size) 92 | ->setColor($color) 93 | ->setBackgroundColor($backgroundColor) 94 | ->generateImage(); 95 | 96 | return $this->generatedImage; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /vendor/yzalis/identicon/src/Identicon/Generator/SvgGenerator.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | class SvgGenerator extends BaseGenerator implements GeneratorInterface 9 | { 10 | /** 11 | * {@inheritdoc} 12 | */ 13 | public function getMimeType() 14 | { 15 | return 'image/svg+xml'; 16 | } 17 | 18 | /** 19 | * {@inheritdoc} 20 | */ 21 | public function getImageBinaryData($string, $size = null, $color = null, $backgroundColor = null) 22 | { 23 | return $this->getImageResource($string, $size, $color, $backgroundColor); 24 | } 25 | 26 | /** 27 | * {@inheritdoc} 28 | */ 29 | public function getImageResource($string, $size = null, $color = null, $backgroundColor = null) 30 | { 31 | $this 32 | ->setString($string) 33 | ->setSize($size) 34 | ->setColor($color) 35 | ->setBackgroundColor($backgroundColor) 36 | ->_generateImage(); 37 | 38 | return $this->generatedImage; 39 | } 40 | 41 | /** 42 | * @return $this 43 | */ 44 | protected function _generateImage() 45 | { 46 | // prepare image 47 | $w = $this->getPixelRatio() * 5; 48 | $h = $this->getPixelRatio() * 5; 49 | $svg = ''; 50 | 51 | $backgroundColor = '#FFF'; 52 | $rgbBackgroundColor = $this->getBackgroundColor(); 53 | if (!is_null($rgbBackgroundColor)) { 54 | $backgroundColor = $this->_toUnderstandableColor($rgbBackgroundColor); 55 | } 56 | 57 | $svg .= ''; 58 | 59 | $rects = []; 60 | // draw content 61 | foreach ($this->getArrayOfSquare() as $lineKey => $lineValue) { 62 | foreach ($lineValue as $colKey => $colValue) { 63 | if (true === $colValue) { 64 | $rects[] = 'M'.$colKey.','.$lineKey.'h1v1h-1v-1'; 65 | } 66 | } 67 | } 68 | 69 | $rgbColor = $this->_toUnderstandableColor($this->getColor()); 70 | $svg .= ''; 71 | $svg .= ''; 72 | 73 | $this->generatedImage = $svg; 74 | 75 | return $this; 76 | } 77 | 78 | /** 79 | * @param array|string $color 80 | * 81 | * @return string 82 | */ 83 | protected function _toUnderstandableColor($color) 84 | { 85 | if (is_array($color)) { 86 | return sprintf('#%X%X%X', $color[0], $color[1], $color[2]); 87 | } 88 | 89 | return $color; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /vendor/yzalis/identicon/src/Identicon/Identicon.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class Identicon 12 | { 13 | /** 14 | * @var \Identicon\Generator\GeneratorInterface 15 | */ 16 | private $generator; 17 | 18 | /** 19 | * Identicon constructor. 20 | * 21 | * @param \Identicon\Generator\GeneratorInterface|null $generator 22 | */ 23 | public function __construct($generator = null) 24 | { 25 | if (null === $generator) { 26 | $this->generator = new GdGenerator(); 27 | } else { 28 | $this->generator = $generator; 29 | } 30 | } 31 | 32 | /** 33 | * Set the image generator. 34 | * 35 | * @param \Identicon\Generator\GeneratorInterface $generator 36 | * 37 | * @return $this 38 | */ 39 | public function setGenerator(GeneratorInterface $generator) 40 | { 41 | $this->generator = $generator; 42 | 43 | return $this; 44 | } 45 | 46 | /** 47 | * Display an Identicon image. 48 | * 49 | * @param string $string 50 | * @param int $size 51 | * @param string|array $color 52 | * @param string $backgroundColor 53 | */ 54 | public function displayImage($string, $size = 64, $color = null, $backgroundColor = null) 55 | { 56 | header('Content-Type: '.$this->generator->getMimeType()); 57 | echo $this->getImageData($string, $size, $color, $backgroundColor); 58 | } 59 | 60 | /** 61 | * Get an Identicon PNG image data. 62 | * 63 | * @param string $string 64 | * @param int $size 65 | * @param string|array $color 66 | * @param string $backgroundColor 67 | * 68 | * @return string 69 | */ 70 | public function getImageData($string, $size = 64, $color = null, $backgroundColor = null) 71 | { 72 | return $this->generator->getImageBinaryData($string, $size, $color, $backgroundColor); 73 | } 74 | 75 | /** 76 | * Get an Identicon PNG image resource. 77 | * 78 | * @param string $string 79 | * @param int $size 80 | * @param string|array $color 81 | * @param string $backgroundColor 82 | * 83 | * @return string 84 | */ 85 | public function getImageResource($string, $size = 64, $color = null, $backgroundColor = null) 86 | { 87 | return $this->generator->getImageResource($string, $size, $color, $backgroundColor); 88 | } 89 | 90 | /** 91 | * Get an Identicon PNG image data as base 64 encoded. 92 | * 93 | * @param string $string 94 | * @param int $size 95 | * @param string|array $color 96 | * @param string $backgroundColor 97 | * 98 | * @return string 99 | */ 100 | public function getImageDataUri($string, $size = 64, $color = null, $backgroundColor = null) 101 | { 102 | return sprintf('data:%s;base64,%s', $this->generator->getMimeType(), base64_encode($this->getImageData($string, $size, $color, $backgroundColor))); 103 | } 104 | 105 | /** 106 | * Get the color of the Identicon 107 | * 108 | * Returns an array with RGB values of the Identicon's color. Colors may be NULL if no image has been generated 109 | * so far (e.g., when calling the method on a new Identicon()). 110 | * 111 | * @return array 112 | */ 113 | public function getColor() 114 | { 115 | $colors = $this->generator->getColor(); 116 | 117 | return [ 118 | "r" => $colors[0], 119 | "g" => $colors[1], 120 | "b" => $colors[2] 121 | ]; 122 | } 123 | } 124 | --------------------------------------------------------------------------------