Compare commits
253 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
815895a524 | ||
|
|
de764c105c | ||
|
|
749e7f193f | ||
|
|
2cda214f86 | ||
|
|
f62b30d696 | ||
|
|
b07a68bb45 | ||
|
|
2b0dc071a0 | ||
|
|
f2cf56ceaa | ||
|
|
783f996e77 | ||
|
|
17dfb43abd | ||
|
|
1693bcaa78 | ||
|
|
bc1eca4014 | ||
|
|
fc9a7d3072 | ||
|
|
67fba8e66b | ||
|
|
7f18a193d4 | ||
|
|
090f452585 | ||
|
|
819c25374c | ||
|
|
2388f68d5d | ||
|
|
3fe84a63a4 | ||
|
|
774c8e0112 | ||
|
|
63132e1cfb | ||
|
|
d349ee8fc6 | ||
|
|
5c3ee9e159 | ||
|
|
cea501d854 | ||
|
|
a1bc5b5fa5 | ||
|
|
d3d5d1c385 | ||
|
|
f000404d5a | ||
|
|
c777cd62ab | ||
|
|
06a524ca2f | ||
|
|
2712946287 | ||
|
|
fffcb13ac9 | ||
|
|
307243a5bf | ||
|
|
61acb5420b | ||
|
|
cccb80de03 | ||
|
|
d0deb6f6c9 | ||
|
|
e551ef2bb2 | ||
|
|
21aa1fbb7d | ||
|
|
4c1124da07 | ||
|
|
19d7cb060e | ||
|
|
c90a716d45 | ||
|
|
4fbf8b31a2 | ||
|
|
422c17eb65 | ||
|
|
70cdcf5dcf | ||
|
|
7b4b27098d | ||
|
|
2362af1e8c | ||
|
|
28f5677247 | ||
|
|
8c2702be96 | ||
|
|
452db23c57 | ||
|
|
c6baa6edfa | ||
|
|
74ccf9f626 | ||
|
|
56f89d5610 | ||
|
|
0ea4b3c160 | ||
|
|
93d78d44fe | ||
|
|
7dac978d16 | ||
|
|
312f18ade2 | ||
|
|
cb2d17411c | ||
|
|
9a4a20fb41 | ||
|
|
72394f17ba | ||
|
|
240c7359a8 | ||
|
|
9d8d5f3d36 | ||
|
|
25b39bbd86 | ||
|
|
4964967524 | ||
|
|
bfb43ab856 | ||
|
|
03464199ee | ||
|
|
96e73e2baf | ||
|
|
6ad94f2063 | ||
|
|
45b2e11729 | ||
|
|
c7f8f37c62 | ||
|
|
6f540ad27e | ||
|
|
ef1a1ecaff | ||
|
|
be5f601866 | ||
|
|
45d933ebf0 | ||
|
|
a145ca88cc | ||
|
|
cf0effd0e8 | ||
|
|
8ee26e6922 | ||
|
|
9d1a4db4d2 | ||
|
|
adb1c468cd | ||
|
|
d6f3b7b5df | ||
|
|
33b08f378d | ||
|
|
31d2712733 | ||
|
|
9200d3d93c | ||
|
|
b669e69511 | ||
|
|
f0cfdeb650 | ||
|
|
99d9542b80 | ||
|
|
b65186f77f | ||
|
|
3ee37fe3a2 | ||
|
|
5ecf80bce1 | ||
|
|
5a5c4a0334 | ||
|
|
7c7358af9c | ||
|
|
ebc4ebda03 | ||
|
|
a4dc4366ba | ||
|
|
ea40ffbc46 | ||
|
|
9a7fadb231 | ||
|
|
199f162fdf | ||
|
|
70c06cfa5c | ||
|
|
520099be96 | ||
|
|
5cf9b86868 | ||
|
|
03d4875e92 | ||
|
|
726c77effb | ||
|
|
68de83b46a | ||
|
|
77d4023f00 | ||
|
|
0119368376 | ||
|
|
166ff1da1b | ||
|
|
7727fc9ea4 | ||
|
|
8de53d1ea7 | ||
|
|
0250b6a577 | ||
|
|
e13f4816fb | ||
|
|
75784174fa | ||
|
|
6d504f3a48 | ||
|
|
3a6c987347 | ||
|
|
5861e73848 | ||
|
|
a2b7feb6f9 | ||
|
|
dce00906ec | ||
|
|
ceffa04b6e | ||
|
|
984246912c | ||
|
|
3a8ac33dd1 | ||
|
|
7e28024d32 | ||
|
|
b149fe88cb | ||
|
|
3a27592d58 | ||
|
|
80e210af86 | ||
|
|
220a3103fa | ||
|
|
6ec765024e | ||
|
|
6c556e921f | ||
|
|
3a90787091 | ||
|
|
c4087c1e84 | ||
|
|
76c0f6cec1 | ||
|
|
f01b685820 | ||
|
|
e022227617 | ||
|
|
2fc56d438d | ||
|
|
fb50f23e19 | ||
|
|
40c53173ca | ||
|
|
30c78ab7da | ||
|
|
5e59d7e80d | ||
|
|
dd0d274ab1 | ||
|
|
3c7e8bea7c | ||
|
|
1a46209bfe | ||
|
|
ad04aeb5b6 | ||
|
|
bbb0b5b111 | ||
|
|
a19d0a3d48 | ||
|
|
63fe1b3edd | ||
|
|
b9e42d0f31 | ||
|
|
021fbad811 | ||
|
|
6cab15f8e7 | ||
|
|
f863045fcf | ||
|
|
87fa55eae8 | ||
|
|
6806e4a15a | ||
|
|
82f97479ff | ||
|
|
75124102cb | ||
|
|
515e034d91 | ||
|
|
2a628e7d7a | ||
|
|
8e3cf866a6 | ||
|
|
6adb557693 | ||
|
|
c178f3af44 | ||
|
|
8da3573ffb | ||
|
|
5f5b836a22 | ||
|
|
17974088bc | ||
|
|
4d5d57df8a | ||
|
|
71df6a54c4 | ||
|
|
4a5e29e7c1 | ||
|
|
9d2bf6a931 | ||
|
|
66eebd1445 | ||
|
|
38f6b1c22f | ||
|
|
263f0b762b | ||
|
|
9f9449a58d | ||
|
|
1cb8e28be7 | ||
|
|
37e0ae26f8 | ||
|
|
d41e06efa0 | ||
|
|
772860e186 | ||
|
|
5cc690bbee | ||
|
|
b2a7c778d8 | ||
|
|
771ec3305e | ||
|
|
f4cea4ce08 | ||
|
|
66570c54d8 | ||
|
|
ee0000bf59 | ||
|
|
5d6b57cabc | ||
|
|
b3e777baa3 | ||
|
|
fb25657d2f | ||
|
|
a58de1f02e | ||
|
|
3e6cfdfed6 | ||
|
|
7170825166 | ||
|
|
2e6a3313a6 | ||
|
|
b0eafc9474 | ||
|
|
d3efbb0d99 | ||
|
|
c5715182c0 | ||
|
|
f7adc73a86 | ||
|
|
d25d562598 | ||
|
|
28937f4270 | ||
|
|
b50e522c0d | ||
|
|
5fb9d21016 | ||
|
|
66fc8aff14 | ||
|
|
b6609b1df2 | ||
|
|
c649233835 | ||
|
|
35ba2c991a | ||
|
|
0210507c22 | ||
|
|
b66a1f2a55 | ||
|
|
bf13df48aa | ||
|
|
4183b1a2db | ||
|
|
e922f9c907 | ||
|
|
801b4acd9d | ||
|
|
aa75c56364 | ||
|
|
b6612cd838 | ||
|
|
3345eb399c | ||
|
|
63a28b8b4b | ||
|
|
3e63da324c | ||
|
|
47545e5702 | ||
|
|
0fe80b29b8 | ||
|
|
0b981d52a6 | ||
|
|
16688fae3c | ||
|
|
00580d8bcc | ||
|
|
56654e1ff4 | ||
|
|
24411dfe93 | ||
|
|
479798a1d2 | ||
|
|
75cde97ae9 | ||
|
|
8f1a4f3af9 | ||
|
|
7adf83cb3a | ||
|
|
d292bbf6bd | ||
|
|
15af093b27 | ||
|
|
e9c6795d7d | ||
|
|
977d3f6bda | ||
|
|
e57360bcfc | ||
|
|
8586775116 | ||
|
|
fd401088bb | ||
|
|
abcc7ca654 | ||
|
|
a75b2e3f62 | ||
|
|
823f7e60d8 | ||
|
|
b63e94c566 | ||
|
|
bfd475b37d | ||
|
|
effeb7daea | ||
|
|
ee4bc7dfe0 | ||
|
|
f88268d7c6 | ||
|
|
3127158064 | ||
|
|
6ce37566b9 | ||
|
|
e6f5a077d3 | ||
|
|
a13d5882ad | ||
|
|
dd3ea7f09b | ||
|
|
040c76dda1 | ||
|
|
eefaaf1643 | ||
|
|
3b922bb05e | ||
|
|
e01a04393f | ||
|
|
5792bf06e2 | ||
|
|
4e680c78d5 | ||
|
|
377d42bfcd | ||
|
|
36089fb199 | ||
|
|
7df2ac0740 | ||
|
|
cd32706ec4 | ||
|
|
c8a6ca728f | ||
|
|
d2d992da6f | ||
|
|
6ba5e31592 | ||
|
|
940338159e | ||
|
|
27a65d4c59 | ||
|
|
73fed1269e | ||
|
|
321d821661 | ||
|
|
17782dc734 |
7
.dockerignore
Normal file
@@ -0,0 +1,7 @@
|
||||
tmp/*
|
||||
inc/config.inc.php
|
||||
data/*
|
||||
lib/vendor
|
||||
bin
|
||||
.git
|
||||
.github
|
||||
59
.github/workflows/build-docker.yml
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*.*.*"
|
||||
pull_request:
|
||||
branches:
|
||||
- "master"
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
# list of Docker images to use as base name for tags
|
||||
images: |
|
||||
hascheksolutions/pictshare
|
||||
ghcr.io/hascheksolutions/pictshare
|
||||
# generate Docker tags based on the following events/attributes
|
||||
tags: |
|
||||
type=schedule
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=sha
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to Docker Hub
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Login to GHCR
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: docker/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
5
.gitignore
vendored
@@ -1 +1,4 @@
|
||||
test.php
|
||||
test.php
|
||||
notice.txt
|
||||
lib/vendor
|
||||
.vscode
|
||||
3
CHANGELOG.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# V2.0.0 (Nov 2023)
|
||||
- Pushed current release to version 2.0
|
||||
- Updated CI to include versions
|
||||
1
LICENSE
@@ -199,4 +199,3 @@
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
469
README.md
@@ -1,328 +1,141 @@
|
||||
# PictShare
|
||||
**[Live Demo](https://www.pictshare.net)**
|
||||
PictShare is a multi lingual, open source image hosting service with a simple resizing and upload API that you can host yourself.
|
||||
|
||||
---
|
||||
[](https://github.com/chrisiaut/pictshare/blob/master/LICENSE)
|
||||
|
||||
|
||||

|
||||
|
||||
Table of contents
|
||||
=================
|
||||
* [Installation](#installation)
|
||||
* [Docker](#docker)
|
||||
* [On nginx](#on-nginx)
|
||||
* [Docker Compose With Prebuild Image by hascheksolutions](#docker-compose-with-prebuild-image-by-hascheksolutions)
|
||||
* [Why would I want to host my own images?](#why-would-i-want-to-host-my-own-images)
|
||||
* [Features](#features)
|
||||
* [Smart query system](#smart-query-system)
|
||||
* [Available options](#available-options)
|
||||
* [How does the external-upload-API work?](#how-does-the-external-upload-api-work)
|
||||
* [Upload from external URL](#upload-from-external-url)
|
||||
* [Example:](#example)
|
||||
* [Upload via POST](#upload-via-post)
|
||||
* [Upload from base64 string](#upload-from-base64-string)
|
||||
* [Restriction settings](#restriction-settings)
|
||||
* [UPLOAD_CODE](#upload_code)
|
||||
* [IMAGE_CHANGE_CODE](#image_change_code)
|
||||
* [Security and privacy](#security-and-privacy)
|
||||
* [Requirements](#requirements)
|
||||
* [Upgrading](#upgrading)
|
||||
* [Addons](#addons)
|
||||
* [Traffic analysis](#traffic-analysis)
|
||||
* [Coming soon](#coming-soon)
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
### Docker
|
||||
The fastest way to deploy PictShare is via the [official Docker repo](https://hub.docker.com/r/hascheksolutions/pictshare/)
|
||||
- [Source code & more examples](https://github.com/HaschekSolutions/PictShare-Docker)
|
||||
|
||||
```bash
|
||||
docker run -d -p 80:80 -e "TITLE=My own PictShare" hascheksolutions/pictshare
|
||||
```
|
||||
|
||||
[](https://www.pictshare.net/8a1dec0973.mp4)
|
||||
|
||||
### Docker Compose With Prebuild Image by hascheksolutions
|
||||
|
||||
Run container by docker-compose:
|
||||
- First, install docker compose:
|
||||
[Docker official docs](https://docs.docker.com/compose/install/)
|
||||
- Pull docker-compose file:
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/chrisiaut/pictshare/master/docker-compose.yml
|
||||
```
|
||||
- Edit docker-compose file:
|
||||
```bash
|
||||
vi docker-compose.yml
|
||||
```
|
||||
- Run container by docker-compose:
|
||||
```bash
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
By using this compose file, you should know that:
|
||||
- Will make a directory "volumes" in the same directory where compose file is.
|
||||
- Change `AUTOUPDATE` to false from true by defalt.
|
||||
- And...it is highly recommended to build your own image.
|
||||
|
||||
### Without Docker
|
||||
|
||||
- Make sure you have PHP5 GD libraries installed: ```apt-get install php5-gd```
|
||||
- Unpack the [PictShare zip](https://github.com/chrisiaut/pictshare/archive/master.zip)
|
||||
- Rename /inc/example.config.inc.php to /inc/config.inc.php
|
||||
- ```chmod +x bin/ffmpeg``` if you want to be able to use mp4 uploads
|
||||
- The provided ffmpeg binary (bin/ffmpeg) is from [here](http://johnvansickle.com/ffmpeg/) and it's a 64bit linux executable. If you need a different one, load yours and overwrite the one provided
|
||||
- (optional) You can and should put a [nginx](https://www.nginx.com/) proxy before the Apache server. That thing is just insanely fast with static content like images.
|
||||
- (optional) To secure your traffic I'd highly recommend getting an [SSL Cert](https://letsencrypt.org/) for your server if you don't already have one.
|
||||
|
||||
|
||||
UPDATES
|
||||
========
|
||||
- Nov. 23: Added support for MP4 uploads and conversion from gif to MP4
|
||||
- Nov. 12: Created new git project: [Pictshare stats](https://github.com/chrisiaut/pictshare_stats)
|
||||
- Nov. 07: Added 9 new (instagram-like) filters
|
||||
- Nov. 06: Master delete code. One code to delete them all
|
||||
- Nov. 01: [Restricted uploads and option-use](#restriction-settings)
|
||||
- Oct. 30: [Rotations and filters](#smart-query-system)
|
||||
- Oct. 10: [Album functionality](#smart-query-system) finally ready
|
||||
|
||||
## Why would I want to host my own images?
|
||||
If you own a server (even a home server) you can host your own PictShare instance so you have full control over your content and can delete images hasslefree.
|
||||
|
||||
If you're an **app developer** or **sysadmin** you can use it for a centralized image hosting. With the simple upload API you can upload images to your PictShare instance and get a nice short URL
|
||||
|
||||
If you're a blogger like myself, you can use it as storage for your images so the images will still work even if you change blog providers or servers
|
||||
|
||||
## Features
|
||||
- Uploads without logins or validation (that's a good thing, right?)
|
||||
- Simple API to upload any image from remote servers to your instance [via URL](#upload-from-url) and [via Base64](#upload-from-base64-string)
|
||||
- 100% file based - no database needed
|
||||
- Simple album functions with embedding support
|
||||
- Converts gif to (much smaller) MP4
|
||||
- MP4 resizing
|
||||
- PictShare removes all exif data so you can upload photos from your phone and all GPS tags and camera model info get wiped
|
||||
- Smart [resize, filter and rotation](#smart-query-system) features
|
||||
- Duplicates don't take up space. If the exact same images is uploaded twice, the second upload will link to the first
|
||||
- You can control who can upload images or use filters/resizes by defining an [upload-code](#restriction-settings)
|
||||
- You can set a code in your ```/inc/config.inc.php``` (MASTER_DELETE_CODE) that, if appended to any URL of an Image, will delete the image and all cached versions of it from the server
|
||||
- Detailed traffic and view statistics of your images via [Pictshare stats](https://github.com/chrisiaut/pictshare_stats)
|
||||
|
||||
## Smart query system
|
||||
PictShare images can be changed after upload just by modifying the URL. It works like this:
|
||||
|
||||
<span style="color:blue">https://base.domain</span>/<span style="color:red"><options></span>/<span style="color:green"><image></span>
|
||||
|
||||
For example: https://pictshare.net/100x100/negative/b260e36b60.jpg will show you the uploaded Image ```b260e36b60.jpg``` but resize it to 100x100 pixels and apply the "negative" filter. The original image will stay untouched.
|
||||
|
||||
### Available options
|
||||
Original URL: ```https://www.pictshare.net/b260e36b60.jpg```
|
||||
|
||||
Note: If an option needs a value it works like this: ```optionname_value```. Eg: ```pixelate_10```
|
||||
If there is some option that's not recognized by PictShare it's simply ignored, so this will work: https://www.pictshare.net/pictshare-is-awesome/b260e36b60.jpg and also even this will work: https://www.pictshare.net/b260e36b60.jpg/how-can-this-still/work/
|
||||
|
||||
|
||||
| Option | Parameter | Example URL | Result |
|
||||
| ------------- | ------------------- | ---------------------- | ----------- |
|
||||
**Resizing** | | | |
|
||||
<width>**x**<height> | -none- | https://pictshare.net/20x20/b260e36b60.jpg |  |
|
||||
forcesize | -none- | https://pictshare.net/100x400/forcesize/b260e36b60.jpg |  |
|
||||
**Albums** | | | |
|
||||
just add multiple image hashes | -none- | https://www.pictshare.net/b260e36b60.jpg/32c9cf77c5.jpg/163484b6b1.jpg | Takes the **images** you put in the URL and makes an album out of them. All filters are supported!
|
||||
embed | -none- | https://www.pictshare.net/b260e36b60.jpg/32c9cf77c5.jpg/163484b6b1.jpg/embed | Renders the album without CSS and with transparent background so you can embed them easily
|
||||
responsive | -none- | https://www.pictshare.net/b260e36b60.jpg/32c9cf77c5.jpg/163484b6b1.jpg/responsive | Renders all images responsive (max-width 100%) according to screen size
|
||||
<width>**x**<height> | -none- | https://www.pictshare.net/b260e36b60.jpg/32c9cf77c5.jpg/163484b6b1.jpg/150x150 | Sets the size for the thumbnails in the album
|
||||
forcesize | -none- | https://www.pictshare.net/b260e36b60.jpg/32c9cf77c5.jpg/163484b6b1.jpg/100x300/forcesize | Forces thumbnail sizes to the values you provided
|
||||
**GIF to mp4** | | |
|
||||
mp4 | -none- | https://www.pictshare.net/mp4/102687fe65.gif | Converts gif to mp4 and displays as that. Note that you can't include that mp4 in an img tag
|
||||
raw | -none- | https://www.pictshare.net/mp4/raw/102687fe65.gif | Renders the converted mp4 directly. Use with /mp4/
|
||||
preview | -none- | https://www.pictshare.net/mp4/preview/102687fe65.gif | Renders the first frame of generated MP4 as JPEG. Use with /mp4/
|
||||
**MP4 options** | | |
|
||||
-none- | -none- | https://www.pictshare.net/65714d22f0.mp4 | Renders the mp4 embedded in a simple HTML template. This link can't be embedded into video tags, use /raw/ instead if you want to embed
|
||||
raw | -none- | https://www.pictshare.net/raw/65714d22f0.mp4 | Renders the mp4 video directly so you can link it
|
||||
preview | -none- | https://www.pictshare.net/preview/65714d22f0.mp4 | Renders the first frame of the MP4 as an JPEG image
|
||||
**Rotating** | | |
|
||||
left | -none- | https://pictshare.net/left/b260e36b60.jpg | 
|
||||
right | -none- | https://pictshare.net/right/b260e36b60.jpg | 
|
||||
upside | -none- | https://pictshare.net/upside/b260e36b60.jpg | 
|
||||
**Filters** | | |
|
||||
negative | -none- | https://pictshare.net/negative/b260e36b60.jpg | 
|
||||
grayscale | -none- | https://pictshare.net/grayscale/b260e36b60.jpg | 
|
||||
brightness | -255 to 255 | https://pictshare.net/brightness_100/b260e36b60.jpg | 
|
||||
edgedetect | -none- | https://pictshare.net/edgedetect/b260e36b60.jpg | 
|
||||
smooth | -10 to 2048 | https://pictshare.net/smooth_3/b260e36b60.jpg | 
|
||||
contrast | -100 to 100 | https://pictshare.net/contrast_40/b260e36b60.jpg | 
|
||||
pixelate | 0 to 100 | https://pictshare.net/pixelate_10/b260e36b60.jpg | 
|
||||
blur | -none- or 0 to 5 | https://pictshare.net/blur/b260e36b60.jpg | 
|
||||
sepia | -none- | https://pictshare.net/sepia/b260e36b60.jpg | 
|
||||
sharpen | -none- | https://pictshare.net/sharpen/b260e36b60.jpg | 
|
||||
emboss | -none- | https://pictshare.net/emboss/b260e36b60.jpg | 
|
||||
cool | -none- | https://pictshare.net/cool/b260e36b60.jpg | 
|
||||
light | -none- | https://pictshare.net/light/b260e36b60.jpg | 
|
||||
aqua | -none- | https://pictshare.net/aqua/b260e36b60.jpg | 
|
||||
fuzzy | -none- | https://pictshare.net/fuzzy/b260e36b60.jpg | 
|
||||
boost | -none- | https://pictshare.net/boost/b260e36b60.jpg | 
|
||||
gray | -none- | https://pictshare.net/gray/b260e36b60.jpg | 
|
||||
|
||||
You can also combine as many options as you want. Even multiple times! Want your image to be negative, resized, grayscale , with increased brightness and negate it again? No problem: https://pictshare.net/500x500/grayscale/negative/brightness_100/negative/b260e36b60.jpg
|
||||
|
||||
## How does the external-upload-API work?
|
||||
|
||||
### Upload from external URL
|
||||
PictShare has a simple REST API to upload remote pictures. The API can be accessed via the backend.php file like this:
|
||||
|
||||
```https://pictshare.net/backend.php?getimage=<URL of the image you want to upload>```.
|
||||
|
||||
#### Example:
|
||||
|
||||
Request: ```https://pictshare.net/backend.php?getimage=https://www.0xf.at/css/imgs/logo.png```
|
||||
|
||||
The server will answer with the file name and the server path in JSON:
|
||||
|
||||
```json
|
||||
{"status":"OK","type":"png","hash":"10ba188162.png","url":"https:\/\/pictshare.net\/10ba188162.png"}
|
||||
```
|
||||
|
||||
### Upload via POST
|
||||
|
||||
Send a POST request to ```https://pictshare.net/backend.php``` and send the image in the variable ```postimage```.
|
||||
|
||||
Server will return JSON of uploaded data like this:
|
||||
|
||||
```json
|
||||
{"status":"OK","type":"png","hash":"2f18a052c4.png","url":"https:\/\/pictshare.net\/2f18a052c4.png","domain":"https:\/\/pictshare.net\/"}
|
||||
```
|
||||
|
||||
### Upload from base64 string
|
||||
|
||||
Just send a POST request to ```https://pictshare.net/backend.php``` and send your image in base64 as the variable name ```base64```
|
||||
|
||||
Server will automatically try to guess the file type (which should work in 90% of the cases) and if it can't figure it out it'll just upload it as png.
|
||||
|
||||
## Restriction settings
|
||||
In your ```config.inc.php``` there are two values to be set: ```UPLOAD_CODE``` and ```IMAGE_CHANGE_CODE```
|
||||
|
||||
Both can be set to strings or multiple strings semi;colon;separated. If there is a semicolon in the string, any of the elements will work
|
||||
|
||||
### UPLOAD_CODE
|
||||
If set, will show users a code field in the upload form. If it doesn't match your setting, files won't be uploaded.
|
||||
|
||||
If enabled, the Upload API will need the variable ```upload_code``` via GET (eg: ```https://pictshare.net/backend.php?getimage=https://www.0xf.at/css/imgs/logo.png&upload_code=YourUploadCodeHere```)
|
||||
|
||||
### IMAGE_CHANGE_CODE
|
||||
If set,the [options](#available-options) will only work if the URL got the code in it. You can provide the code as option ```changecode_YourChangeCode```
|
||||
|
||||
For example: If enabled the image ```https://www.pictshare.net/negative/b260e36b60.jpg``` won't show the negative version but the original.
|
||||
If you access the image with the code like this: ```https://www.pictshare.net/changecode_YourChangeCode/b260e36b60.jpg``` it gets cached on the server so the next time someone requests the link without providing the change-code, they'll see the inverted image (because you just created it before by accessing the image with the code)
|
||||
|
||||
## Security and privacy
|
||||
- By hosting your own images you can delete them any time you want
|
||||
- You can enable or disable upload logging. Don't want to know who uploaded stuff? Just change the setting in inc/config.inc.php
|
||||
- No exif data is stored on the server, all jpegs get cleaned on upload
|
||||
- You have full control over your data. PictShare doesn't need remote libaries or tracking crap
|
||||
|
||||
## Scaling
|
||||
You can use Backblaze Buckets for storage of images so you can use multiple instances of PictShare and if the image is not found on the instance, it will look in the bucket.
|
||||
|
||||
Just add your credentials to the config.inc.php file as described in the ```example.config.inc.php``` file.
|
||||
|
||||
## Requirements
|
||||
- Apache or Nginx Webserver with PHP
|
||||
- PHP 5 GD library
|
||||
- A domain or sub-domain since PictShare can't be run from a subfolder of some other domain
|
||||
|
||||
## nginx config
|
||||
This is a simple config file that should make PictShare work on nginx
|
||||
|
||||
- Install php fpm: ```apt-get install php5-fpm```
|
||||
- Install php Graphics libraries: ```apt-get install php5-gd```
|
||||
|
||||
```
|
||||
server {
|
||||
listen 80 default_server;
|
||||
server_name your.awesome.domain.name;
|
||||
|
||||
root /var/www/pictshare; # or where ever you put it
|
||||
index index.php;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?url=$request_uri; # instead of htaccess mod_rewrite
|
||||
}
|
||||
|
||||
location ~ \.php {
|
||||
fastcgi_pass unix:/var/run/php5-fpm.sock;
|
||||
fastcgi_index index.php;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO $fastcgi_script_name;
|
||||
}
|
||||
|
||||
location ~ /(upload|tmp|bin) {
|
||||
deny all;
|
||||
return 404;
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
## Apache config
|
||||
This is a simple vHost config that should make PictShare work on Apache2.
|
||||
|
||||
- Install php5: ```apt-get install php5 libapache2-mod-php5```
|
||||
- Install php Graphics libraries: ```apt-get install php5-gd```
|
||||
- enable mod_rewrite
|
||||
|
||||
```
|
||||
<VirtualHost *:80 >
|
||||
ServerAdmin webmaster@sub.domain.tld
|
||||
ServerName sub.domain.tld
|
||||
ServerAlias sub.domain.tld
|
||||
DocumentRoot /var/www/html
|
||||
|
||||
<Directory /var/www/html/>
|
||||
Options Indexes FollowSymLinks MultiViews
|
||||
AllowOverride All
|
||||
Order allow,deny
|
||||
Allow from All
|
||||
</Directory>
|
||||
ErrorLog ${APACHE_LOG_DIR}/error.log
|
||||
LogLevel warn
|
||||
CustomLog ${APACHE_LOG_DIR}/access.log combined
|
||||
</VirtualHost>
|
||||
```
|
||||
|
||||
|
||||
## Upgrading
|
||||
- Just re-download the [PictShare zip](https://github.com/chrisiaut/pictshare/archive/master.zip) file and extract and overwrite existing pictshare files. Uploads and config won't be affected.
|
||||
- Check if your ```/inc/config.inc.php``` file has all settings required by the ```/inc/example.config.inc.php``` since new options might get added in new versions
|
||||
|
||||
Or use these commands:
|
||||
|
||||
```bash
|
||||
# to be run from the directory where your pictshare directory sits in
|
||||
git clone https://github.com/chrisiaut/pictshare.git temp
|
||||
cp -r temp/* pictshare/.
|
||||
rm -rf temp
|
||||
```
|
||||
|
||||
## Addons
|
||||
- Chrome Browser extension: https://chrome.google.com/webstore/detail/pictshare-1-click-imagesc/mgomffcdpnohakmlhhjmiemlolonpafc
|
||||
- Source: https://github.com/chrisiaut/PictShare-Chrome-extension
|
||||
- Plugin to upload images with ShareX: https://github.com/ShareX/CustomUploaders/blob/master/pictshare.net.sxcu
|
||||
|
||||
## Traffic analysis
|
||||
See [Pictshare stats](https://github.com/chrisiaut/pictshare_stats)
|
||||
|
||||
## Coming soon
|
||||
- Delete codes for every uploaded image so users can delete images if no longer needed
|
||||
- Albums
|
||||
|
||||
---
|
||||
Design (c) by [Bernhard Moser](mailto://bernhard.moser91@gmail.com)
|
||||
|
||||
This is a [HASCHEK SOLUTIONS](https://haschek.solutions) project
|
||||
|
||||
[](https://haschek.solutions)
|
||||
<p align="center">
|
||||
<a href="" rel="noopener">
|
||||
<img height=200px src="./css/imgs/logo/logo.svg" alt="PictShare logo">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<h1 align="center">PictShare</h1>
|
||||
|
||||
<h4 align="center">https://pictshare.net</h4>
|
||||
|
||||
<div align="center">
|
||||
|
||||
|
||||

|
||||
[](https://hub.docker.com/r/hascheksolutions/pictshare)
|
||||
]
|
||||
[](https://github.com/HaschekSolutions/pictshare/blob/master/LICENSE)
|
||||
[](https://hits.seeyoufarm.com)
|
||||
[](https://github.com/HaschekSolutions/pictshare)
|
||||
|
||||
#### Host your own `images` `gifs` `mp4s` `text bins` and stay in control
|
||||
|
||||
</div>
|
||||
|
||||
-----------------------------------------
|
||||
<center>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://www.pictshare.net/39928d8239.gif" alt="PictShare demo">
|
||||
</p>
|
||||
|
||||
Table of contents
|
||||
=================
|
||||
* [Quick Start](#quickstart)
|
||||
* [Features](#features)
|
||||
* [Installation](/rtfm/INSTALL.md)
|
||||
* [Configuration](/rtfm/CONFIG.md)
|
||||
* [Docker](/rtfm/DOCKER.md)
|
||||
* [API](/rtfm/API.md)
|
||||
* [Addons and integration](/rtfm/INTEGRATIONS.md)
|
||||
* [Development roadmap](#development-roadmap)
|
||||
|
||||
---
|
||||
|
||||
## Quickstart
|
||||
|
||||
```bash
|
||||
docker run -d -p 8080:80 --name=pictshare ghcr.io/hascheksolutions/pictshare
|
||||
```
|
||||
|
||||
Then open http://localhost:8080 in your browser
|
||||
|
||||
## New Features
|
||||
|
||||
- Generate identicons based on strings in the URL [example1](https://pictshare.net/identicon/example1) [example2](https://pictshare.net/identicon/example2)
|
||||
- Generate placeholder images by specifying the size in the URL. [example](https://pictshare.net/placeholder/555x250/color-white-blue)
|
||||
- Added support for external storage
|
||||
- [Encryption of files in external storage](/rtfm/ENCRYPTION.md)
|
||||
- Added text hosting (like pastebin)
|
||||
- Added URL shortening
|
||||
- Added WebP to images (and automatic conversion from jpg, png to webp if the requesting browser supports it)
|
||||
- Massive code rework. Actually we designed it from the ground up to be more modular and easier to debug
|
||||
|
||||
# Features
|
||||
|
||||
- Selfhostable
|
||||
- [Simple upload API](/rtfm/API.md)
|
||||
- 100% file based - no database needed
|
||||
- [Scalable hosting](/rtfm/SCALING.md)
|
||||
- Many [Filters](/rtfm/IMAGEFILTERS.md) for images
|
||||
- GIF to MP4 conversion
|
||||
- JPG, PNG to WEBP conversion
|
||||
- MP4 resizing
|
||||
- PictShare removes all exif data so you can upload photos from your phone and all GPS tags and camera model info get wiped
|
||||
- Change and resize your images and videos just by editing the URL
|
||||
- Duplicates don't take up space. If the exact same file is uploaded twice, the second upload will link to the first
|
||||
- Many [configuration options](/rtfm/CONFIG.md)
|
||||
- Full control over your data. Delete images with individual and global delete codes
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Development roadmap
|
||||
|
||||
- [x] Duplicate detection
|
||||
- [x] Write permission detection
|
||||
- [x] Delete codes for every uploaded file
|
||||
- [x] Upload via link/url
|
||||
- [x] Upload via base64
|
||||
- [ ] Autodestruct for every uploaded file
|
||||
|
||||
### Config options
|
||||
|
||||
Read [here](/rtfm/CONFIG.md) what those options do
|
||||
|
||||
- [x] ALT_FOLDER
|
||||
- [x] URL (instead of FORCE_DOMAIN but mandatory)
|
||||
- [x] LOG_UPLOADER
|
||||
- [x] FFMPEG_BINARY
|
||||
- [x] PNG_COMPRESSION
|
||||
- [x] JPEG_COMPRESSION
|
||||
- [x] WEBP_COMPRESSION
|
||||
- [x] MASTER_DELETE_CODE
|
||||
- [x] MASTER_DELETE_IP
|
||||
- [x] UPLOAD_FORM_LOCATION
|
||||
- [x] S3 Backend
|
||||
- [x] UPLOAD_CODE
|
||||
- [ ] UPLOAD_QUOTA
|
||||
- [ ] LOW_PROFILE
|
||||
- [ ] IMAGE_CHANGE_CODE
|
||||
- [ ] MAX_RESIZED_IMAGES
|
||||
- [ ] ALLOW_BLOATING
|
||||
|
||||
### Image hosting
|
||||
- [x] Resizing
|
||||
- [x] Filters
|
||||
- [x] Gif to mp4 conversion
|
||||
- [x] Upload of images
|
||||
|
||||
### Text file hosting
|
||||
- [x] Upload of text files
|
||||
- [x] Render template for text files
|
||||
- [x] Raw data view
|
||||
- [x] Downloadable
|
||||
|
||||
### URL shortening
|
||||
- [ ] Upload of links to shorten
|
||||
|
||||
### MP4 hosting
|
||||
- [x] Resizing
|
||||
- [x] Preview image generation
|
||||
- [x] Upload of videos
|
||||
- [x] Automatic conversion if not mobile friendly or wrong encoder used
|
||||
- [x] Render template for videos
|
||||
|
||||
|
||||
---
|
||||
|
||||
This is a [HASCHEK SOLUTIONS](https://haschek.solutions) project
|
||||
|
||||
[](https://haschek.solutions)
|
||||
|
||||
11
SECURITY.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
PictShare uses rolling releases so the latest version is the only supported one.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Reports can be made as issues in this repo or in confidence via christian@haschek.at
|
||||
|
||||
Pull requests welcome
|
||||
125
api/base64.php
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
// basic path definitions
|
||||
define('DS', DIRECTORY_SEPARATOR);
|
||||
define('ROOT', dirname(__FILE__).'/..');
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
//loading default settings if exist
|
||||
if(!file_exists(ROOT.DS.'inc'.DS.'config.inc.php'))
|
||||
exit('Rename /inc/example.config.inc.php to /inc/config.inc.php first!');
|
||||
include_once(ROOT.DS.'inc'.DS.'config.inc.php');
|
||||
|
||||
//loading core and controllers
|
||||
include_once(ROOT . DS . 'inc' . DS. 'core.php');
|
||||
//load external things if existing
|
||||
if(file_exists(ROOT.'/lib/vendor/autoload.php'))
|
||||
require ROOT.'/lib/vendor/autoload.php';
|
||||
loadAllContentControllers();
|
||||
|
||||
// check if client has permission to upload
|
||||
executeUploadPermission();
|
||||
|
||||
// check write permissions first
|
||||
if(!isFolderWritable(getDataDir()))
|
||||
exit(json_encode(array('status'=>'err','reason'=>'Data directory not writable')));
|
||||
else if(!isFolderWritable(ROOT.DS.'tmp'))
|
||||
exit(json_encode(array('status'=>'err','reason'=>'Temp directory not writable')));
|
||||
|
||||
$hash = sanatizeString(trim($_REQUEST['hash']))?sanatizeString(trim($_REQUEST['hash'])):false;
|
||||
|
||||
// check for POSTed text
|
||||
if($_REQUEST['base64'])
|
||||
{
|
||||
$data = $_REQUEST['base64'];
|
||||
$format = $_REQUEST['format'];
|
||||
|
||||
$tmpfile = ROOT.DS.'tmp'.DS.md5(rand(0,10000).time()).time();
|
||||
|
||||
base64ToFile($data, $tmpfile);
|
||||
|
||||
|
||||
//get the file type
|
||||
$type = getTypeOfFile($tmpfile);
|
||||
|
||||
//check for duplicates
|
||||
$sha1 = sha1_file($tmpfile);
|
||||
$ehash = sha1Exists($sha1);
|
||||
if($ehash && file_exists(getDataDir().DS.$ehash.DS.$ehash))
|
||||
exit(json_encode(array('status'=>'ok','hash'=>$ehash,'filetype'=>$type,'url'=>getURL().$ehash)));
|
||||
|
||||
|
||||
|
||||
//cross check filetype for controllers
|
||||
//
|
||||
//image?
|
||||
if(in_array($type,(new ImageController)->getRegisteredExtensions()))
|
||||
{
|
||||
$answer = (new ImageController())->handleUpload($tmpfile,$hash);
|
||||
}
|
||||
//or, a text
|
||||
else if($type=='text')
|
||||
{
|
||||
$answer = (new TextController())->handleUpload($tmpfile,$hash);
|
||||
}
|
||||
//or, a video
|
||||
else if(in_array($type,(new VideoController)->getRegisteredExtensions()))
|
||||
{
|
||||
$answer = (new VideoController())->handleUpload($tmpfile,$hash);
|
||||
}
|
||||
|
||||
if(!$answer)
|
||||
$answer = array('status'=>'err','reason'=>'Unsupported filetype','filetype'=>$type);
|
||||
|
||||
if($answer['hash'] && $answer['status']=='ok')
|
||||
{
|
||||
$answer['filetype'] = $type;
|
||||
//add this sha1 to the list
|
||||
addSha1($answer['hash'],$sha1);
|
||||
|
||||
if(getDeleteCodeOfHash($answer['hash']))
|
||||
{
|
||||
$answer['delete_code'] = getDeleteCodeOfHash($answer['hash']);
|
||||
$answer['delete_url'] = getURL().'delete_'.getDeleteCodeOfHash($answer['hash']).'/'.$answer['hash'];
|
||||
}
|
||||
|
||||
storageControllerUpload($answer['hash']);
|
||||
}
|
||||
|
||||
echo json_encode($answer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function base64_to_type($base64_string)
|
||||
{
|
||||
$data = explode(',', $base64_string);
|
||||
$data = $data[1];
|
||||
|
||||
$data = str_replace(' ','+',$data);
|
||||
$data = base64_decode($data);
|
||||
|
||||
$info = getimagesizefromstring($data);
|
||||
|
||||
|
||||
|
||||
trigger_error("########## FILETYPE: ".$info['mime']);
|
||||
|
||||
|
||||
$f = finfo_open();
|
||||
$type = finfo_buffer($f, $data, FILEINFO_MIME_TYPE);
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
function base64ToFile($base64_string, $output_file)
|
||||
{
|
||||
$data = explode(',', $base64_string);
|
||||
$data = $data[1];
|
||||
$data = str_replace(' ','+',$data);
|
||||
$data = base64_decode($data);
|
||||
$ifp = fopen( $output_file, 'wb' );
|
||||
fwrite( $ifp, $data );
|
||||
fclose( $ifp );
|
||||
}
|
||||
128
api/geturl.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
// basic path definitions
|
||||
define('DS', DIRECTORY_SEPARATOR);
|
||||
define('ROOT', dirname(__FILE__).'/..');
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
//loading default settings if exist
|
||||
if(!file_exists(ROOT.DS.'inc'.DS.'config.inc.php'))
|
||||
exit('Rename /inc/example.config.inc.php to /inc/config.inc.php first!');
|
||||
include_once(ROOT.DS.'inc'.DS.'config.inc.php');
|
||||
|
||||
//loading core and controllers
|
||||
include_once(ROOT . DS . 'inc' . DS. 'core.php');
|
||||
//load external things if existing
|
||||
if(file_exists(ROOT.'/lib/vendor/autoload.php'))
|
||||
require ROOT.'/lib/vendor/autoload.php';
|
||||
loadAllContentControllers();
|
||||
|
||||
// check if client has permission to upload
|
||||
executeUploadPermission();
|
||||
|
||||
// check write permissions first
|
||||
if(!isFolderWritable(getDataDir()))
|
||||
exit(json_encode(array('status'=>'err','reason'=>'Data directory not writable')));
|
||||
else if(!isFolderWritable(ROOT.DS.'tmp'))
|
||||
exit(json_encode(array('status'=>'err','reason'=>'Temp directory not writable')));
|
||||
|
||||
$hash = sanatizeString(trim($_REQUEST['hash']))?sanatizeString(trim($_REQUEST['hash'])):false;
|
||||
|
||||
$url = trim($_REQUEST['url']);
|
||||
|
||||
if(checkURLForPrivateIPRange($url))
|
||||
exit(json_encode(array('status'=>'err','reason'=>'Private IP range')));
|
||||
|
||||
if(!$url || !startsWith($url, 'http'))
|
||||
exit(json_encode(array('status'=>'err','reason'=>'Invalid URL')));
|
||||
|
||||
//@todo: let user decide max upload size via config and set php_ini var
|
||||
else if(remote_filesize($url)*0.000001 > 20)
|
||||
exit(json_encode(array('status'=>'err','reason'=>'File too big. 20MB max')));
|
||||
|
||||
$name = basename($url);
|
||||
$tmpfile = ROOT.DS.'tmp'.DS.$name;
|
||||
|
||||
$context = stream_context_create(
|
||||
array(
|
||||
"http" => array(
|
||||
"follow_location" => false,
|
||||
),
|
||||
)
|
||||
);
|
||||
file_put_contents($tmpfile,file_get_contents($url, false, $context));
|
||||
|
||||
$type = getTypeOfFile($tmpfile);
|
||||
|
||||
//check for duplicates
|
||||
$sha1 = sha1_file($tmpfile);
|
||||
$ehash = sha1Exists($sha1);
|
||||
if($ehash && file_exists(getDataDir().DS.$ehash.DS.$ehash))
|
||||
exit(json_encode(array('status'=>'ok','hash'=>$ehash,'filetype'=>$type,'url'=>getURL().$ehash)));
|
||||
|
||||
//cross check filetype for controllers
|
||||
//
|
||||
//image?
|
||||
if(in_array($type,(new ImageController)->getRegisteredExtensions()))
|
||||
{
|
||||
$answer = (new ImageController())->handleUpload($tmpfile,$hash);
|
||||
}
|
||||
//or, a text
|
||||
else if($type=='text')
|
||||
{
|
||||
$answer = (new TextController())->handleUpload($tmpfile,$hash);
|
||||
}
|
||||
//or, a video
|
||||
else if(in_array($type,(new VideoController)->getRegisteredExtensions()))
|
||||
{
|
||||
$answer = (new VideoController())->handleUpload($tmpfile,$hash);
|
||||
}
|
||||
|
||||
if(!$answer)
|
||||
$answer = array('status'=>'err','reason'=>'Unsupported filetype','filetype'=>$type);
|
||||
|
||||
if($answer['hash'] && $answer['status']=='ok')
|
||||
{
|
||||
$answer['filetype'] = $type;
|
||||
//add this sha1 to the list
|
||||
addSha1($answer['hash'],$sha1);
|
||||
|
||||
if(getDeleteCodeOfHash($answer['hash']))
|
||||
{
|
||||
$answer['delete_code'] = getDeleteCodeOfHash($answer['hash']);
|
||||
$answer['delete_url'] = getURL().'delete_'.getDeleteCodeOfHash($answer['hash']).'/'.$answer['hash'];
|
||||
}
|
||||
|
||||
|
||||
storageControllerUpload($answer['hash']);
|
||||
}
|
||||
|
||||
if($answer['hash'] && $answer['status']=='ok')
|
||||
{
|
||||
//add this sha1 to the list
|
||||
addSha1($answer['hash'],$sha1);
|
||||
|
||||
if(getDeleteCodeOfHash($answer['hash']))
|
||||
{
|
||||
$answer['delete_code'] = getDeleteCodeOfHash($answer['hash']);
|
||||
$answer['delete_url'] = getURL().'delete_'.getDeleteCodeOfHash($answer['hash']).'/'.$answer['hash'];
|
||||
}
|
||||
|
||||
storageControllerUpload($answer['hash']);
|
||||
}
|
||||
|
||||
echo json_encode($answer);
|
||||
|
||||
|
||||
|
||||
function remote_filesize($url) {
|
||||
static $regex = '/^Content-Length: *+\K\d++$/im';
|
||||
if (!$fp = @fopen($url, 'rb'))
|
||||
return false;
|
||||
if (
|
||||
isset($http_response_header) &&
|
||||
preg_match($regex, implode("\n", $http_response_header), $matches)
|
||||
)
|
||||
return (int)$matches[0];
|
||||
return strlen(stream_get_contents($fp));
|
||||
}
|
||||
53
api/info.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
// basic path definitions
|
||||
define('DS', DIRECTORY_SEPARATOR);
|
||||
define('ROOT', dirname(__FILE__).'/..');
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
//loading default settings if exist
|
||||
if(!file_exists(ROOT.DS.'inc'.DS.'config.inc.php'))
|
||||
exit('Rename /inc/example.config.inc.php to /inc/config.inc.php first!');
|
||||
include_once(ROOT.DS.'inc'.DS.'config.inc.php');
|
||||
|
||||
//loading core and controllers
|
||||
include_once(ROOT . DS . 'inc' . DS. 'core.php');
|
||||
//load external things if existing
|
||||
if(file_exists(ROOT.'/lib/vendor/autoload.php'))
|
||||
require ROOT.'/lib/vendor/autoload.php';
|
||||
|
||||
if($_REQUEST['ip']=='pls') exit(getUserIP());
|
||||
|
||||
loadAllContentControllers();
|
||||
|
||||
$hash = $_REQUEST['hash'];
|
||||
|
||||
if(!isExistingHash($hash))
|
||||
{
|
||||
exit(json_encode(array('status'=>'err','reason'=>'File not found')));
|
||||
}
|
||||
else
|
||||
{
|
||||
$answer = getInfoAboutHash($hash);
|
||||
$answer['status'] = 'ok';
|
||||
exit(json_encode($answer));
|
||||
}
|
||||
|
||||
|
||||
function getInfoAboutHash($hash)
|
||||
{
|
||||
$file = getDataDir().DS.$hash.DS.$hash;
|
||||
if(!file_exists($file))
|
||||
return array('status'=>'err','reason'=>'File not found');
|
||||
$size = filesize($file);
|
||||
$size_hr = renderSize($size);
|
||||
$content_type = exec("file -bi " . escapeshellarg($file));
|
||||
if($content_type && strpos($content_type,'/')!==false && strpos($content_type,';')!==false)
|
||||
{
|
||||
$type = $content_type;
|
||||
$c = explode(';',$type);
|
||||
$type = $c[0];
|
||||
}
|
||||
|
||||
return array('hash'=>$hash,'size_bytes'=>$size,'size_interpreted'=>$size_hr,'type'=>$type,'type_interpreted'=>getTypeOfFile($file));
|
||||
}
|
||||
47
api/pastebin.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
// basic path definitions
|
||||
define('DS', DIRECTORY_SEPARATOR);
|
||||
define('ROOT', dirname(__FILE__).'/..');
|
||||
|
||||
//loading default settings if exist
|
||||
if(!file_exists(ROOT.DS.'inc'.DS.'config.inc.php'))
|
||||
exit('Rename /inc/example.config.inc.php to /inc/config.inc.php first!');
|
||||
include_once(ROOT.DS.'inc'.DS.'config.inc.php');
|
||||
|
||||
//loading core and controllers
|
||||
include_once(ROOT . DS . 'inc' . DS. 'core.php');
|
||||
//load external things if existing
|
||||
if(file_exists(ROOT.'/lib/vendor/autoload.php'))
|
||||
require ROOT.'/lib/vendor/autoload.php';
|
||||
$controllers = loadAllContentControllers();
|
||||
if(!in_array('TextController',$controllers))
|
||||
exit(json_encode(array('status'=>'err','reason'=>'Text controller not enabled')));
|
||||
|
||||
// check if client has permission to upload
|
||||
executeUploadPermission();
|
||||
|
||||
// check write permissions first
|
||||
if(!isFolderWritable(getDataDir()))
|
||||
exit(json_encode(array('status'=>'err','reason'=>'Data directory not writable')));
|
||||
else if(!isFolderWritable(ROOT.DS.'tmp'))
|
||||
exit(json_encode(array('status'=>'err','reason'=>'Temp directory not writable')));
|
||||
|
||||
// check for POSTed text
|
||||
if($_REQUEST['api_paste_code'])
|
||||
{
|
||||
$hash = getNewHash('txt',$length=10);
|
||||
$tmpfile = ROOT.DS.'tmp'.DS.$hash;
|
||||
file_put_contents($tmpfile,$_REQUEST['api_paste_code']);
|
||||
|
||||
//check if this exact paste already exists
|
||||
$sha1 = sha1_file($tmpfile);
|
||||
$sha_hash = sha1Exists($sha1);
|
||||
if($sha_hash)
|
||||
exit(getURL().$sha_hash);
|
||||
|
||||
$answer = (new TextController())->handleUpload($tmpfile,$hash);
|
||||
if($answer['hash'] && $answer['status']=='ok')
|
||||
addSha1($answer['hash'],$sha1);
|
||||
|
||||
echo getURL().$hash;
|
||||
}
|
||||
98
api/upload.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
// basic path definitions
|
||||
define('DS', DIRECTORY_SEPARATOR);
|
||||
define('ROOT', dirname(__FILE__).DS.'..');
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
//loading default settings if exist
|
||||
if(!file_exists(ROOT.DS.'inc'.DS.'config.inc.php'))
|
||||
exit('Rename /inc/example.config.inc.php to /inc/config.inc.php first!');
|
||||
include_once(ROOT.DS.'inc'.DS.'config.inc.php');
|
||||
|
||||
//loading core and controllers
|
||||
include_once(ROOT . DS . 'inc' . DS. 'core.php');
|
||||
//load external things if existing
|
||||
if(file_exists(ROOT.'/lib/vendor/autoload.php'))
|
||||
require ROOT.'/lib/vendor/autoload.php';
|
||||
$allowedcontentcontrollers = loadAllContentControllers();
|
||||
|
||||
// check write permissions first
|
||||
if(!isFolderWritable(getDataDir()))
|
||||
exit(json_encode(array('status'=>'err','reason'=>'Data directory not writable')));
|
||||
else if(!isFolderWritable(ROOT.DS.'tmp'))
|
||||
exit(json_encode(array('status'=>'err','reason'=>'Temp directory not writable')));
|
||||
|
||||
// check if client has permission to upload
|
||||
executeUploadPermission();
|
||||
|
||||
if(isset($_REQUEST['hash']))
|
||||
$hash = sanatizeString(trim($_REQUEST['hash']));
|
||||
else
|
||||
$hash = false;
|
||||
|
||||
// check for POST upload
|
||||
if ($_FILES['file']["error"] == UPLOAD_ERR_OK)
|
||||
{
|
||||
//get the file type
|
||||
$type = getTypeOfFile($_FILES['file']["tmp_name"]);
|
||||
|
||||
//check for duplicates
|
||||
$sha1 = sha1_file($_FILES['file']["tmp_name"]);
|
||||
$ehash = sha1Exists($sha1);
|
||||
if($ehash && file_exists(getDataDir().DS.$ehash.DS.$ehash))
|
||||
exit(json_encode(array('status'=>'ok','hash'=>$ehash,'filetype'=>$type,'url'=>getURL().$ehash)));
|
||||
|
||||
//cross check filetype for controllers
|
||||
//
|
||||
//image?
|
||||
|
||||
foreach($allowedcontentcontrollers as $cc)
|
||||
{
|
||||
if(in_array($type,(new $cc)->getRegisteredExtensions()))
|
||||
{
|
||||
$answer = (new $cc())->handleUpload($_FILES['file']['tmp_name'],$hash);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if(in_array($type,(new ImageController)->getRegisteredExtensions()))
|
||||
{
|
||||
$answer = (new ImageController())->handleUpload($_FILES['file']['tmp_name'],$hash);
|
||||
}
|
||||
|
||||
//or, a text
|
||||
else if($type=='text')
|
||||
{
|
||||
$answer = (new TextController())->handleUpload($_FILES['file']['tmp_name'],$hash);
|
||||
}
|
||||
//or, a video
|
||||
else if(in_array($type,(new VideoController)->getRegisteredExtensions()))
|
||||
{
|
||||
$answer = (new VideoController())->handleUpload($_FILES['file']['tmp_name'],$hash);
|
||||
}
|
||||
*/
|
||||
if(!$answer)
|
||||
$answer = array('status'=>'err','reason'=>'Unsupported filetype: '.$type,'filetype'=>$type);
|
||||
|
||||
if($answer['hash'] && $answer['status']=='ok')
|
||||
{
|
||||
$answer['filetype'] = $type;
|
||||
//add this sha1 to the list
|
||||
addSha1($answer['hash'],$sha1);
|
||||
|
||||
if(getDeleteCodeOfHash($answer['hash']))
|
||||
{
|
||||
$answer['delete_code'] = getDeleteCodeOfHash($answer['hash']);
|
||||
$answer['delete_url'] = getURL().'delete_'.getDeleteCodeOfHash($answer['hash']).'/'.$answer['hash'];
|
||||
}
|
||||
|
||||
|
||||
storageControllerUpload($answer['hash']);
|
||||
}
|
||||
|
||||
echo json_encode($answer);
|
||||
}
|
||||
else
|
||||
exit(json_encode(array('status'=>'err','reason'=>'Upload error')));
|
||||
54
backend.php
@@ -1,54 +0,0 @@
|
||||
<?php
|
||||
session_cache_limiter("public");
|
||||
$expiry = 90; //days
|
||||
session_cache_expire($expiry * 24 * 60);
|
||||
session_start();
|
||||
define('DS', DIRECTORY_SEPARATOR);
|
||||
define('ROOT', dirname(__FILE__));
|
||||
define('PATH',((dirname($_SERVER['PHP_SELF'])=='/'||dirname($_SERVER['PHP_SELF'])=='\\'||dirname($_SERVER['PHP_SELF'])=='/index.php'||dirname($_SERVER['PHP_SELF'])=='/backend.php')?'/':dirname($_SERVER['PHP_SELF']).'/'));
|
||||
|
||||
if(!file_exists(ROOT.DS.'inc'.DS.'config.inc.php'))
|
||||
exit('Rename /inc/example.config.inc.php to /inc/config.inc.php first!');
|
||||
include_once(ROOT.DS.'inc'.DS.'config.inc.php');
|
||||
|
||||
if(FORCE_DOMAIN)
|
||||
define('DOMAINPATH',FORCE_DOMAIN);
|
||||
else
|
||||
define('DOMAINPATH',(isset($_SERVER['HTTPS'])?'https':'http').'://'.$_SERVER['HTTP_HOST']);
|
||||
error_reporting(E_ALL & ~E_NOTICE);
|
||||
if(SHOW_ERRORS)
|
||||
ini_set('display_errors','On');
|
||||
else ini_set('display_errors','Off');
|
||||
|
||||
include_once(ROOT.DS.'inc'.DS.'core.php');
|
||||
|
||||
$pm = new PictshareModel();
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
if(UPLOAD_CODE!=false && !$pm->uploadCodeExists($_REQUEST['upload_code']))
|
||||
exit(json_encode(array('status'=>'ERR','reason'=>'Wrong upload code provided')));
|
||||
|
||||
if($_REQUEST['getimage'])
|
||||
{
|
||||
$url = $_REQUEST['getimage'];
|
||||
|
||||
echo json_encode($pm->uploadImageFromURL($url));
|
||||
}
|
||||
else if($_FILES['postimage'])
|
||||
{
|
||||
$image = $_FILES['postimage'];
|
||||
echo json_encode($pm->processSingleUpload($file,'postimage'));
|
||||
}
|
||||
else if($_REQUEST['base64'])
|
||||
{
|
||||
$data = $_REQUEST['base64'];
|
||||
$format = $_REQUEST['format'];
|
||||
echo json_encode($pm->uploadImageFromBase64($data,$format));
|
||||
}
|
||||
else if($_REQUEST['geturlinfo'])
|
||||
echo json_encode($pm->getURLInfo($_REQUEST['geturlinfo']));
|
||||
else if($_REQUEST['a']=='oembed')
|
||||
echo json_encode($pm->oembed($_REQUEST['url'],$_REQUEST['t']));
|
||||
else
|
||||
echo json_encode(array('status'=>'ERR','reason'=>'NO_VALID_COMMAND'));
|
||||
BIN
bin/ffmpeg
@@ -1,275 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Backblaze B2 wrapper without external depenecies
|
||||
*
|
||||
* @author Christian Haschek <christian@haschek.at>
|
||||
*/
|
||||
|
||||
class Backblaze
|
||||
{
|
||||
private $token;
|
||||
private $apiURL;
|
||||
private $bucket;
|
||||
private $dlURL;
|
||||
private $ulURL;
|
||||
private $ulToken;
|
||||
private $bucket_name;
|
||||
private $files;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
if( BACKBLAZE !== true || !defined('BACKBLAZE_ID') || !defined('BACKBLAZE_KEY') || !defined('BACKBLAZE_BUCKET_ID'))
|
||||
return;
|
||||
$this->authorize();
|
||||
$this->bucket = BACKBLAZE_BUCKET_ID;
|
||||
$this->bucket_name = (( defined('BACKBLAZE_BUCKET_NAME') && BACKBLAZE_BUCKET_NAME != "")?BACKBLAZE_BUCKET_NAME:$this->bucketIdToName($bucket));
|
||||
}
|
||||
|
||||
function authorize()
|
||||
{
|
||||
$account_id = BACKBLAZE_ID; // Obtained from your B2 account page
|
||||
$application_key = BACKBLAZE_KEY; // Obtained from your B2 account page
|
||||
$credentials = base64_encode($account_id . ":" . $application_key);
|
||||
$url = "https://api.backblazeb2.com/b2api/v1/b2_authorize_account";
|
||||
|
||||
$session = curl_init($url);
|
||||
|
||||
// Add headers
|
||||
$headers = array();
|
||||
$headers[] = "Accept: application/json";
|
||||
$headers[] = "Authorization: Basic " . $credentials;
|
||||
curl_setopt($session, CURLOPT_HTTPHEADER, $headers); // Add headers
|
||||
|
||||
curl_setopt($session, CURLOPT_HTTPGET, true); // HTTP GET
|
||||
curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // Receive server response
|
||||
$server_output = curl_exec($session);
|
||||
curl_close ($session);
|
||||
$data = json_decode($server_output,true);
|
||||
|
||||
$this->token = $data['authorizationToken'];
|
||||
$this->apiURL = $data['apiUrl'];
|
||||
$this->dlURL = $data['downloadUrl'];
|
||||
}
|
||||
|
||||
function upload($hash)
|
||||
{
|
||||
if(!$this->ulURL)
|
||||
$this->getUploadInfo();
|
||||
$file_name = $hash;
|
||||
$my_file = ROOT.DS.'upload'.DS.$hash.DS.$hash;
|
||||
$handle = fopen($my_file, 'r');
|
||||
$read_file = fread($handle,filesize($my_file));
|
||||
|
||||
$upload_url = $this->ulURL; // Provided by b2_get_upload_url
|
||||
$upload_auth_token = $this->ulToken; // Provided by b2_get_upload_url
|
||||
$bucket_id = $this->bucket; // The ID of the bucket
|
||||
$content_type = "text/plain";
|
||||
$sha1_of_file_data = sha1_file($my_file);
|
||||
|
||||
$session = curl_init($upload_url);
|
||||
|
||||
// Add read file as post field
|
||||
curl_setopt($session, CURLOPT_POSTFIELDS, $read_file);
|
||||
|
||||
// Add headers
|
||||
$headers = array();
|
||||
$headers[] = "Authorization: " . $upload_auth_token;
|
||||
$headers[] = "X-Bz-File-Name: " . $file_name;
|
||||
$headers[] = "Content-Type: " . $content_type;
|
||||
$headers[] = "X-Bz-Content-Sha1: " . $sha1_of_file_data;
|
||||
curl_setopt($session, CURLOPT_HTTPHEADER, $headers);
|
||||
|
||||
curl_setopt($session, CURLOPT_POST, true); // HTTP POST
|
||||
curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // Receive server response
|
||||
$server_output = curl_exec($session); // Let's do this!
|
||||
curl_close ($session); // Clean up
|
||||
//var_dump($server_output); // Tell me about the rabbits, George!
|
||||
}
|
||||
|
||||
function getUploadInfo()
|
||||
{
|
||||
$api_url = $this->apiURL; // From b2_authorize_account call
|
||||
$auth_token = $this->token; // From b2_authorize_account call
|
||||
$bucket_id = $this->bucket; // The ID of the bucket you want to upload to
|
||||
|
||||
$session = curl_init($api_url . "/b2api/v1/b2_get_upload_url");
|
||||
|
||||
// Add post fields
|
||||
$data = array("bucketId" => $bucket_id);
|
||||
$post_fields = json_encode($data);
|
||||
curl_setopt($session, CURLOPT_POSTFIELDS, $post_fields);
|
||||
|
||||
// Add headers
|
||||
$headers = array();
|
||||
$headers[] = "Authorization: " . $auth_token;
|
||||
curl_setopt($session, CURLOPT_HTTPHEADER, $headers);
|
||||
|
||||
curl_setopt($session, CURLOPT_POST, true); // HTTP POST
|
||||
curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // Receive server response
|
||||
$server_output = curl_exec($session); // Let's do this!
|
||||
curl_close ($session); // Clean up
|
||||
$data = json_decode($server_output,true); // Tell me about the rabbits, George!
|
||||
$this->ulURL = $data['uploadUrl'];
|
||||
$this->ulToken = $data['authorizationToken'];
|
||||
}
|
||||
|
||||
function download($hash)
|
||||
{
|
||||
if(file_exists(ROOT.DS.'upload'.DS.$hash.DS.$hash)) return false;
|
||||
$download_url = $this->dlURL; // From b2_authorize_account call
|
||||
$bucket_name = $this->bucket_name; // The NAME of the bucket you want to download from
|
||||
$file_name = $hash; // The name of the file you want to download
|
||||
$auth_token = $this->token; // From b2_authorize_account call
|
||||
$uri = $download_url . "/file/" . $bucket_name . "/" . $file_name;
|
||||
|
||||
$session = curl_init($uri);
|
||||
|
||||
// Add headers
|
||||
$headers = array();
|
||||
$headers[] = "Authorization: " . $auth_token;
|
||||
curl_setopt($session, CURLOPT_HTTPHEADER, $headers);
|
||||
|
||||
curl_setopt($session, CURLOPT_HTTPGET, true); // HTTP POST
|
||||
curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // Receive server response
|
||||
$server_output = curl_exec($session); // Let's do this!
|
||||
curl_close ($session); // Clean up
|
||||
$is_binary = preg_match('~[^\x20-\x7E\t\r\n]~', $server_output); // Tell me about the rabbits, George!
|
||||
if(!$is_binary) return false;
|
||||
|
||||
mkdir(ROOT.DS.'upload'.DS.$hash);
|
||||
$file = ROOT.DS.'upload'.DS.$hash.DS.$hash;
|
||||
|
||||
file_put_contents($file, $server_output);
|
||||
return true;
|
||||
}
|
||||
|
||||
function bucketIdToName($bucket)
|
||||
{
|
||||
$api_url = $this->apiURL; // From b2_authorize_account call
|
||||
$auth_token = $this->token; // From b2_authorize_account call
|
||||
$account_id = BACKBLAZE_ID;
|
||||
|
||||
$session = curl_init($api_url . "/b2api/v1/b2_list_buckets");
|
||||
|
||||
// Add post fields
|
||||
$data = array("accountId" => $account_id);
|
||||
$post_fields = json_encode($data);
|
||||
curl_setopt($session, CURLOPT_POSTFIELDS, $post_fields);
|
||||
|
||||
// Add headers
|
||||
$headers = array();
|
||||
$headers[] = "Authorization: " . $auth_token;
|
||||
curl_setopt($session, CURLOPT_HTTPHEADER, $headers);
|
||||
|
||||
curl_setopt($session, CURLOPT_POST, true); // HTTP POST
|
||||
curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // Receive server response
|
||||
$server_output = curl_exec($session); // Let's do this!
|
||||
curl_close ($session); // Clean up
|
||||
$data = json_decode($server_output,true); // Tell me about the rabbits, George!
|
||||
if(is_array($data))
|
||||
foreach($data['buckets'] as $bucket)
|
||||
{
|
||||
if($bucket['bucketId']==$this->bucket) return $bucket['bucketName'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function deleteFile($hash,$file_id=false)
|
||||
{
|
||||
$api_url = $this->apiURL; // From b2_authorize_account call
|
||||
$auth_token = $this->token; // From b2_authorize_account call
|
||||
$file_name = $hash; // The file name of the file you want to delete
|
||||
if(!$file_id)
|
||||
$file_id = $this->fileExistsInBucket($hash);
|
||||
|
||||
$session = curl_init($api_url . "/b2api/v1/b2_delete_file_version");
|
||||
|
||||
// Add post fields
|
||||
$data = array("fileId" => $file_id, "fileName" => $file_name);
|
||||
$post_fields = json_encode($data);
|
||||
curl_setopt($session, CURLOPT_POSTFIELDS, $post_fields);
|
||||
|
||||
// Add headers
|
||||
$headers = array();
|
||||
$headers[] = "Authorization: " . $auth_token;
|
||||
curl_setopt($session, CURLOPT_HTTPHEADER, $headers);
|
||||
|
||||
curl_setopt($session, CURLOPT_POST, true); // HTTP POST
|
||||
curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // Receive server response
|
||||
$server_output = curl_exec($session); // Let's do this!
|
||||
curl_close ($session); // Clean up
|
||||
}
|
||||
|
||||
function fileExistsInBucket($hash)
|
||||
{
|
||||
$api_url = $this->apiURL; // From b2_authorize_account call
|
||||
$auth_token = $this->token; // From b2_authorize_account call
|
||||
$bucket_id = $this->bucket; // The ID of the bucket
|
||||
|
||||
$session = curl_init($api_url . "/b2api/v1/b2_list_file_names");
|
||||
|
||||
// Add post fields
|
||||
$data = array("bucketId" => $bucket_id,
|
||||
"startFileName" => $hash);
|
||||
$post_fields = json_encode($data);
|
||||
curl_setopt($session, CURLOPT_POSTFIELDS, $post_fields);
|
||||
|
||||
// Add headers
|
||||
$headers = array();
|
||||
$headers[] = "Authorization: " . $auth_token;
|
||||
curl_setopt($session, CURLOPT_HTTPHEADER, $headers);
|
||||
|
||||
curl_setopt($session, CURLOPT_POST, true); // HTTP POST
|
||||
curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // Receive server response
|
||||
$server_output = curl_exec($session); // Let's do this!
|
||||
curl_close ($session); // Clean up
|
||||
$data = json_decode($server_output,true);
|
||||
|
||||
foreach($data['files'] as $file)
|
||||
{
|
||||
//it's either the first one or it doesn't exist
|
||||
if($file['fileName']==$hash)
|
||||
return $file['fileId'];
|
||||
else return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function getAllFilesInBucket($startFileName=null)
|
||||
{
|
||||
$api_url = $this->apiURL; // From b2_authorize_account call
|
||||
$auth_token = $this->token; // From b2_authorize_account call
|
||||
$bucket_id = $this->bucket; // The ID of the bucket
|
||||
|
||||
$session = curl_init($api_url . "/b2api/v1/b2_list_file_names");
|
||||
|
||||
// Add post fields
|
||||
$data = array("bucketId" => $bucket_id,
|
||||
"startFileName" => $startFileName);
|
||||
$post_fields = json_encode($data);
|
||||
curl_setopt($session, CURLOPT_POSTFIELDS, $post_fields);
|
||||
|
||||
// Add headers
|
||||
$headers = array();
|
||||
$headers[] = "Authorization: " . $auth_token;
|
||||
curl_setopt($session, CURLOPT_HTTPHEADER, $headers);
|
||||
|
||||
curl_setopt($session, CURLOPT_POST, true); // HTTP POST
|
||||
curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // Receive server response
|
||||
$server_output = curl_exec($session); // Let's do this!
|
||||
curl_close ($session); // Clean up
|
||||
$data = json_decode($server_output,true);
|
||||
|
||||
foreach($data['files'] as $file)
|
||||
{
|
||||
$name = $file['fileName'];
|
||||
$id = $file['fileId'];
|
||||
$this->files[$name] = $id;
|
||||
}
|
||||
|
||||
if($data['nextFileName'])
|
||||
$this->getAllFilesInBucket($data['nextFileName']);
|
||||
}
|
||||
}
|
||||
@@ -1,220 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Filter
|
||||
{
|
||||
/**
|
||||
* @var resource
|
||||
*/
|
||||
|
||||
private $image;
|
||||
|
||||
/**
|
||||
* Directory for image assets.
|
||||
* @var string
|
||||
*/
|
||||
|
||||
private $assetDirectory;
|
||||
|
||||
/**
|
||||
* run constructor
|
||||
* @param resource &$image GD image resource
|
||||
*/
|
||||
|
||||
public function __construct(&$image)
|
||||
{
|
||||
$this->image = $image;
|
||||
|
||||
$this->assetDirectory = dirname(dirname(dirname(__FILE__))) . '/assets/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current image resource
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
|
||||
public function getImage()
|
||||
{
|
||||
return $this->image;
|
||||
}
|
||||
|
||||
public function bubbles()
|
||||
{
|
||||
$dest = imagecreatefromjpeg($this->assetDirectory . "pattern4.jpg");
|
||||
|
||||
$x = imagesx($this->image);
|
||||
$y = imagesy($this->image);
|
||||
|
||||
$x2 = imagesx($dest);
|
||||
$y2 = imagesy($dest);
|
||||
|
||||
$thumb = imagecreatetruecolor($x, $y);
|
||||
imagecopyresampled($thumb, $dest, 0, 0, 0, 0, $x, $y, $x2, $y2);
|
||||
|
||||
imagecopymerge($this->image, $thumb, 0, 0, 0, 0, $x, $y, 20);
|
||||
imagefilter($this->image, IMG_FILTER_BRIGHTNESS, 40);
|
||||
imagefilter($this->image, IMG_FILTER_CONTRAST, -10);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function colorise()
|
||||
{
|
||||
$dest = imagecreatefromjpeg($this->assetDirectory . "pattern5.jpg");
|
||||
|
||||
$x = imagesx($this->image);
|
||||
$y = imagesy($this->image);
|
||||
|
||||
$x2 = imagesx($dest);
|
||||
$y2 = imagesy($dest);
|
||||
|
||||
$thumb = imagecreatetruecolor($x, $y);
|
||||
imagecopyresampled($thumb, $dest, 0, 0, 0, 0, $x, $y, $x2, $y2);
|
||||
|
||||
imagecopymerge($this->image, $thumb, 0, 0, 0, 0, $x, $y, 40);
|
||||
imagefilter($this->image, IMG_FILTER_CONTRAST, -25);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function sepia()
|
||||
{
|
||||
imagefilter($this->image, IMG_FILTER_GRAYSCALE);
|
||||
imagefilter($this->image, IMG_FILTER_COLORIZE, 100, 50, 0);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function sharpen()
|
||||
{
|
||||
$gaussian = array(
|
||||
array(1.0, 1.0, 1.0),
|
||||
array(1.0, -7.0, 1.0),
|
||||
array(1.0, 1.0, 1.0)
|
||||
);
|
||||
imageconvolution($this->image, $gaussian, 1, 4);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function emboss()
|
||||
{
|
||||
$gaussian = array(
|
||||
array(-2.0, -1.0, 0.0),
|
||||
array(-1.0, 1.0, 1.0),
|
||||
array(0.0, 1.0, 2.0)
|
||||
);
|
||||
|
||||
imageconvolution($this->image, $gaussian, 1, 5);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function cool()
|
||||
{
|
||||
imagefilter($this->image, IMG_FILTER_MEAN_REMOVAL);
|
||||
imagefilter($this->image, IMG_FILTER_CONTRAST, -50);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function old2()
|
||||
{
|
||||
$dest = imagecreatefromjpeg($this->assetDirectory . "pattern1.jpg");
|
||||
|
||||
$x = imagesx($this->image);
|
||||
$y = imagesy($this->image);
|
||||
|
||||
$x2 = imagesx($dest);
|
||||
$y2 = imagesy($dest);
|
||||
|
||||
$thumb = imagecreatetruecolor($x, $y);
|
||||
imagecopyresampled($thumb, $dest, 0, 0, 0, 0, $x, $y, $x2, $y2);
|
||||
|
||||
imagecopymerge($this->image, $thumb, 0, 0, 0, 0, $x, $y, 40);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function old3()
|
||||
{
|
||||
imagefilter($this->image, IMG_FILTER_CONTRAST, -30);
|
||||
|
||||
$dest = imagecreatefromjpeg($this->assetDirectory . "pattern3.jpg");
|
||||
|
||||
$x = imagesx($this->image);
|
||||
$y = imagesy($this->image);
|
||||
|
||||
$x2 = imagesx($dest);
|
||||
$y2 = imagesy($dest);
|
||||
|
||||
$thumb = imagecreatetruecolor($x, $y);
|
||||
imagecopyresampled($thumb, $dest, 0, 0, 0, 0, $x, $y, $x2, $y2);
|
||||
|
||||
imagecopymerge($this->image, $thumb, 0, 0, 0, 0, $x, $y, 50);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function old()
|
||||
{
|
||||
$dest = imagecreatefromjpeg($this->assetDirectory . "bg1.jpg");
|
||||
|
||||
$x = imagesx($this->image);
|
||||
$y = imagesy($this->image);
|
||||
|
||||
$x2 = imagesx($dest);
|
||||
$y2 = imagesy($dest);
|
||||
|
||||
$thumb = imagecreatetruecolor($x, $y);
|
||||
imagecopyresampled($thumb, $dest, 0, 0, 0, 0, $x, $y, $x2, $y2);
|
||||
|
||||
imagecopymerge($this->image, $thumb, 0, 0, 0, 0, $x, $y, 30);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function light()
|
||||
{
|
||||
imagefilter($this->image, IMG_FILTER_BRIGHTNESS, 10);
|
||||
imagefilter($this->image, IMG_FILTER_COLORIZE, 100, 50, 0, 10);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function aqua()
|
||||
{
|
||||
imagefilter($this->image, IMG_FILTER_COLORIZE, 0, 70, 0, 30);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function fuzzy()
|
||||
{
|
||||
$gaussian = array(
|
||||
array(1.0, 1.0, 1.0),
|
||||
array(1.0, 1.0, 1.0),
|
||||
array(1.0, 1.0, 1.0)
|
||||
);
|
||||
|
||||
imageconvolution($this->image, $gaussian, 9, 20);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function boost()
|
||||
{
|
||||
imagefilter($this->image, IMG_FILTER_CONTRAST, -35);
|
||||
imagefilter($this->image, IMG_FILTER_BRIGHTNESS, 10);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function gray()
|
||||
{
|
||||
imagefilter($this->image, IMG_FILTER_CONTRAST, -60);
|
||||
imagefilter($this->image, IMG_FILTER_GRAYSCALE);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
class HTML {
|
||||
|
||||
/*
|
||||
* Characters that will pass:
|
||||
* a-z
|
||||
* A-Z
|
||||
* 0-9
|
||||
* .
|
||||
* _
|
||||
* -
|
||||
*/
|
||||
function sanatizeString($string)
|
||||
{
|
||||
return preg_replace("/[^a-zA-Z0-9._\-]+/", "", $string);
|
||||
}
|
||||
|
||||
function renderSize($byte)
|
||||
{
|
||||
if($byte < 1024) {
|
||||
$result = round($byte, 2). ' Byte';
|
||||
}elseif($byte < pow(1024, 2)) {
|
||||
$result = round($byte/1024, 2).' KB';
|
||||
}elseif($byte >= pow(1024, 2) and $byte < pow(1024, 3)) {
|
||||
$result = round($byte/pow(1024, 2), 2).' MB';
|
||||
}elseif($byte >= pow(1024, 3) and $byte < pow(1024, 4)) {
|
||||
$result = round($byte/pow(1024, 3), 2).' GB';
|
||||
}elseif($byte >= pow(1024, 4) and $byte < pow(1024, 5)) {
|
||||
$result = round($byte/pow(1024, 4), 2).' TB';
|
||||
}elseif($byte >= pow(1024, 5) and $byte < pow(1024, 6)) {
|
||||
$result = round($byte/pow(1024, 5), 2).' PB';
|
||||
}elseif($byte >= pow(1024, 6) and $byte < pow(1024, 7)) {
|
||||
$result = round($byte/pow(1024, 6), 2).' EB';
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,215 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Image
|
||||
{
|
||||
function rotate(&$im,$direction)
|
||||
{
|
||||
switch($direction)
|
||||
{
|
||||
case 'upside': $angle = 180;break;
|
||||
case 'left': $angle = 90;break;
|
||||
case 'right': $angle = -90;break;
|
||||
default: $angle = 0;break;
|
||||
}
|
||||
|
||||
$im = imagerotate($im,$angle,0);
|
||||
}
|
||||
|
||||
function forceResize(&$img,$size)
|
||||
{
|
||||
$pm = new PictshareModel();
|
||||
|
||||
$sd = $pm->sizeStringToWidthHeight($size);
|
||||
$maxwidth = $sd['width'];
|
||||
$maxheight = $sd['height'];
|
||||
|
||||
|
||||
|
||||
$width = imagesx($img);
|
||||
$height = imagesy($img);
|
||||
|
||||
$maxwidth = ($maxwidth>$width?$width:$maxwidth);
|
||||
$maxheight = ($maxheight>$height?$height:$maxheight);
|
||||
|
||||
|
||||
$dst_img = imagecreatetruecolor($maxwidth, $maxheight);
|
||||
$src_img = $img;
|
||||
|
||||
$palsize = ImageColorsTotal($img);
|
||||
for ($i = 0; $i < $palsize; $i++)
|
||||
{
|
||||
$colors = ImageColorsForIndex($img, $i);
|
||||
ImageColorAllocate($dst_img, $colors['red'], $colors['green'], $colors['blue']);
|
||||
}
|
||||
|
||||
imagefill($dst_img, 0, 0, IMG_COLOR_TRANSPARENT);
|
||||
imagesavealpha($dst_img,true);
|
||||
imagealphablending($dst_img, true);
|
||||
|
||||
$width_new = $height * $maxwidth / $maxheight;
|
||||
$height_new = $width * $maxheight / $maxwidth;
|
||||
//if the new width is greater than the actual width of the image, then the height is too large and the rest cut off, or vice versa
|
||||
if($width_new > $width){
|
||||
//cut point by height
|
||||
$h_point = (($height - $height_new) / 2);
|
||||
//copy image
|
||||
imagecopyresampled($dst_img, $src_img, 0, 0, 0, $h_point, $maxwidth, $maxheight, $width, $height_new);
|
||||
}else{
|
||||
//cut point by width
|
||||
$w_point = (($width - $width_new) / 2);
|
||||
imagecopyresampled($dst_img, $src_img, 0, 0, $w_point, 0, $maxwidth, $maxheight, $width_new, $height);
|
||||
}
|
||||
|
||||
$img = $dst_img;
|
||||
}
|
||||
|
||||
/**
|
||||
* From: https://stackoverflow.com/questions/4590441/php-thumbnail-image-resizing-with-proportions
|
||||
*/
|
||||
function resize(&$img,$size)
|
||||
{
|
||||
$pm = new PictshareModel();
|
||||
|
||||
$sd = $pm->sizeStringToWidthHeight($size);
|
||||
$maxwidth = $sd['width'];
|
||||
$maxheight = $sd['height'];
|
||||
|
||||
$width = imagesx($img);
|
||||
$height = imagesy($img);
|
||||
|
||||
if(!ALLOW_BLOATING)
|
||||
{
|
||||
if($maxwidth>$width)$maxwidth = $width;
|
||||
if($maxheight>$height)$maxheight = $height;
|
||||
}
|
||||
|
||||
if ($height > $width)
|
||||
{
|
||||
$ratio = $maxheight / $height;
|
||||
$newheight = $maxheight;
|
||||
$newwidth = $width * $ratio;
|
||||
}
|
||||
else
|
||||
{
|
||||
$ratio = $maxwidth / $width;
|
||||
$newwidth = $maxwidth;
|
||||
$newheight = $height * $ratio;
|
||||
}
|
||||
|
||||
$newimg = imagecreatetruecolor($newwidth,$newheight);
|
||||
|
||||
$palsize = ImageColorsTotal($img);
|
||||
for ($i = 0; $i < $palsize; $i++)
|
||||
{
|
||||
$colors = ImageColorsForIndex($img, $i);
|
||||
ImageColorAllocate($newimg, $colors['red'], $colors['green'], $colors['blue']);
|
||||
}
|
||||
|
||||
imagefill($newimg, 0, 0, IMG_COLOR_TRANSPARENT);
|
||||
imagesavealpha($newimg,true);
|
||||
imagealphablending($newimg, true);
|
||||
|
||||
imagecopyresampled($newimg, $img, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
|
||||
|
||||
$img = $newimg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strong Blur
|
||||
*
|
||||
* @param resource $gdImageResource
|
||||
* @param int $blurFactor optional
|
||||
* This is the strength of the blur
|
||||
* 0 = no blur, 3 = default, anything over 5 is extremely blurred
|
||||
* @return GD image resource
|
||||
* @author Martijn Frazer, idea based on http://stackoverflow.com/a/20264482
|
||||
*/
|
||||
function blur(&$gdImageResource, $blurFactor = 3)
|
||||
{
|
||||
if(!$blurFactor)
|
||||
$blurFactor = 3;
|
||||
if($blurFactor>6)
|
||||
$blurFactor = 6;
|
||||
else if($blurFactor<0)
|
||||
$blurFactor = 0;
|
||||
// blurFactor has to be an integer
|
||||
$blurFactor = round($blurFactor);
|
||||
|
||||
$originalWidth = imagesx($gdImageResource);
|
||||
$originalHeight = imagesy($gdImageResource);
|
||||
|
||||
$smallestWidth = ceil($originalWidth * pow(0.5, $blurFactor));
|
||||
$smallestHeight = ceil($originalHeight * pow(0.5, $blurFactor));
|
||||
|
||||
// for the first run, the previous image is the original input
|
||||
$prevImage = $gdImageResource;
|
||||
$prevWidth = $originalWidth;
|
||||
$prevHeight = $originalHeight;
|
||||
|
||||
// scale way down and gradually scale back up, blurring all the way
|
||||
for($i = 0; $i < $blurFactor; $i += 1)
|
||||
{
|
||||
// determine dimensions of next image
|
||||
$nextWidth = $smallestWidth * pow(2, $i);
|
||||
$nextHeight = $smallestHeight * pow(2, $i);
|
||||
|
||||
// resize previous image to next size
|
||||
$nextImage = imagecreatetruecolor($nextWidth, $nextHeight);
|
||||
imagecopyresized($nextImage, $prevImage, 0, 0, 0, 0,
|
||||
$nextWidth, $nextHeight, $prevWidth, $prevHeight);
|
||||
|
||||
// apply blur filter
|
||||
imagefilter($nextImage, IMG_FILTER_GAUSSIAN_BLUR);
|
||||
|
||||
// now the new image becomes the previous image for the next step
|
||||
$prevImage = $nextImage;
|
||||
$prevWidth = $nextWidth;
|
||||
$prevHeight = $nextHeight;
|
||||
}
|
||||
|
||||
// scale back to original size and blur one more time
|
||||
imagecopyresized($gdImageResource, $nextImage,
|
||||
0, 0, 0, 0, $originalWidth, $originalHeight, $nextWidth, $nextHeight);
|
||||
imagefilter($gdImageResource, IMG_FILTER_GAUSSIAN_BLUR);
|
||||
|
||||
// clean up
|
||||
imagedestroy($prevImage);
|
||||
|
||||
// return result
|
||||
return $gdImageResource;
|
||||
}
|
||||
|
||||
function filter(&$im,$vars)
|
||||
{
|
||||
|
||||
foreach($vars as $var)
|
||||
{
|
||||
if(strpos($var,'_'))
|
||||
{
|
||||
$a = explode('_',$var);
|
||||
$var = $a[0];
|
||||
$val = $a[1];
|
||||
}
|
||||
switch($var)
|
||||
{
|
||||
case 'negative': imagefilter($im,IMG_FILTER_NEGATE); break;
|
||||
case 'grayscale': imagefilter($im,IMG_FILTER_GRAYSCALE); break;
|
||||
case 'brightness': imagefilter($im,IMG_FILTER_BRIGHTNESS,$val); break;
|
||||
case 'edgedetect': imagefilter($im,IMG_FILTER_EDGEDETECT); break;
|
||||
case 'smooth': imagefilter($im,IMG_FILTER_SMOOTH,$val); break;
|
||||
case 'contrast': imagefilter($im,IMG_FILTER_CONTRAST,$val); break;
|
||||
case 'pixelate': imagefilter($im,IMG_FILTER_PIXELATE,$val); break;
|
||||
case 'blur': $this->blur($im,$val); break;
|
||||
case 'sepia': (new Filter($im))->sepia()->getImage();break;
|
||||
case 'sharpen':(new Filter($im))->sharpen()->getImage();break;
|
||||
case 'emboss':(new Filter($im))->emboss()->getImage();break;
|
||||
case 'cool':(new Filter($im))->cool()->getImage();break;
|
||||
case 'light':(new Filter($im))->light()->getImage();break;
|
||||
case 'aqua':(new Filter($im))->aqua()->getImage();break;
|
||||
case 'fuzzy':(new Filter($im))->fuzzy()->getImage();break;
|
||||
case 'boost':(new Filter($im))->boost()->getImage();break;
|
||||
case 'gray':(new Filter($im))->gray()->getImage();break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Model class for all models
|
||||
*
|
||||
* @author Christian
|
||||
*/
|
||||
class Model// extends SQLQuery
|
||||
{
|
||||
protected $_model;
|
||||
|
||||
function __construct($id=0)
|
||||
{
|
||||
$this->_model = substr(get_class($this),0,-5);
|
||||
$this->_table = strtolower($this->_model);
|
||||
$this->_id = $id;
|
||||
}
|
||||
|
||||
function __destruct()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
29
cli.php
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
define('DS', DIRECTORY_SEPARATOR);
|
||||
define('ROOT', dirname(__FILE__));
|
||||
define('CLI', true);
|
||||
define('PATH',((dirname($_SERVER['PHP_SELF'])=='/'||dirname($_SERVER['PHP_SELF'])=='\\'||dirname($_SERVER['PHP_SELF'])=='/index.php'||dirname($_SERVER['PHP_SELF'])=='/backend.php')?'/':dirname($_SERVER['PHP_SELF']).'/'));
|
||||
|
||||
if(!file_exists(ROOT.DS.'inc'.DS.'config.inc.php'))
|
||||
exit('Rename /inc/example.config.inc.php to /inc/config.inc.php first!');
|
||||
include_once(ROOT.DS.'inc'.DS.'config.inc.php');
|
||||
|
||||
if(FORCE_DOMAIN)
|
||||
define('DOMAINPATH',FORCE_DOMAIN);
|
||||
else
|
||||
define('DOMAINPATH',(isset($_SERVER['HTTPS'])?'https':'http').'://'.$_SERVER['HTTP_HOST']);
|
||||
error_reporting(E_ALL & ~E_NOTICE);
|
||||
if(SHOW_ERRORS)
|
||||
ini_set('display_errors','On');
|
||||
else ini_set('display_errors','Off');
|
||||
include_once(ROOT.DS.'inc'.DS.'core.php');
|
||||
|
||||
$action = $argv[2];
|
||||
$params = $argv;
|
||||
|
||||
//lose first param (self name)
|
||||
array_shift($params);
|
||||
|
||||
$model = new PictshareModel();
|
||||
$model->backend($params);
|
||||
38
content-controllers/identicon/identicon.controller.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
use Bitverse\Identicon\Identicon;
|
||||
use Bitverse\Identicon\Color\Color;
|
||||
use Bitverse\Identicon\Generator\RingsGenerator;
|
||||
use Bitverse\Identicon\Preprocessor\MD5Preprocessor;
|
||||
|
||||
class IdenticonController implements ContentController
|
||||
{
|
||||
public const ctype = 'dynamic';
|
||||
|
||||
//returns all extensions registered by this type of content
|
||||
public function getRegisteredExtensions(){return array('identicon');}
|
||||
|
||||
public function handleHash($hash,$url)
|
||||
{
|
||||
unset($url[array_search('identicon',$url)]);
|
||||
$url = array_values($url);
|
||||
|
||||
|
||||
$generator = new RingsGenerator();
|
||||
$generator->setBackgroundColor(Color::parseHex('#EEEEEE'));
|
||||
|
||||
$identicon = new Identicon(new MD5Preprocessor(), $generator);
|
||||
|
||||
$icon = $identicon->getIcon($url[0]);
|
||||
|
||||
header('Content-type: image/svg+xml');
|
||||
echo $icon;
|
||||
}
|
||||
|
||||
public function handleUpload($tmpfile,$hash=false)
|
||||
{
|
||||
return array('status'=>'err','hash'=>$hash,'reason'=>'Cannot upload to Identicons');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
0
content-controllers/image/conversion.php
Normal file
278
content-controllers/image/filters.php
Normal file
@@ -0,0 +1,278 @@
|
||||
<?php
|
||||
|
||||
function getFilters()
|
||||
{
|
||||
return get_class_methods('Filter');
|
||||
}
|
||||
|
||||
class Filter {
|
||||
public function sepia($im,$val) {
|
||||
|
||||
imagefilter($im, IMG_FILTER_GRAYSCALE);
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 100, 50, 0);
|
||||
|
||||
return $im;
|
||||
}
|
||||
public function sepia2($im,$val) {
|
||||
imagefilter($im, IMG_FILTER_GRAYSCALE);
|
||||
imagefilter($im, IMG_FILTER_BRIGHTNESS, -10);
|
||||
imagefilter($im, IMG_FILTER_CONTRAST, -20);
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 60, 30, -15);
|
||||
return $im;
|
||||
}
|
||||
public function sharpen($im,$val) {
|
||||
|
||||
$gaussian = array(
|
||||
array(1.0, 1.0, 1.0),
|
||||
array(1.0, -7.0, 1.0),
|
||||
array(1.0, 1.0, 1.0)
|
||||
);
|
||||
imageconvolution($im, $gaussian, 1, 4);
|
||||
|
||||
return $im;
|
||||
}
|
||||
public function emboss($im,$val) {
|
||||
|
||||
$gaussian = array(
|
||||
array(-2.0, -1.0, 0.0),
|
||||
array(-1.0, 1.0, 1.0),
|
||||
array(0.0, 1.0, 2.0)
|
||||
);
|
||||
|
||||
imageconvolution($im, $gaussian, 1, 5);
|
||||
|
||||
return $im;
|
||||
}
|
||||
public function cool($im,$val) {
|
||||
|
||||
imagefilter($im, IMG_FILTER_MEAN_REMOVAL);
|
||||
imagefilter($im, IMG_FILTER_CONTRAST, -50);
|
||||
|
||||
return $im;
|
||||
}
|
||||
public function light($im,$val) {
|
||||
|
||||
imagefilter($im, IMG_FILTER_BRIGHTNESS, 10);
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 100, 50, 0, 10);
|
||||
|
||||
return $im;
|
||||
}
|
||||
public function aqua($im,$val) {
|
||||
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 0, 70, 0, 30);
|
||||
|
||||
return $im;
|
||||
}
|
||||
public function fuzzy($im,$val) {
|
||||
|
||||
$gaussian = array(
|
||||
array(1.0, 1.0, 1.0),
|
||||
array(1.0, 1.0, 1.0),
|
||||
array(1.0, 1.0, 1.0)
|
||||
);
|
||||
imageconvolution($im, $gaussian, 9, 20);
|
||||
|
||||
return $im;
|
||||
}
|
||||
public function boost($im,$val) {
|
||||
|
||||
imagefilter($im, IMG_FILTER_CONTRAST, -35);
|
||||
imagefilter($im, IMG_FILTER_BRIGHTNESS, 10);
|
||||
|
||||
return $im;
|
||||
}
|
||||
public function boost2($im,$val) {
|
||||
imagefilter( $im, IMG_FILTER_CONTRAST, -35);
|
||||
imagefilter( $im, IMG_FILTER_COLORIZE, 25, 25, 25);
|
||||
return $im;
|
||||
}
|
||||
public function gray($im,$val) {
|
||||
|
||||
imagefilter($im, IMG_FILTER_CONTRAST, -60);
|
||||
imagefilter($im, IMG_FILTER_GRAYSCALE);
|
||||
|
||||
return $im;
|
||||
}
|
||||
public function antique($im,$val) {
|
||||
imagefilter($im, IMG_FILTER_BRIGHTNESS, 0);
|
||||
imagefilter($im, IMG_FILTER_CONTRAST, -30);
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 75, 50, 25);
|
||||
return $im;
|
||||
}
|
||||
public function blackwhite($im,$val) {
|
||||
imagefilter($im, IMG_FILTER_GRAYSCALE);
|
||||
imagefilter($im, IMG_FILTER_BRIGHTNESS, 10);
|
||||
imagefilter($im, IMG_FILTER_CONTRAST, -20);
|
||||
return $im;
|
||||
}
|
||||
public function vintage($im,$val) {
|
||||
imagefilter($im, IMG_FILTER_BRIGHTNESS, 10);
|
||||
imagefilter($im, IMG_FILTER_GRAYSCALE);
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 40, 10, -15);
|
||||
return $im;
|
||||
}
|
||||
|
||||
public function concentrate($im,$val) {
|
||||
imagefilter($im, IMG_FILTER_GAUSSIAN_BLUR);
|
||||
imagefilter($im, IMG_FILTER_SMOOTH, -10);
|
||||
return $im;
|
||||
}
|
||||
|
||||
public function hermajesty($im,$val) {
|
||||
imagefilter($im, IMG_FILTER_BRIGHTNESS, -10);
|
||||
imagefilter($im, IMG_FILTER_CONTRAST, -5);
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 80, 0, 60);
|
||||
return $im;
|
||||
}
|
||||
public function everglow($im,$val) {
|
||||
imagefilter($im, IMG_FILTER_BRIGHTNESS, -30);
|
||||
imagefilter($im, IMG_FILTER_CONTRAST, -5);
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 30, 30, 0);
|
||||
return $im;
|
||||
}
|
||||
public function freshblue($im,$val) {
|
||||
imagefilter($im, IMG_FILTER_CONTRAST, -5);
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 20, 0, 80, 60);
|
||||
return $im;
|
||||
}
|
||||
public function tender($im,$val) {
|
||||
imagefilter($im, IMG_FILTER_CONTRAST, 5);
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 80, 20, 40, 50);
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 0, 40, 40, 100);
|
||||
imagefilter($im, IMG_FILTER_SELECTIVE_BLUR);
|
||||
return $im;
|
||||
}
|
||||
public function dream($im,$val) {
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 150, 0, 0, 50);
|
||||
imagefilter($im, IMG_FILTER_NEGATE);
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 0, 50, 0, 50);
|
||||
imagefilter($im, IMG_FILTER_NEGATE);
|
||||
imagefilter($im, IMG_FILTER_GAUSSIAN_BLUR);
|
||||
return $im;
|
||||
}
|
||||
public function frozen($im,$val) {
|
||||
imagefilter($im, IMG_FILTER_BRIGHTNESS, -15);
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 0, 0, 100, 50);
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 0, 0, 100, 50);
|
||||
imagefilter($im, IMG_FILTER_GAUSSIAN_BLUR);
|
||||
return $im;
|
||||
}
|
||||
public function forest($im,$val) {
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 0, 0, 150, 50);
|
||||
imagefilter($im, IMG_FILTER_NEGATE);
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 0, 0, 150, 50);
|
||||
imagefilter($im, IMG_FILTER_NEGATE);
|
||||
imagefilter($im, IMG_FILTER_SMOOTH, 10);
|
||||
return $im;
|
||||
}
|
||||
public function rain($im,$val) {
|
||||
imagefilter($im, IMG_FILTER_GAUSSIAN_BLUR);
|
||||
imagefilter($im, IMG_FILTER_MEAN_REMOVAL);
|
||||
imagefilter($im, IMG_FILTER_NEGATE);
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 0, 80, 50, 50);
|
||||
imagefilter($im, IMG_FILTER_NEGATE);
|
||||
imagefilter($im, IMG_FILTER_SMOOTH, 10);
|
||||
return $im;
|
||||
}
|
||||
public function orangepeel($im,$val) {
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 100, 20, -50, 20);
|
||||
imagefilter($im, IMG_FILTER_SMOOTH, 10);
|
||||
imagefilter($im, IMG_FILTER_BRIGHTNESS, -10);
|
||||
imagefilter($im, IMG_FILTER_CONTRAST, 10);
|
||||
imagegammacorrect($im, 1, 1.2 );
|
||||
return $im;
|
||||
}
|
||||
public function darken($im,$val) {
|
||||
imagefilter($im, IMG_FILTER_GRAYSCALE);
|
||||
imagefilter($im, IMG_FILTER_BRIGHTNESS, -50);
|
||||
return $im;
|
||||
}
|
||||
public function summer($im,$val) {
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 0, 150, 0, 50);
|
||||
imagefilter($im, IMG_FILTER_NEGATE);
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 25, 50, 0, 50);
|
||||
imagefilter($im, IMG_FILTER_NEGATE);
|
||||
return $im;
|
||||
}
|
||||
public function retro($im,$val) {
|
||||
imagefilter($im, IMG_FILTER_GRAYSCALE);
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 100, 25, 25, 50);
|
||||
return $im;
|
||||
}
|
||||
public function country($im,$val) {
|
||||
imagefilter($im, IMG_FILTER_BRIGHTNESS, -30);
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, 50, 50, 50, 50);
|
||||
imagegammacorrect($im, 1, 0.3);
|
||||
return $im;
|
||||
}
|
||||
public function washed($im,$val) {
|
||||
imagefilter($im, IMG_FILTER_BRIGHTNESS, 30);
|
||||
imagefilter($im, IMG_FILTER_NEGATE);
|
||||
imagefilter($im, IMG_FILTER_COLORIZE, -50, 0, 20, 50);
|
||||
imagefilter($im, IMG_FILTER_NEGATE );
|
||||
imagefilter($im, IMG_FILTER_BRIGHTNESS, 10);
|
||||
imagegammacorrect($im, 1, 1.2);
|
||||
return $im;
|
||||
}
|
||||
|
||||
public function pixelate($im,$val) {
|
||||
if($val==null) $val = 10;
|
||||
imagefilter($im,IMG_FILTER_PIXELATE,$val);
|
||||
return $im;
|
||||
}
|
||||
|
||||
public function blur($im,$blurFactor)
|
||||
{
|
||||
if(!$blurFactor)
|
||||
$blurFactor = 3;
|
||||
if($blurFactor>6)
|
||||
$blurFactor = 6;
|
||||
else if($blurFactor<0)
|
||||
$blurFactor = 0;
|
||||
// blurFactor has to be an integer
|
||||
$blurFactor = round($blurFactor);
|
||||
|
||||
$originalWidth = imagesx($im);
|
||||
$originalHeight = imagesy($im);
|
||||
|
||||
$smallestWidth = ceil($originalWidth * pow(0.5, $blurFactor));
|
||||
$smallestHeight = ceil($originalHeight * pow(0.5, $blurFactor));
|
||||
|
||||
// for the first run, the previous image is the original input
|
||||
$prevImage = $im;
|
||||
$prevWidth = $originalWidth;
|
||||
$prevHeight = $originalHeight;
|
||||
|
||||
// scale way down and gradually scale back up, blurring all the way
|
||||
for($i = 0; $i < $blurFactor; $i += 1)
|
||||
{
|
||||
// determine dimensions of next image
|
||||
$nextWidth = $smallestWidth * pow(2, $i);
|
||||
$nextHeight = $smallestHeight * pow(2, $i);
|
||||
|
||||
// resize previous image to next size
|
||||
$nextImage = imagecreatetruecolor($nextWidth, $nextHeight);
|
||||
imagecopyresized($nextImage, $prevImage, 0, 0, 0, 0,
|
||||
$nextWidth, $nextHeight, $prevWidth, $prevHeight);
|
||||
|
||||
// apply blur filter
|
||||
imagefilter($nextImage, IMG_FILTER_GAUSSIAN_BLUR);
|
||||
|
||||
// now the new image becomes the previous image for the next step
|
||||
$prevImage = $nextImage;
|
||||
$prevWidth = $nextWidth;
|
||||
$prevHeight = $nextHeight;
|
||||
}
|
||||
|
||||
// scale back to original size and blur one more time
|
||||
imagecopyresized($im, $nextImage,
|
||||
0, 0, 0, 0, $originalWidth, $originalHeight, $nextWidth, $nextHeight);
|
||||
imagefilter($im, IMG_FILTER_GAUSSIAN_BLUR);
|
||||
|
||||
// clean up
|
||||
imagedestroy($prevImage);
|
||||
|
||||
// return result
|
||||
return $im;
|
||||
}
|
||||
}
|
||||
330
content-controllers/image/image.controller.php
Normal file
@@ -0,0 +1,330 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @Todo:
|
||||
* - Resizing
|
||||
* - Filters
|
||||
* - Conversion gif to mp4
|
||||
* - Conversion jpg,png to webp
|
||||
*/
|
||||
|
||||
class ImageController implements ContentController
|
||||
{
|
||||
public const ctype = 'static';
|
||||
//returns all extensions registered by this type of content
|
||||
public function getRegisteredExtensions(){return array('png','bmp','gif','jpg','jpeg','x-png','webp');}
|
||||
|
||||
public function handleUpload($tmpfile,$hash=false)
|
||||
{
|
||||
$type = exif_imagetype($tmpfile); //http://www.php.net/manual/en/function.exif-imagetype.php
|
||||
switch($type)
|
||||
{
|
||||
case 1: $ext = 'gif';break; //gif
|
||||
case 3: $ext = 'png';break; // png
|
||||
case 6: $ext = 'bmp';break; // bmp
|
||||
case 17: $ext = 'ico';break; // ico
|
||||
case 18: $ext = 'webp';break; // webp
|
||||
|
||||
case 2:
|
||||
//we clean up exif data of JPGs so GPS and other data is removed
|
||||
$res = imagecreatefromjpeg($tmpfile);
|
||||
|
||||
// rotate based on EXIF Orientation
|
||||
$exif = exif_read_data($tmpfile);
|
||||
if (!empty($exif['Orientation'])) {
|
||||
switch ($exif['Orientation']) {
|
||||
case 2:
|
||||
imageflip($res, IMG_FLIP_HORIZONTAL);
|
||||
case 1:
|
||||
// Nothing to do
|
||||
break;
|
||||
|
||||
case 4:
|
||||
imageflip($res, IMG_FLIP_HORIZONTAL);
|
||||
// Also rotate
|
||||
case 3:
|
||||
$res = imagerotate($res, 180, 0);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
imageflip($res, IMG_FLIP_VERTICAL);
|
||||
// Also rotate
|
||||
case 6:
|
||||
$res = imagerotate($res, -90, 0);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
imageflip($res, IMG_FLIP_VERTICAL);
|
||||
// Also rotate
|
||||
case 8:
|
||||
$res = imagerotate($res, 90, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
imagejpeg($res, $tmpfile, (defined('JPEG_COMPRESSION')?JPEG_COMPRESSION:90));
|
||||
$ext = 'jpg';
|
||||
break;
|
||||
|
||||
default:
|
||||
return array('status'=>'err','reason'=>'Not a valid image');
|
||||
}
|
||||
|
||||
if($hash===false)
|
||||
{
|
||||
$hash = getNewHash($ext,6);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!endswith($hash,'.'.$ext))
|
||||
$hash.='.'.$ext;
|
||||
if(isExistingHash($hash))
|
||||
return array('status'=>'err','hash'=>$hash,'reason'=>'Custom hash already exists');
|
||||
}
|
||||
|
||||
storeFile($tmpfile,$hash,true);
|
||||
|
||||
return array('status'=>'ok','hash'=>$hash,'url'=>getURL().$hash);
|
||||
}
|
||||
|
||||
public function handleHash($hash,$url)
|
||||
{
|
||||
$path = getDataDir().DS.$hash.DS.$hash;
|
||||
$type = getExtensionOfFilename($hash);
|
||||
|
||||
//get all our sub files where all the good functions lie
|
||||
include_once(dirname(__FILE__).DS.'resize.php');
|
||||
include_once(dirname(__FILE__).DS.'filters.php');
|
||||
include_once(dirname(__FILE__).DS.'conversion.php');
|
||||
|
||||
//don't do this if it's a gif because PHP can't handle animated gifs
|
||||
if($type!='gif')
|
||||
{
|
||||
$filters = getFilters();
|
||||
foreach($url as $u)
|
||||
{
|
||||
if(isSize($u))
|
||||
$modifiers['size'] = $u;
|
||||
else if(isRotation($u))
|
||||
$modifiers['rotation'] = $u;
|
||||
else // check for filters
|
||||
{
|
||||
foreach($filters as $filter)
|
||||
{
|
||||
if(startsWith($u,$filter) && ($u==$filter || startsWith($u,$filter.'_')))
|
||||
{
|
||||
$a = explode('_',$u);
|
||||
$value = $a[1];
|
||||
if(is_numeric($value))
|
||||
$modifiers['filters'][] = array('filter'=>$filter,'value'=>$value);
|
||||
else
|
||||
$modifiers['filters'][] = array('filter'=>$filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( (in_array('webp',$url) && $type!='webp') || ( $this->shouldAlwaysBeWebp() && ($type=='jpg' || $type=='png') ) )
|
||||
$modifiers['webp'] = true;
|
||||
if(in_array('forcesize',$url) && $modifiers['size'])
|
||||
$modifiers['forcesize'] = true;
|
||||
}
|
||||
else //gif
|
||||
{
|
||||
if(in_array('mp4',$url))
|
||||
$modifiers['mp4']=true;
|
||||
}
|
||||
|
||||
if($modifiers)
|
||||
{
|
||||
//why in gods name would you use http build query here???
|
||||
//well we want a unique filename for every modied image
|
||||
//so if we take all parameters in key=>value form and hash it
|
||||
//we get one nice little hash for every eventuality
|
||||
$modhash = md5(http_build_query($modifiers,'',','));
|
||||
$newpath = getDataDir().DS.$hash.DS.$modhash.'_'.$hash;
|
||||
$im = $this->getObjOfImage($path);
|
||||
$f = new Filter();
|
||||
|
||||
if(!file_exists($newpath))
|
||||
{
|
||||
foreach($modifiers as $mod => $val)
|
||||
{
|
||||
switch($mod)
|
||||
{
|
||||
case 'filters':
|
||||
foreach($val as $fd)
|
||||
{
|
||||
$filter = $fd['filter'];
|
||||
$value = $fd['value'];
|
||||
$im = $f->$filter($im,$value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'size':
|
||||
($modifiers['forcesize']?forceResize($im,$val):resize($im,$val));
|
||||
break;
|
||||
|
||||
case 'rotation':
|
||||
rotate($im,$val);
|
||||
break;
|
||||
|
||||
case 'webp':
|
||||
$type = 'webp';
|
||||
break;
|
||||
|
||||
case 'mp4':
|
||||
$mp4path = getDataDir().DS.$hash.DS.$hash.'mp4';
|
||||
if(!file_exists($mp4path))
|
||||
$this->gifToMP4($path,$mp4path);
|
||||
$path = $mp4path;
|
||||
|
||||
if(in_array('raw',$url))
|
||||
(new VideoController())->serveMP4($path,$hash);
|
||||
else if(in_array('preview',$url))
|
||||
{
|
||||
$preview = $path.'_preview.jpg';
|
||||
if(!file_exists($preview))
|
||||
{
|
||||
(new VideoController())->saveFirstFrameOfMP4($path,$preview);
|
||||
}
|
||||
|
||||
header ("Content-type: image/jpeg");
|
||||
readfile($preview);
|
||||
exit;
|
||||
}
|
||||
else if(in_array('download',$url))
|
||||
{
|
||||
if (file_exists($path)) {
|
||||
header('Content-Description: File Transfer');
|
||||
header('Content-Type: application/octet-stream');
|
||||
header('Content-Disposition: attachment; filename="'.basename($path).'"');
|
||||
header('Expires: 0');
|
||||
header('Cache-Control: must-revalidate');
|
||||
header('Pragma: public');
|
||||
header('Content-Length: ' . filesize($path));
|
||||
readfile($path);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$data = array('url'=>implode('/',$url),'hash'=>$hash,'filesize'=>renderSize(filesize($path)));
|
||||
renderTemplate('video',$data);
|
||||
exit;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->saveObjOfImage($im,$newpath,$type);
|
||||
}
|
||||
else if($modifiers['webp'])
|
||||
{
|
||||
$type = 'webp';
|
||||
}
|
||||
$path = $newpath;
|
||||
|
||||
}
|
||||
|
||||
switch($type)
|
||||
{
|
||||
case 'jpeg':
|
||||
case 'jpg':
|
||||
header ("Content-type: image/jpeg");
|
||||
header ("Last-Modified: ".gmdate('D, d M Y H:i:s ', filemtime($path)) . 'GMT');
|
||||
header ("ETag: $hash");
|
||||
header('Cache-control: public, max-age=31536000');
|
||||
readfile($path);
|
||||
break;
|
||||
|
||||
case 'png':
|
||||
header ("Content-type: image/png");
|
||||
header ("Last-Modified: ".gmdate('D, d M Y H:i:s ', filemtime($path)) . 'GMT');
|
||||
header ("ETag: $hash");
|
||||
header('Cache-control: public, max-age=31536000');
|
||||
readfile($path);
|
||||
break;
|
||||
|
||||
case 'gif':
|
||||
header ("Content-type: image/gif");
|
||||
header ("Last-Modified: ".gmdate('D, d M Y H:i:s ', filemtime($path)) . 'GMT');
|
||||
header ("ETag: $hash");
|
||||
header('Cache-control: public, max-age=31536000');
|
||||
readfile($path);
|
||||
break;
|
||||
|
||||
case 'webp':
|
||||
header ("Content-type: image/webp");
|
||||
header ("Last-Modified: ".gmdate('D, d M Y H:i:s ', filemtime($path)) . 'GMT');
|
||||
header ("ETag: $hash");
|
||||
header('Cache-control: public, max-age=31536000');
|
||||
readfile($path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function getObjOfImage($path)
|
||||
{
|
||||
return imagecreatefromstring(file_get_contents($path));
|
||||
}
|
||||
|
||||
function gifToMP4($gifpath,$target)
|
||||
{
|
||||
$bin = escapeshellcmd(FFMPEG_BINARY);
|
||||
$file = escapeshellarg($gifpath);
|
||||
|
||||
if(!file_exists($target)) //simple caching.. have to think of something better
|
||||
{
|
||||
$cmd = "$bin -f gif -y -i $file -vcodec libx264 -an -profile:v baseline -level 3.0 -pix_fmt yuv420p -vf \"scale=trunc(iw/2)*2:trunc(ih/2)*2\" -f mp4 $target";
|
||||
system($cmd);
|
||||
}
|
||||
|
||||
return $target;
|
||||
}
|
||||
|
||||
function saveObjOfImage($im,$path,$type)
|
||||
{
|
||||
$tmppath = '/tmp/'.getNewHash($type,12);
|
||||
switch($type)
|
||||
{
|
||||
case 'jpeg':
|
||||
case 'jpg':
|
||||
imagejpeg($im,$tmppath,(defined('JPEG_COMPRESSION')?JPEG_COMPRESSION:90));
|
||||
break;
|
||||
|
||||
case 'png':
|
||||
imagepng($im,$tmppath,(defined('PNG_COMPRESSION')?PNG_COMPRESSION:6));
|
||||
break;
|
||||
|
||||
case 'webp':
|
||||
imagepalettetotruecolor($im);
|
||||
imagealphablending($im, true);
|
||||
imagewebp($im,$tmppath,(defined('WEBP_COMPRESSION')?WEBP_COMPRESSION:80));
|
||||
break;
|
||||
}
|
||||
|
||||
if(file_exists($tmppath) && filesize($tmppath)>0)
|
||||
{
|
||||
rename($tmppath,$path);
|
||||
return $im;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
function shouldAlwaysBeWebp()
|
||||
{
|
||||
//sanity check
|
||||
if(!$_SERVER['HTTP_ACCEPT']) return false;
|
||||
|
||||
if(defined('ALWAYS_WEBP') && ALWAYS_WEBP && strpos( $_SERVER['HTTP_ACCEPT'], 'image/webp' ) !== false )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
120
content-controllers/image/resize.php
Normal file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
function isRotation($var)
|
||||
{
|
||||
switch($var)
|
||||
{
|
||||
case 'upside':
|
||||
case 'left':
|
||||
case 'right': return true;
|
||||
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
function rotate(&$im,$direction)
|
||||
{
|
||||
switch($direction)
|
||||
{
|
||||
case 'upside': $angle = 180;break;
|
||||
case 'left': $angle = 90;break;
|
||||
case 'right': $angle = -90;break;
|
||||
default: $angle = 0;break;
|
||||
}
|
||||
|
||||
$im = imagerotate($im,$angle,0);
|
||||
}
|
||||
|
||||
function forceResize(&$img,$size)
|
||||
{
|
||||
$sd = sizeStringToWidthHeight($size);
|
||||
$maxwidth = $sd['width'];
|
||||
$maxheight = $sd['height'];
|
||||
|
||||
|
||||
$width = imagesx($img);
|
||||
$height = imagesy($img);
|
||||
|
||||
$maxwidth = ($maxwidth>$width?$width:$maxwidth);
|
||||
$maxheight = ($maxheight>$height?$height:$maxheight);
|
||||
|
||||
|
||||
$dst_img = imagecreatetruecolor($maxwidth, $maxheight);
|
||||
$src_img = $img;
|
||||
|
||||
$palsize = ImageColorsTotal($img);
|
||||
for ($i = 0; $i < $palsize; $i++)
|
||||
{
|
||||
$colors = ImageColorsForIndex($img, $i);
|
||||
ImageColorAllocate($dst_img, $colors['red'], $colors['green'], $colors['blue']);
|
||||
}
|
||||
|
||||
imagefill($dst_img, 0, 0, IMG_COLOR_TRANSPARENT);
|
||||
imagesavealpha($dst_img,true);
|
||||
imagealphablending($dst_img, true);
|
||||
|
||||
$width_new = $height * $maxwidth / $maxheight;
|
||||
$height_new = $width * $maxheight / $maxwidth;
|
||||
//if the new width is greater than the actual width of the image, then the height is too large and the rest cut off, or vice versa
|
||||
if($width_new > $width){
|
||||
//cut point by height
|
||||
$h_point = (($height - $height_new) / 2);
|
||||
//copy image
|
||||
imagecopyresampled($dst_img, $src_img, 0, 0, 0, $h_point, $maxwidth, $maxheight, $width, $height_new);
|
||||
}else{
|
||||
//cut point by width
|
||||
$w_point = (($width - $width_new) / 2);
|
||||
imagecopyresampled($dst_img, $src_img, 0, 0, $w_point, 0, $maxwidth, $maxheight, $width_new, $height);
|
||||
}
|
||||
|
||||
$img = $dst_img;
|
||||
}
|
||||
|
||||
/**
|
||||
* From: https://stackoverflow.com/questions/4590441/php-thumbnail-image-resizing-with-proportions
|
||||
*/
|
||||
function resize(&$img,$size)
|
||||
{
|
||||
$sd = sizeStringToWidthHeight($size);
|
||||
$maxwidth = $sd['width'];
|
||||
$maxheight = $sd['height'];
|
||||
|
||||
$width = imagesx($img);
|
||||
$height = imagesy($img);
|
||||
|
||||
if(defined('ALLOW_BLOATING') && !ALLOW_BLOATING)
|
||||
{
|
||||
if($maxwidth>$width)$maxwidth = $width;
|
||||
if($maxheight>$height)$maxheight = $height;
|
||||
}
|
||||
|
||||
if ($height > $width)
|
||||
{
|
||||
$ratio = $maxheight / $height;
|
||||
$newheight = intval($maxheight);
|
||||
$newwidth = intval($width * $ratio) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
$ratio = $maxwidth / $width;
|
||||
$newwidth = intval($maxwidth) ;
|
||||
$newheight = intval($height * $ratio);
|
||||
}
|
||||
|
||||
$newimg = imagecreatetruecolor($newwidth,$newheight);
|
||||
|
||||
$palsize = ImageColorsTotal($img);
|
||||
for ($i = 0; $i < $palsize; $i++)
|
||||
{
|
||||
$colors = ImageColorsForIndex($img, $i);
|
||||
ImageColorAllocate($newimg, $colors['red'], $colors['green'], $colors['blue']);
|
||||
}
|
||||
|
||||
imagefill($newimg, 0, 0, IMG_COLOR_TRANSPARENT);
|
||||
imagesavealpha($newimg,true);
|
||||
imagealphablending($newimg, true);
|
||||
|
||||
imagecopyresampled($newimg, $img, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
|
||||
|
||||
$img = $newimg;
|
||||
}
|
||||
52
content-controllers/placeholder/placeholder.controller.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
class PlaceholderController implements ContentController
|
||||
{
|
||||
public const ctype = 'dynamic';
|
||||
|
||||
//returns all extensions registered by this type of content
|
||||
public function getRegisteredExtensions(){return array('placeholder');}
|
||||
|
||||
public function handleHash($hash,$url)
|
||||
{
|
||||
$path = getDataDir().DS.$hash.DS.$hash;
|
||||
|
||||
include_once(dirname(__FILE__).DS.'placeholdergenerator.php');
|
||||
$pg = new PlaceholderGenerator();
|
||||
|
||||
foreach($url as $u)
|
||||
{
|
||||
if(isSize($u))
|
||||
$modifiers['size'] = $u;
|
||||
if(startsWith($u,'color-'))
|
||||
{
|
||||
$u = substr($u,6);
|
||||
$colors = explode('-',$u);
|
||||
foreach($colors as $c)
|
||||
if(isColor($c))
|
||||
$modifiers['colors'][] = (ctype_xdigit($c)?$c:color_name_to_hex($c));
|
||||
|
||||
if(count($modifiers['colors'])>4)
|
||||
$modifiers['colors'] = array_slice($modifiers['colors'],0,4);
|
||||
}
|
||||
}
|
||||
|
||||
$img = $pg->generateImage($modifiers);
|
||||
|
||||
$img = $pg->gradient($img, $modifiers['colors']);
|
||||
$img = $pg->addSizeText($img,$modifiers);
|
||||
|
||||
header ("Content-type: image/jpeg");
|
||||
header ("ETag: $hash");
|
||||
header('Cache-control: public, max-age=31536000');
|
||||
|
||||
imagejpeg($img,null,(defined('JPEG_COMPRESSION')?JPEG_COMPRESSION:90));
|
||||
}
|
||||
|
||||
public function handleUpload($tmpfile,$hash=false)
|
||||
{
|
||||
return array('status'=>'err','hash'=>$hash,'reason'=>'Cannot upload to placeholder image');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
88
content-controllers/placeholder/placeholdergenerator.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
class PlaceholderGenerator {
|
||||
|
||||
function generateImage($modifiers)
|
||||
{
|
||||
$size = ($modifiers['size']?:'800x600');
|
||||
|
||||
$sd = sizeStringToWidthHeight($size);
|
||||
$width = $sd['width'];
|
||||
$height = $sd['height'];
|
||||
|
||||
$im = imagecreatetruecolor($width, $height);
|
||||
|
||||
return $im;
|
||||
}
|
||||
|
||||
function addSizeText($im,$modifiers)
|
||||
{
|
||||
$size = imagesx($im).'x'.imagesy($im);
|
||||
$text = $size;
|
||||
//add the size as text in the center of the image
|
||||
$textcolor = imagecolorallocate($im, 0, 0, 0);
|
||||
$font = dirname(__FILE__).DS.'fonts/RonysiswadiArchitect5-1GErv.ttf';
|
||||
//calculate the size of the text to make sure it will alway be visible
|
||||
$fontsize = 20;
|
||||
$textsize = imagettfbbox($fontsize, 0, $font, $text);
|
||||
$scaleX = imagesx($im) / ($textsize[2] - $textsize[0] + 25);
|
||||
$scaleY = imagesy($im) / ($textsize[1] - $textsize[7] + 25);
|
||||
|
||||
$scale = min($scaleX,$scaleY);
|
||||
|
||||
$fontsize = 20 * $scale;
|
||||
$textsize = imagettfbbox($fontsize, 0, $font, $text);
|
||||
$textwidth = $textsize[2] - $textsize[0];
|
||||
$textheight = $textsize[1] - $textsize[7];
|
||||
|
||||
if($textwidth > imagesx($im) || $textheight > imagesy($im))
|
||||
return $im;
|
||||
|
||||
$x = intval((imagesx($im) - $textwidth) / 2);
|
||||
$y = intval((imagesy($im) - $textheight) / 2 + $textheight);
|
||||
imagettftext($im, $fontsize, 0, $x, $y, $textcolor, $font, $text);
|
||||
|
||||
return $im;
|
||||
}
|
||||
|
||||
function gradient($im, $c) {
|
||||
|
||||
$w = imagesx($im);
|
||||
$h = imagesy($im);
|
||||
|
||||
if(!$c[0]) $c = ['ffffff','ffffff','ffffff','ffffff'];
|
||||
else if(!$c[1]) $c = [$c[0],$c[0],$c[0],$c[0]];
|
||||
else if(!$c[2]) $c = [$c[0],$c[0],$c[1],$c[1]];
|
||||
else if(!$c[3]) $c = [$c[0],$c[1],$c[2],$c[0]];
|
||||
|
||||
for($i=0;$i<=3;$i++) {
|
||||
$c[$i]=$this->hex2rgb($c[$i]);
|
||||
}
|
||||
|
||||
$rgb=$c[0]; // start with top left color
|
||||
for($x=0;$x<=$w;$x++) { // loop columns
|
||||
for($y=0;$y<=$h;$y++) { // loop rows
|
||||
// set pixel color
|
||||
$col=imagecolorallocate($im,intval($rgb[0]),intval($rgb[1]),intval($rgb[2]));
|
||||
imagesetpixel($im,$x-1,$y-1,$col);
|
||||
// calculate new color
|
||||
for($i=0;$i<=2;$i++) {
|
||||
$rgb[$i]=
|
||||
$c[0][$i]*(($w-$x)*($h-$y)/($w*$h)) +
|
||||
$c[1][$i]*($x *($h-$y)/($w*$h)) +
|
||||
$c[2][$i]*(($w-$x)*$y /($w*$h)) +
|
||||
$c[3][$i]*($x *$y /($w*$h));
|
||||
}
|
||||
}
|
||||
}
|
||||
return $im;
|
||||
}
|
||||
|
||||
function hex2rgb($hex)
|
||||
{
|
||||
$rgb[0]=hexdec(substr($hex,0,2));
|
||||
$rgb[1]=hexdec(substr($hex,2,2));
|
||||
$rgb[2]=hexdec(substr($hex,4,2));
|
||||
return($rgb);
|
||||
}
|
||||
}
|
||||
60
content-controllers/text/text.controller.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
class TextController implements ContentController
|
||||
{
|
||||
public const ctype = 'static';
|
||||
|
||||
//returns all extensions registered by this type of content
|
||||
public function getRegisteredExtensions(){return array('txt','text','csv');}
|
||||
|
||||
public function handleHash($hash,$url)
|
||||
{
|
||||
$path = getDataDir().DS.$hash.DS.$hash;
|
||||
|
||||
if(in_array('raw',$url))
|
||||
{
|
||||
header('Content-Type: text/plain; charset=utf-8');
|
||||
echo file_get_contents($path);
|
||||
}
|
||||
else if(in_array('download',$url))
|
||||
{
|
||||
if (file_exists($path)) {
|
||||
header('Content-Description: File Transfer');
|
||||
header('Content-Type: application/octet-stream');
|
||||
header('Content-Disposition: attachment; filename="'.basename($path).'"');
|
||||
header('Expires: 0');
|
||||
header('Cache-Control: must-revalidate');
|
||||
header('Pragma: public');
|
||||
header('Content-Length: ' . filesize($path));
|
||||
readfile($path);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
else
|
||||
renderTemplate('text',array('hash'=>$hash,'content'=>htmlentities(file_get_contents($path))));
|
||||
}
|
||||
|
||||
public function handleUpload($tmpfile,$hash=false)
|
||||
{
|
||||
if($hash===false)
|
||||
{
|
||||
$hash = getNewHash('txt',6);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!endswith($hash,'.txt'))
|
||||
$hash.='.txt';
|
||||
if(isExistingHash($hash))
|
||||
return array('status'=>'err','hash'=>$hash,'reason'=>'Custom hash already exists');
|
||||
}
|
||||
|
||||
storeFile($tmpfile,$hash,true);
|
||||
|
||||
return array('status'=>'ok','hash'=>$hash,'url'=>getURL().$hash);
|
||||
}
|
||||
|
||||
function getTypeOfText($hash)
|
||||
{
|
||||
return file_get_contents(getDataDir().DS.$hash.DS.'type');
|
||||
}
|
||||
}
|
||||
11
content-controllers/url/url.controller.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
class UrlController implements ContentController
|
||||
{
|
||||
public const ctype = 'static';
|
||||
|
||||
//returns all extensions registered by this type of content
|
||||
public function getRegisteredExtensions(){return array('url');}
|
||||
public function handleHash($hash,$url){}
|
||||
public function handleUpload($tmpfile,$hash=false){}
|
||||
}
|
||||
217
content-controllers/video/video.controller.php
Normal file
@@ -0,0 +1,217 @@
|
||||
<?php
|
||||
|
||||
class VideoController implements ContentController
|
||||
{
|
||||
public const ctype = 'static';
|
||||
|
||||
//returns all extensions registered by this type of content
|
||||
public function getRegisteredExtensions(){return array('mp4');}
|
||||
|
||||
public function handleHash($hash,$url)
|
||||
{
|
||||
$path = getDataDir().DS.$hash.DS.$hash;
|
||||
|
||||
//@todo: - resize by changing $path
|
||||
|
||||
//check if video should be resized
|
||||
foreach($url as $u)
|
||||
if(isSize($u)==true)
|
||||
$size = $u;
|
||||
if($size)
|
||||
{
|
||||
$s = sizeStringToWidthHeight($size);
|
||||
$width = $s['width'];
|
||||
$newpath = getDataDir().DS.$hash.DS.$width.'_'.$hash;
|
||||
if(!file_exists($newpath))
|
||||
$this->resize($path,$newpath,$width);
|
||||
$path = $newpath;
|
||||
}
|
||||
|
||||
|
||||
if(in_array('raw',$url))
|
||||
$this->serveMP4($path,$hash);
|
||||
else if(in_array('preview',$url))
|
||||
{
|
||||
$preview = $path.'_preview.jpg';
|
||||
if(!file_exists($preview))
|
||||
{
|
||||
$this->saveFirstFrameOfMP4($path,$preview);
|
||||
}
|
||||
|
||||
header ("Content-type: image/jpeg");
|
||||
readfile($preview);
|
||||
|
||||
}
|
||||
else if(in_array('download',$url))
|
||||
{
|
||||
if (file_exists($path)) {
|
||||
header('Content-Description: File Transfer');
|
||||
header('Content-Type: application/octet-stream');
|
||||
header('Content-Disposition: attachment; filename="'.basename($path).'"');
|
||||
header('Expires: 0');
|
||||
header('Cache-Control: must-revalidate');
|
||||
header('Pragma: public');
|
||||
header('Content-Length: ' . filesize($path));
|
||||
readfile($path);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$data = array('url'=>implode('/',$url),'hash'=>$hash,'filesize'=>renderSize(filesize($path)));
|
||||
renderTemplate('video',$data);
|
||||
}
|
||||
}
|
||||
|
||||
public function handleUpload($tmpfile,$hash=false)
|
||||
{
|
||||
if($hash===false)
|
||||
$hash = getNewHash('mp4',6);
|
||||
else
|
||||
{
|
||||
$hash.='.mp4';
|
||||
if(isExistingHash($hash))
|
||||
return array('status'=>'err','hash'=>$hash,'reason'=>'Custom hash already exists');
|
||||
}
|
||||
|
||||
$file = storeFile($tmpfile,$hash,true);
|
||||
|
||||
if(!$this->rightEncodedMP4($file))
|
||||
system("nohup php ".ROOT.DS.'tools'.DS.'re-encode_mp4.php force '.$hash." > /dev/null 2> /dev/null &");
|
||||
|
||||
return array('status'=>'ok','hash'=>$hash,'url'=>getURL().$hash);
|
||||
}
|
||||
|
||||
|
||||
//via gist: https://gist.github.com/codler/3906826
|
||||
function serveMP4($path,$hash)
|
||||
{
|
||||
if ($fp = fopen($path, "rb"))
|
||||
{
|
||||
$size = filesize($path);
|
||||
$length = $size;
|
||||
$start = 0;
|
||||
$end = $size - 1;
|
||||
header('Content-type: video/mp4');
|
||||
header('Cache-control: public, max-age=31536000');
|
||||
header("Accept-Ranges: 0-$length");
|
||||
if (isset($_SERVER['HTTP_RANGE'])) {
|
||||
$c_start = $start;
|
||||
$c_end = $end;
|
||||
list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2);
|
||||
if (strpos($range, ',') !== false) {
|
||||
header('HTTP/1.1 416 Requested Range Not Satisfiable');
|
||||
header("Content-Range: bytes $start-$end/$size");
|
||||
exit;
|
||||
}
|
||||
if ($range == '-') {
|
||||
$c_start = $size - substr($range, 1);
|
||||
} else {
|
||||
$range = explode('-', $range);
|
||||
$c_start = $range[0];
|
||||
$c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $size;
|
||||
}
|
||||
$c_end = ($c_end > $end) ? $end : $c_end;
|
||||
if ($c_start > $c_end || $c_start > $size - 1 || $c_end >= $size) {
|
||||
header('HTTP/1.1 416 Requested Range Not Satisfiable');
|
||||
header("Content-Range: bytes $start-$end/$size");
|
||||
exit;
|
||||
}
|
||||
$start = $c_start;
|
||||
$end = $c_end;
|
||||
$length = $end - $start + 1;
|
||||
fseek($fp, $start);
|
||||
header('HTTP/1.1 206 Partial Content');
|
||||
}
|
||||
header("Content-Range: bytes $start-$end/$size");
|
||||
header("Content-Length: ".$length);
|
||||
$buffer = 1024 * 8;
|
||||
while(!feof($fp) && ($p = ftell($fp)) <= $end) {
|
||||
if ($p + $buffer > $end) {
|
||||
$buffer = $end - $p + 1;
|
||||
}
|
||||
set_time_limit(0);
|
||||
echo fread($fp, $buffer);
|
||||
flush();
|
||||
}
|
||||
fclose($fp);
|
||||
exit();
|
||||
} else die('file not found');
|
||||
}
|
||||
|
||||
function isProperMP4($filename)
|
||||
{
|
||||
$file = escapeshellarg($filename);
|
||||
$tmp = ROOT.DS.'tmp'.DS.md5(time()+rand(1,10000)).'.'.rand(1,10000).'.log';
|
||||
$bin = escapeshellcmd(FFMPEG_BINARY);
|
||||
|
||||
|
||||
|
||||
$cmd = "$bin -i $file > $tmp 2>> $tmp";
|
||||
|
||||
system($cmd);
|
||||
|
||||
//var_dump(system( "$bin -i $file "));
|
||||
|
||||
$answer = file($tmp);
|
||||
unlink($tmp);
|
||||
$ismp4 = false;
|
||||
if(is_array($answer))
|
||||
foreach($answer as $line)
|
||||
{
|
||||
$line = trim($line);
|
||||
if(strpos($line,'Duration: 00:00:00')) return false;
|
||||
if(strpos($line, 'Video: h264'))
|
||||
$ismp4 = true;
|
||||
}
|
||||
|
||||
return $ismp4;
|
||||
}
|
||||
|
||||
function rightEncodedMP4($file)
|
||||
{
|
||||
$hash = md5($file);
|
||||
$cmd = FFMPEG_BINARY." -i $file -hide_banner 2> ".ROOT.DS.'tmp'.DS.$hash.'.txt';
|
||||
system($cmd);
|
||||
$results = file(ROOT.DS.'tmp'.DS.$hash.'.txt');
|
||||
foreach($results as $l)
|
||||
{
|
||||
$elements = explode(':',trim($l));
|
||||
$key=trim(array_shift($elements));
|
||||
$value = trim(implode(':',$elements));
|
||||
if($key=='encoder')
|
||||
{
|
||||
if(startsWith(strtolower($value),'lav'))
|
||||
{
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
}
|
||||
unlink(ROOT.DS.'tmp'.DS.$hash.'.txt');
|
||||
return false;
|
||||
}
|
||||
|
||||
function saveFirstFrameOfMP4($path,$target)
|
||||
{
|
||||
$bin = escapeshellcmd(FFMPEG_BINARY);
|
||||
$file = escapeshellarg($path);
|
||||
$cmd = "$bin -y -i $file -vframes 1 -f image2 $target";
|
||||
|
||||
system($cmd);
|
||||
}
|
||||
|
||||
function resize($in,$out,$width)
|
||||
{
|
||||
$file = escapeshellarg($in);
|
||||
$tmp = '/dev/null';
|
||||
$bin = escapeshellcmd(FFMPEG_BINARY);
|
||||
|
||||
$addition = '-c:v libx264 -profile:v baseline -level 3.0 -pix_fmt yuv420p';
|
||||
$height = 'trunc(ow/a/2)*2';
|
||||
|
||||
$cmd = "$bin -i $file -y -vf scale=\"$width:$height\" $addition $out";
|
||||
system($cmd);
|
||||
|
||||
return (file_exists($out) && filesize($out)>0);
|
||||
}
|
||||
}
|
||||
388
css/dropzone.css
Normal file
@@ -0,0 +1,388 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright (c) 2012 Matias Meno <m@tias.me>
|
||||
*/
|
||||
@-webkit-keyframes passing-through {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: translateY(40px);
|
||||
-moz-transform: translateY(40px);
|
||||
-ms-transform: translateY(40px);
|
||||
-o-transform: translateY(40px);
|
||||
transform: translateY(40px); }
|
||||
30%, 70% {
|
||||
opacity: 1;
|
||||
-webkit-transform: translateY(0px);
|
||||
-moz-transform: translateY(0px);
|
||||
-ms-transform: translateY(0px);
|
||||
-o-transform: translateY(0px);
|
||||
transform: translateY(0px); }
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: translateY(-40px);
|
||||
-moz-transform: translateY(-40px);
|
||||
-ms-transform: translateY(-40px);
|
||||
-o-transform: translateY(-40px);
|
||||
transform: translateY(-40px); } }
|
||||
@-moz-keyframes passing-through {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: translateY(40px);
|
||||
-moz-transform: translateY(40px);
|
||||
-ms-transform: translateY(40px);
|
||||
-o-transform: translateY(40px);
|
||||
transform: translateY(40px); }
|
||||
30%, 70% {
|
||||
opacity: 1;
|
||||
-webkit-transform: translateY(0px);
|
||||
-moz-transform: translateY(0px);
|
||||
-ms-transform: translateY(0px);
|
||||
-o-transform: translateY(0px);
|
||||
transform: translateY(0px); }
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: translateY(-40px);
|
||||
-moz-transform: translateY(-40px);
|
||||
-ms-transform: translateY(-40px);
|
||||
-o-transform: translateY(-40px);
|
||||
transform: translateY(-40px); } }
|
||||
@keyframes passing-through {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: translateY(40px);
|
||||
-moz-transform: translateY(40px);
|
||||
-ms-transform: translateY(40px);
|
||||
-o-transform: translateY(40px);
|
||||
transform: translateY(40px); }
|
||||
30%, 70% {
|
||||
opacity: 1;
|
||||
-webkit-transform: translateY(0px);
|
||||
-moz-transform: translateY(0px);
|
||||
-ms-transform: translateY(0px);
|
||||
-o-transform: translateY(0px);
|
||||
transform: translateY(0px); }
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: translateY(-40px);
|
||||
-moz-transform: translateY(-40px);
|
||||
-ms-transform: translateY(-40px);
|
||||
-o-transform: translateY(-40px);
|
||||
transform: translateY(-40px); } }
|
||||
@-webkit-keyframes slide-in {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: translateY(40px);
|
||||
-moz-transform: translateY(40px);
|
||||
-ms-transform: translateY(40px);
|
||||
-o-transform: translateY(40px);
|
||||
transform: translateY(40px); }
|
||||
30% {
|
||||
opacity: 1;
|
||||
-webkit-transform: translateY(0px);
|
||||
-moz-transform: translateY(0px);
|
||||
-ms-transform: translateY(0px);
|
||||
-o-transform: translateY(0px);
|
||||
transform: translateY(0px); } }
|
||||
@-moz-keyframes slide-in {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: translateY(40px);
|
||||
-moz-transform: translateY(40px);
|
||||
-ms-transform: translateY(40px);
|
||||
-o-transform: translateY(40px);
|
||||
transform: translateY(40px); }
|
||||
30% {
|
||||
opacity: 1;
|
||||
-webkit-transform: translateY(0px);
|
||||
-moz-transform: translateY(0px);
|
||||
-ms-transform: translateY(0px);
|
||||
-o-transform: translateY(0px);
|
||||
transform: translateY(0px); } }
|
||||
@keyframes slide-in {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: translateY(40px);
|
||||
-moz-transform: translateY(40px);
|
||||
-ms-transform: translateY(40px);
|
||||
-o-transform: translateY(40px);
|
||||
transform: translateY(40px); }
|
||||
30% {
|
||||
opacity: 1;
|
||||
-webkit-transform: translateY(0px);
|
||||
-moz-transform: translateY(0px);
|
||||
-ms-transform: translateY(0px);
|
||||
-o-transform: translateY(0px);
|
||||
transform: translateY(0px); } }
|
||||
@-webkit-keyframes pulse {
|
||||
0% {
|
||||
-webkit-transform: scale(1);
|
||||
-moz-transform: scale(1);
|
||||
-ms-transform: scale(1);
|
||||
-o-transform: scale(1);
|
||||
transform: scale(1); }
|
||||
10% {
|
||||
-webkit-transform: scale(1.1);
|
||||
-moz-transform: scale(1.1);
|
||||
-ms-transform: scale(1.1);
|
||||
-o-transform: scale(1.1);
|
||||
transform: scale(1.1); }
|
||||
20% {
|
||||
-webkit-transform: scale(1);
|
||||
-moz-transform: scale(1);
|
||||
-ms-transform: scale(1);
|
||||
-o-transform: scale(1);
|
||||
transform: scale(1); } }
|
||||
@-moz-keyframes pulse {
|
||||
0% {
|
||||
-webkit-transform: scale(1);
|
||||
-moz-transform: scale(1);
|
||||
-ms-transform: scale(1);
|
||||
-o-transform: scale(1);
|
||||
transform: scale(1); }
|
||||
10% {
|
||||
-webkit-transform: scale(1.1);
|
||||
-moz-transform: scale(1.1);
|
||||
-ms-transform: scale(1.1);
|
||||
-o-transform: scale(1.1);
|
||||
transform: scale(1.1); }
|
||||
20% {
|
||||
-webkit-transform: scale(1);
|
||||
-moz-transform: scale(1);
|
||||
-ms-transform: scale(1);
|
||||
-o-transform: scale(1);
|
||||
transform: scale(1); } }
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
-webkit-transform: scale(1);
|
||||
-moz-transform: scale(1);
|
||||
-ms-transform: scale(1);
|
||||
-o-transform: scale(1);
|
||||
transform: scale(1); }
|
||||
10% {
|
||||
-webkit-transform: scale(1.1);
|
||||
-moz-transform: scale(1.1);
|
||||
-ms-transform: scale(1.1);
|
||||
-o-transform: scale(1.1);
|
||||
transform: scale(1.1); }
|
||||
20% {
|
||||
-webkit-transform: scale(1);
|
||||
-moz-transform: scale(1);
|
||||
-ms-transform: scale(1);
|
||||
-o-transform: scale(1);
|
||||
transform: scale(1); } }
|
||||
.dropzone, .dropzone * {
|
||||
box-sizing: border-box; }
|
||||
|
||||
.dropzone {
|
||||
min-height: 150px;
|
||||
border: 2px solid rgba(0, 0, 0, 0.3);
|
||||
background: white;
|
||||
padding: 20px 20px; }
|
||||
.dropzone.dz-clickable {
|
||||
cursor: pointer; }
|
||||
.dropzone.dz-clickable * {
|
||||
cursor: default; }
|
||||
.dropzone.dz-clickable .dz-message, .dropzone.dz-clickable .dz-message * {
|
||||
cursor: pointer; }
|
||||
.dropzone.dz-started .dz-message {
|
||||
display: none; }
|
||||
.dropzone.dz-drag-hover {
|
||||
border-style: solid; }
|
||||
.dropzone.dz-drag-hover .dz-message {
|
||||
opacity: 0.5; }
|
||||
.dropzone .dz-message {
|
||||
text-align: center;
|
||||
margin: 2em 0; }
|
||||
.dropzone .dz-preview {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin: 16px;
|
||||
min-height: 100px; }
|
||||
.dropzone .dz-preview:hover {
|
||||
z-index: 1000; }
|
||||
.dropzone .dz-preview:hover .dz-details {
|
||||
opacity: 1; }
|
||||
.dropzone .dz-preview.dz-file-preview .dz-image {
|
||||
border-radius: 20px;
|
||||
background: #999;
|
||||
background: linear-gradient(to bottom, #eee, #ddd); }
|
||||
.dropzone .dz-preview.dz-file-preview .dz-details {
|
||||
opacity: 1; }
|
||||
.dropzone .dz-preview.dz-image-preview {
|
||||
background: white; }
|
||||
.dropzone .dz-preview.dz-image-preview .dz-details {
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
-moz-transition: opacity 0.2s linear;
|
||||
-ms-transition: opacity 0.2s linear;
|
||||
-o-transition: opacity 0.2s linear;
|
||||
transition: opacity 0.2s linear; }
|
||||
.dropzone .dz-preview .dz-remove {
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
border: none; }
|
||||
.dropzone .dz-preview .dz-remove:hover {
|
||||
text-decoration: underline; }
|
||||
.dropzone .dz-preview:hover .dz-details {
|
||||
opacity: 1; }
|
||||
.dropzone .dz-preview .dz-details {
|
||||
z-index: 20;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
font-size: 13px;
|
||||
min-width: 100%;
|
||||
max-width: 100%;
|
||||
padding: 2em 1em;
|
||||
text-align: center;
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
line-height: 150%; }
|
||||
.dropzone .dz-preview .dz-details .dz-size {
|
||||
margin-bottom: 1em;
|
||||
font-size: 16px; }
|
||||
.dropzone .dz-preview .dz-details .dz-filename {
|
||||
white-space: nowrap; }
|
||||
.dropzone .dz-preview .dz-details .dz-filename:hover span {
|
||||
border: 1px solid rgba(200, 200, 200, 0.8);
|
||||
background-color: rgba(255, 255, 255, 0.8); }
|
||||
.dropzone .dz-preview .dz-details .dz-filename:not(:hover) {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis; }
|
||||
.dropzone .dz-preview .dz-details .dz-filename:not(:hover) span {
|
||||
border: 1px solid transparent; }
|
||||
.dropzone .dz-preview .dz-details .dz-filename span, .dropzone .dz-preview .dz-details .dz-size span {
|
||||
background-color: rgba(255, 255, 255, 0.4);
|
||||
padding: 0 0.4em;
|
||||
border-radius: 3px; }
|
||||
.dropzone .dz-preview:hover .dz-image img {
|
||||
-webkit-transform: scale(1.05, 1.05);
|
||||
-moz-transform: scale(1.05, 1.05);
|
||||
-ms-transform: scale(1.05, 1.05);
|
||||
-o-transform: scale(1.05, 1.05);
|
||||
transform: scale(1.05, 1.05);
|
||||
-webkit-filter: blur(8px);
|
||||
filter: blur(8px); }
|
||||
.dropzone .dz-preview .dz-image {
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
position: relative;
|
||||
display: block;
|
||||
z-index: 10; }
|
||||
.dropzone .dz-preview .dz-image img {
|
||||
display: block; }
|
||||
.dropzone .dz-preview.dz-success .dz-success-mark {
|
||||
-webkit-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
|
||||
-moz-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
|
||||
-ms-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
|
||||
-o-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
|
||||
animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1); }
|
||||
.dropzone .dz-preview.dz-error .dz-error-mark {
|
||||
opacity: 1;
|
||||
-webkit-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
|
||||
-moz-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
|
||||
-ms-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
|
||||
-o-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
|
||||
animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1); }
|
||||
.dropzone .dz-preview .dz-success-mark, .dropzone .dz-preview .dz-error-mark {
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
z-index: 500;
|
||||
position: absolute;
|
||||
display: block;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -27px;
|
||||
margin-top: -27px; }
|
||||
.dropzone .dz-preview .dz-success-mark svg, .dropzone .dz-preview .dz-error-mark svg {
|
||||
display: block;
|
||||
width: 54px;
|
||||
height: 54px; }
|
||||
.dropzone .dz-preview.dz-processing .dz-progress {
|
||||
opacity: 1;
|
||||
-webkit-transition: all 0.2s linear;
|
||||
-moz-transition: all 0.2s linear;
|
||||
-ms-transition: all 0.2s linear;
|
||||
-o-transition: all 0.2s linear;
|
||||
transition: all 0.2s linear; }
|
||||
.dropzone .dz-preview.dz-complete .dz-progress {
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.4s ease-in;
|
||||
-moz-transition: opacity 0.4s ease-in;
|
||||
-ms-transition: opacity 0.4s ease-in;
|
||||
-o-transition: opacity 0.4s ease-in;
|
||||
transition: opacity 0.4s ease-in; }
|
||||
.dropzone .dz-preview:not(.dz-processing) .dz-progress {
|
||||
-webkit-animation: pulse 6s ease infinite;
|
||||
-moz-animation: pulse 6s ease infinite;
|
||||
-ms-animation: pulse 6s ease infinite;
|
||||
-o-animation: pulse 6s ease infinite;
|
||||
animation: pulse 6s ease infinite; }
|
||||
.dropzone .dz-preview .dz-progress {
|
||||
opacity: 1;
|
||||
z-index: 1000;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
height: 16px;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
margin-top: -8px;
|
||||
width: 80px;
|
||||
margin-left: -40px;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
-webkit-transform: scale(1);
|
||||
border-radius: 8px;
|
||||
overflow: hidden; }
|
||||
.dropzone .dz-preview .dz-progress .dz-upload {
|
||||
background: #333;
|
||||
background: linear-gradient(to bottom, #666, #444);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 0;
|
||||
-webkit-transition: width 300ms ease-in-out;
|
||||
-moz-transition: width 300ms ease-in-out;
|
||||
-ms-transition: width 300ms ease-in-out;
|
||||
-o-transition: width 300ms ease-in-out;
|
||||
transition: width 300ms ease-in-out; }
|
||||
.dropzone .dz-preview.dz-error .dz-error-message {
|
||||
display: block; }
|
||||
.dropzone .dz-preview.dz-error:hover .dz-error-message {
|
||||
opacity: 1;
|
||||
pointer-events: auto; }
|
||||
.dropzone .dz-preview .dz-error-message {
|
||||
pointer-events: none;
|
||||
z-index: 1000;
|
||||
position: absolute;
|
||||
display: block;
|
||||
display: none;
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.3s ease;
|
||||
-moz-transition: opacity 0.3s ease;
|
||||
-ms-transition: opacity 0.3s ease;
|
||||
-o-transition: opacity 0.3s ease;
|
||||
transition: opacity 0.3s ease;
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
top: 130px;
|
||||
left: -10px;
|
||||
width: 140px;
|
||||
background: #be2626;
|
||||
background: linear-gradient(to bottom, #be2626, #a92222);
|
||||
padding: 0.5em 1.2em;
|
||||
color: white; }
|
||||
.dropzone .dz-preview .dz-error-message:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
left: 64px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 6px solid transparent;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid #be2626; }
|
||||
5
css/gh-fork-ribbon.min.css
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/*!
|
||||
* "Fork me on GitHub" CSS ribbon v0.2.3 | MIT License
|
||||
* https://github.com/simonwhitaker/github-fork-ribbon-css
|
||||
*/.github-fork-ribbon{width:12.1em;height:12.1em;position:absolute;overflow:hidden;top:0;right:0;z-index:9999;pointer-events:none;font-size:13px;text-decoration:none;text-indent:-999999px}.github-fork-ribbon.fixed{position:fixed}.github-fork-ribbon:active,.github-fork-ribbon:hover{background-color:rgba(0,0,0,0)}.github-fork-ribbon:after,.github-fork-ribbon:before{position:absolute;display:block;width:15.38em;height:1.54em;top:3.23em;right:-3.23em;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.github-fork-ribbon:before{content:"";padding:.38em 0;background-color:#a00;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,0)),to(rgba(0,0,0,.15)));background-image:-webkit-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:-moz-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:-ms-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:-o-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:linear-gradient(to bottom,rgba(0,0,0,0),rgba(0,0,0,.15));-webkit-box-shadow:0 .15em .23em 0 rgba(0,0,0,.5);-moz-box-shadow:0 .15em .23em 0 rgba(0,0,0,.5);box-shadow:0 .15em .23em 0 rgba(0,0,0,.5);pointer-events:auto}.github-fork-ribbon:after{content:attr(data-ribbon);color:#fff;font:700 1em "Helvetica Neue",Helvetica,Arial,sans-serif;line-height:1.54em;text-decoration:none;text-shadow:0 -.08em rgba(0,0,0,.5);text-align:center;text-indent:0;padding:.15em 0;margin:.15em 0;border-width:.08em 0;border-style:dotted;border-color:#fff;border-color:rgba(255,255,255,.7)}.github-fork-ribbon.left-bottom,.github-fork-ribbon.left-top{right:auto;left:0}.github-fork-ribbon.left-bottom,.github-fork-ribbon.right-bottom{top:auto;bottom:0}.github-fork-ribbon.left-bottom:after,.github-fork-ribbon.left-bottom:before,.github-fork-ribbon.left-top:after,.github-fork-ribbon.left-top:before{right:auto;left:-3.23em}.github-fork-ribbon.left-bottom:after,.github-fork-ribbon.left-bottom:before,.github-fork-ribbon.right-bottom:after,.github-fork-ribbon.right-bottom:before{top:auto;bottom:3.23em}.github-fork-ribbon.left-top:after,.github-fork-ribbon.left-top:before,.github-fork-ribbon.right-bottom:after,.github-fork-ribbon.right-bottom:before{-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg)}
|
||||
/*# sourceMappingURL=gh-fork-ribbon.min.css.map */
|
||||
0
css/imgs/logo/horizontal.png
Normal file → Executable file
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
0
css/imgs/logo/horizontal2.png
Normal file → Executable file
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
0
css/imgs/logo/horizontal3.png
Normal file → Executable file
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
0
css/imgs/logo/logo.png
Normal file → Executable file
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
1
css/imgs/logo/logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2" viewBox="0 0 318.8 194"><circle cx="97" cy="97" r="97" style="fill:url(#a)"/><path d="M97.3 6.8c50 0 90.5 40.3 90.5 90s-40.5 90-90.5 90-90.5-40.3-90.5-90 40.5-90 90.5-90Zm69.8 140.7a85.2 85.2 0 0 0 16.6-50.6A86.2 86.2 0 0 0 97.3 11 86.2 86.2 0 0 0 11 96.9c0 17 5 32.8 13.5 46.2 36.3-67.4 36.2-74.7 45.3-74.7 8.8 0 10.3 7.6 43.3 71.4 16.7-25.9 18.9-30.4 24.3-30.4 6.7 0 8 5 29.7 38Zm-29.3-68.2a10.6 10.6 0 1 1 0 21.2 10.6 10.6 0 0 1 0-21.2Z" style="fill:url(#b)"/><path d="M253 37.1a33 33 0 1 1 10.4 27l-69.7 26.1-6.4-28.5L253 37.1Z" style="fill:url(#c)"/><path d="M263.4 129.3a32.9 32.9 0 0 1 55.4 24.2 33 33 0 0 1-65.8 3.2l-65.6-24.8 6.4-28.9 69.6 26.3Z" style="fill:url(#d)"/><defs><radialGradient id="a" cx="0" cy="0" r="1" gradientTransform="matrix(79 0 0 -73 97.3 77.6)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#867278;stop-opacity:1"/><stop offset=".5" style="stop-color:#5c4955;stop-opacity:1"/><stop offset="1" style="stop-color:#433545;stop-opacity:1"/></radialGradient><radialGradient id="c" cx="0" cy="0" r="1" gradientTransform="matrix(55 0 0 -55 253 48.6)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#867278;stop-opacity:1"/><stop offset=".5" style="stop-color:#5c4955;stop-opacity:1"/><stop offset="1" style="stop-color:#433545;stop-opacity:1"/></radialGradient><radialGradient id="d" cx="0" cy="0" r="1" gradientTransform="matrix(55 0 0 -56 253.1 144.8)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#867278;stop-opacity:1"/><stop offset=".5" style="stop-color:#5c4955;stop-opacity:1"/><stop offset="1" style="stop-color:#433545;stop-opacity:1"/></radialGradient><linearGradient id="b" x1="0" x2="1" y1="0" y2="0" gradientTransform="matrix(97 0 0 97 53.6 97)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#40a1d4;stop-opacity:1"/><stop offset="1" style="stop-color:#2971c2;stop-opacity:1"/></linearGradient></defs></svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
0
css/imgs/logo/logo2.png
Normal file → Executable file
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
0
css/imgs/logo/monochrome.png
Normal file → Executable file
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
0
css/imgs/logo/monochrome2.png
Normal file → Executable file
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
0
css/imgs/logo/picthshare.ai
Normal file → Executable file
0
css/imgs/logo/picthshare.pdf
Normal file → Executable file
0
css/imgs/logo/picthshare.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 67 KiB |
0
css/imgs/logo/vertical.png
Normal file → Executable file
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
0
css/imgs/logo/vertical2.png
Normal file → Executable file
|
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 99 KiB |
0
css/imgs/logo/vertical3.png
Normal file → Executable file
|
Before Width: | Height: | Size: 203 KiB After Width: | Height: | Size: 203 KiB |
@@ -25,4 +25,11 @@ body {
|
||||
background: rgba(245, 245, 245, .8);
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.05);
|
||||
box-shadow: inset 0 1px 1px rgba(0,0,0,.05);
|
||||
}
|
||||
|
||||
.box__dragndrop,
|
||||
.box__uploading,
|
||||
.box__success,
|
||||
.box__error {
|
||||
display: none;
|
||||
}
|
||||
0
upload/deletecodes/.gitignore → data/.gitignore
vendored
Normal file → Executable file
@@ -1,24 +0,0 @@
|
||||
version: '2'
|
||||
|
||||
services:
|
||||
pictshare:
|
||||
restart: always
|
||||
image: hascheksolutions/pictshare:latest
|
||||
volumes:
|
||||
- ./volumes/upload:/opt/pictshare/upload
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
environment:
|
||||
- TITLE=
|
||||
- AUTOUPDATE=false
|
||||
- MAXUPLOADSIZE=
|
||||
- MASTERDELETECODE=
|
||||
- BLOATING=
|
||||
- UPLOADCODE=
|
||||
- UPLOADPATH=
|
||||
- IMAGECHANGECODE=
|
||||
- LOGUPLOADER=
|
||||
- MAXRESIZEDIMAGES=
|
||||
- DOMAIN=
|
||||
- SHOWERRORS=
|
||||
69
docker/Dockerfile
Normal file
@@ -0,0 +1,69 @@
|
||||
FROM alpine:3.18
|
||||
|
||||
RUN apk add --no-cache bash socat wget curl nginx file ffmpeg unzip zlib redis \
|
||||
php82-fileinfo \
|
||||
php82-session \
|
||||
php \
|
||||
php-curl \
|
||||
php-openssl \
|
||||
php-mbstring \
|
||||
php-json \
|
||||
php-gd \
|
||||
php-dom \
|
||||
php-fpm \
|
||||
php82 \
|
||||
php82-pdo \
|
||||
php82-exif \
|
||||
php82-curl \
|
||||
php82-gd \
|
||||
php82-json \
|
||||
php82-phar \
|
||||
php82-fpm \
|
||||
php82-openssl \
|
||||
php82-ctype \
|
||||
php82-opcache \
|
||||
php82-mbstring \
|
||||
php82-sodium \
|
||||
php82-xml \
|
||||
php82-ftp \
|
||||
php82-simplexml \
|
||||
php82-session \
|
||||
php82-fileinfo \
|
||||
php82-pcntl \
|
||||
php82-pecl-redis
|
||||
|
||||
RUN ln -s /usr/bin/php82 /usr/bin/php
|
||||
|
||||
RUN curl -sS https://getcomposer.org/installer | /usr/bin/php -- --install-dir=/usr/bin --filename=composer
|
||||
RUN mkdir -p /var/www
|
||||
WORKDIR /var/www
|
||||
|
||||
ADD . /var/www/.
|
||||
|
||||
ADD docker/rootfs/start.sh /etc/start.sh
|
||||
RUN chmod +x /etc/start.sh
|
||||
|
||||
# Composer intall
|
||||
WORKDIR /var/www/lib
|
||||
RUN composer install --no-dev --no-interaction --no-progress --optimize-autoloader
|
||||
|
||||
# nginx stuff
|
||||
WORKDIR /var/www
|
||||
ADD docker/rootfs/nginx.conf /etc/nginx/http.d/default.conf
|
||||
RUN mkdir -p /run/nginx
|
||||
RUN mkdir -p /var/log/nginx
|
||||
RUN sed -i 's/nobody/nginx/g' /etc/php82/php-fpm.d/www.conf
|
||||
|
||||
# Since requests can trigger conversion, let's give the server enough time to respond
|
||||
RUN sed -i "/max_execution_time/c\max_execution_time=3600" /etc/php82/php.ini
|
||||
RUN sed -i "/max_input_time/c\max_input_time=3600" /etc/php82/php.ini
|
||||
|
||||
WORKDIR /var/www/
|
||||
|
||||
# Volumes to mount
|
||||
#VOLUME /var/lib/influxdb
|
||||
VOLUME /var/www/data
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
ENTRYPOINT ["/etc/start.sh"]
|
||||
73
docker/rootfs/nginx.conf
Normal file
@@ -0,0 +1,73 @@
|
||||
server {
|
||||
listen 80 default_server;
|
||||
|
||||
set $base /var/www;
|
||||
root /var/www/;
|
||||
|
||||
index index.php;
|
||||
|
||||
client_max_body_size 50M;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?url=$request_uri;
|
||||
}
|
||||
|
||||
location ~ /(data|tmp|bin|content-controllers|inc|interfaces|storage-controllers|templates|tools|docker) {
|
||||
deny all;
|
||||
return 404;
|
||||
}
|
||||
|
||||
# logging
|
||||
access_log /var/log/nginx/pictshare/access.log;
|
||||
error_log /var/log/nginx/pictshare/error.log warn;
|
||||
|
||||
location ~ \.php$ {
|
||||
# 404
|
||||
try_files $fastcgi_script_name =404;
|
||||
|
||||
# default fastcgi_params
|
||||
include fastcgi_params;
|
||||
|
||||
# fastcgi settings
|
||||
fastcgi_pass 127.0.0.1:9000;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_buffers 8 16k;
|
||||
fastcgi_buffer_size 32k;
|
||||
fastcgi_max_temp_file_size 0; # caching files to disk while uploading. this will help low-memory devices
|
||||
fastcgi_read_timeout 1d; # we set the timeout to 1 day so big uploads and have enough time to be delivered
|
||||
fastcgi_send_timeout 1d; # it's especially important if you want to use storage controllers like S3 or FTP
|
||||
fastcgi_request_buffering off; # disabbling buffering which will send the uploaded data right to PHP
|
||||
|
||||
# fastcgi params
|
||||
fastcgi_param DOCUMENT_ROOT $realpath_root;
|
||||
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
||||
fastcgi_param PHP_ADMIN_VALUE "open_basedir=$base/:/usr/lib/php/:/tmp/";
|
||||
}
|
||||
|
||||
location /favicon.ico {
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
# security headers
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header Referrer-Policy "no-referrer-when-downgrade" always;
|
||||
add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
|
||||
|
||||
# svg, fonts
|
||||
location ~* \.(?:svgz?|ttf|ttc|otf|eot|woff2?)$ {
|
||||
add_header Access-Control-Allow-Origin "*";
|
||||
expires 7d;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# gzip
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 6;
|
||||
gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss application/atom+xml image/svg+xml;
|
||||
|
||||
}
|
||||
96
docker/rootfs/start.sh
Normal file
@@ -0,0 +1,96 @@
|
||||
#!/bin/bash
|
||||
|
||||
######### functions
|
||||
|
||||
_maxUploadSize() {
|
||||
echo "[i] Setting uploadsize to ${MAX_UPLOAD_SIZE}M"
|
||||
|
||||
sed -i "/post_max_size/c\post_max_size=${MAX_UPLOAD_SIZE}M" /etc/php82/php.ini
|
||||
sed -i "/upload_max_filesize/c\upload_max_filesize=${MAX_UPLOAD_SIZE}M" /etc/php82/php.ini
|
||||
|
||||
# set error reporting no notices, no warnings
|
||||
sed -i "/^error_reporting/c\error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_WARNING & ~E_NOTICE" /etc/php82/php.ini
|
||||
|
||||
sed -i -e "s/50M/${MAX_UPLOAD_SIZE}M/g" /etc/nginx/http.d/default.conf
|
||||
|
||||
MAX_RAM=$((MAX_UPLOAD_SIZE + 30)) # 30megs more than the upload size
|
||||
echo "[i] Also changing memory limit of PHP to ${MAX_RAM}M"
|
||||
sed -i -e "s/128M/${MAX_RAM}M/g" /etc/php82/php.ini
|
||||
sed -i "/memory_limit/c\memory_limit=${MAX_RAM}M" /etc/php82/php.ini
|
||||
}
|
||||
|
||||
_filePermissions() {
|
||||
chown -R nginx:nginx /var/www
|
||||
touch data/sha1.csv
|
||||
chown nginx:nginx data/sha1.csv
|
||||
}
|
||||
|
||||
_buildConfig() {
|
||||
echo "<?php"
|
||||
echo "define('URL', '${URL:-}');"
|
||||
echo "define('TITLE', '${TITLE:-PictShare}');"
|
||||
echo "define('ALLOWED_SUBNET', '${ALLOWED_SUBNET:-}');"
|
||||
echo "define('CONTENTCONTROLLERS', '${CONTENTCONTROLLERS:-}');"
|
||||
echo "define('MASTER_DELETE_CODE', '${MASTER_DELETE_CODE:-}');"
|
||||
echo "define('MASTER_DELETE_IP', '${MASTER_DELETE_IP:-}');"
|
||||
echo "define('UPLOAD_FORM_LOCATION', '${UPLOAD_FORM_LOCATION:-}');"
|
||||
echo "define('UPLOAD_CODE', '${UPLOAD_CODE:-}');"
|
||||
echo "define('LOG_UPLOADER', ${LOG_UPLOADER:-false});"
|
||||
echo "define('MAX_RESIZED_IMAGES',${MAX_RESIZED_IMAGES:--1});"
|
||||
echo "define('ALLOW_BLOATING', ${ALLOW_BLOATING:-false});"
|
||||
echo "define('SHOW_ERRORS', ${SHOW_ERRORS:-false});"
|
||||
echo "define('JPEG_COMPRESSION', ${JPEG_COMPRESSION:-90});"
|
||||
echo "define('PNG_COMPRESSION', ${PNG_COMPRESSION:-6});"
|
||||
echo "define('ALT_FOLDER', '${ALT_FOLDER:-}');"
|
||||
echo "define('S3_BUCKET', '${S3_BUCKET:-}');"
|
||||
echo "define('S3_ACCESS_KEY', '${S3_ACCESS_KEY:-}');"
|
||||
echo "define('S3_SECRET_KEY', '${S3_SECRET_KEY:-}');"
|
||||
echo "define('S3_ENDPOINT', '${S3_ENDPOINT:-}');"
|
||||
echo "define('S3_REGION', '${S3_REGION:-}');"
|
||||
echo "define('FTP_SERVER', '${FTP_SERVER:-}');"
|
||||
echo "define('FTP_PORT', ${FTP_PORT:-21});"
|
||||
echo "define('FTP_USER', '${FTP_USER:-}');"
|
||||
echo "define('FTP_PASS', '${FTP_PASS:-}');"
|
||||
echo "define('FTP_PASSIVEMODE', ${FTP_PASSIVEMODE:-true});"
|
||||
echo "define('FTP_SSL', ${FTP_SSL:-false});"
|
||||
echo "define('FTP_BASEDIR', '${FTP_BASEDIR:-}');"
|
||||
echo "define('ENCRYPTION_KEY', '${ENCRYPTION_KEY:-}');"
|
||||
echo "define('FFMPEG_BINARY', '${FFMPEG_BINARY:-/usr/bin/ffmpeg}');"
|
||||
echo "define('ALWAYS_WEBP', ${ALWAYS_WEBP:-false});"
|
||||
echo "define('ALLOWED_DOMAINS', '${ALLOWED_DOMAINS:-}');"
|
||||
echo "define('SPLIT_DATA_DIR', ${SPLIT_DATA_DIR:-false});"
|
||||
}
|
||||
|
||||
|
||||
|
||||
######### main
|
||||
|
||||
echo 'Starting Pictshare'
|
||||
|
||||
cd /var/www/
|
||||
|
||||
if [[ ${MAX_UPLOAD_SIZE:=100} =~ ^[0-9]+$ ]]; then
|
||||
_maxUploadSize
|
||||
fi
|
||||
|
||||
# run _filePermissions function unless SKIP_FILEPERMISSIONS is set to true
|
||||
if [[ ${SKIP_FILEPERMISSIONS:=false} != true ]]; then
|
||||
_filePermissions
|
||||
fi
|
||||
|
||||
echo ' [+] Starting php'
|
||||
php-fpm82
|
||||
|
||||
echo ' [+] Creating config'
|
||||
|
||||
_buildConfig > inc/config.inc.php
|
||||
|
||||
echo ' [+] Starting nginx'
|
||||
|
||||
mkdir -p /var/log/nginx/pictshare
|
||||
touch /var/log/nginx/pictshare/access.log
|
||||
touch /var/log/nginx/pictshare/error.log
|
||||
|
||||
nginx
|
||||
|
||||
tail -f /var/log/nginx/pictshare/*.log
|
||||
1
inc/.gitignore
vendored
@@ -1,2 +1 @@
|
||||
# don#t track the active config
|
||||
config.inc.php
|
||||
1507
inc/core.php
85
inc/encryption.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
class Encryption{
|
||||
|
||||
/**
|
||||
* $key must have been generated at some point with: random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES)
|
||||
*/
|
||||
function encryptText($text,$key)
|
||||
{
|
||||
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
|
||||
$ciphertext = sodium_crypto_secretbox($text, $nonce, $key);
|
||||
$encoded = base64_encode($nonce . $ciphertext);
|
||||
return $encoded;
|
||||
}
|
||||
|
||||
/**
|
||||
* $key must have been generated at some point with: random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES)
|
||||
*/
|
||||
function decryptText($encoded,$key)
|
||||
{
|
||||
$decoded = base64_decode($encoded);
|
||||
$nonce = mb_substr($decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
|
||||
|
||||
|
||||
$ciphertext = mb_substr($decoded, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');
|
||||
$plaintext = sodium_crypto_secretbox_open($ciphertext, $nonce, $key);
|
||||
return $plaintext;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* $key must have been generated at some point with: sodium_crypto_secretstream_xchacha20poly1305_keygen();
|
||||
*/
|
||||
function encryptFile($infile,$enc_outfile,$key)
|
||||
{
|
||||
$chunk_size = 4096;
|
||||
|
||||
$fd_in = fopen($infile, 'rb');
|
||||
$fd_out = fopen($enc_outfile, 'wb');
|
||||
|
||||
list($stream, $header) = sodium_crypto_secretstream_xchacha20poly1305_init_push($key);
|
||||
|
||||
fwrite($fd_out, $header);
|
||||
|
||||
$tag = SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_MESSAGE;
|
||||
do {
|
||||
$chunk = fread($fd_in, $chunk_size);
|
||||
if (feof($fd_in)) {
|
||||
$tag = SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL;
|
||||
}
|
||||
$encrypted_chunk = sodium_crypto_secretstream_xchacha20poly1305_push($stream, $chunk, '', $tag);
|
||||
fwrite($fd_out, $encrypted_chunk);
|
||||
} while ($tag !== SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL);
|
||||
|
||||
fclose($fd_out);
|
||||
fclose($fd_in);
|
||||
}
|
||||
|
||||
/**
|
||||
* $key must have been generated at some point with: sodium_crypto_secretstream_xchacha20poly1305_keygen();
|
||||
*/
|
||||
function decryptFile($enc_infile,$outfile,$key)
|
||||
{
|
||||
$fd_in = fopen($enc_infile, 'rb');
|
||||
$fd_out = fopen($outfile, 'wb');
|
||||
$chunk_size = 4096;
|
||||
|
||||
$header = fread($fd_in, SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES);
|
||||
|
||||
$stream = sodium_crypto_secretstream_xchacha20poly1305_init_pull($header, $key);
|
||||
do {
|
||||
$chunk = fread($fd_in, $chunk_size + SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES);
|
||||
list($decrypted_chunk, $tag) = sodium_crypto_secretstream_xchacha20poly1305_pull($stream, $chunk);
|
||||
fwrite($fd_out, $decrypted_chunk);
|
||||
} while (!feof($fd_in) && $tag !== SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL);
|
||||
$ok = feof($fd_in);
|
||||
|
||||
fclose($fd_out);
|
||||
fclose($fd_in);
|
||||
|
||||
if (!$ok) {
|
||||
die('Invalid/corrupted input');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,86 +1,25 @@
|
||||
<?php
|
||||
|
||||
//Set title for your image and mp4 hosting service
|
||||
define('TITLE', 'PictShare');
|
||||
|
||||
// PNG level from 0 (largest file) to
|
||||
// 9 (smallest file). Note that this doesn't affect
|
||||
// quality, only file size and CPU
|
||||
define('PNG_COMPRESSION', 6);
|
||||
|
||||
// JPG compression percenage from 0 (smallest file, worst quality)
|
||||
// to 100 (large file, best quality)
|
||||
define('JPEG_COMPRESSION', 90);
|
||||
|
||||
//If set, can be added to any image URL to delete the image and all versions of the image
|
||||
//Must be longer than 10 characters
|
||||
//Usage example:
|
||||
// image: https://pictshare.net/b260e36b60.jpg
|
||||
// to delete it, access https://pictshare.net/delete_YOURMASTERDELETECODE/b260e36b60.jpg
|
||||
// Will render one last time, if refreshed won't be on the server anymore
|
||||
define('MASTER_DELETE_CODE', false);
|
||||
|
||||
//if set, the IP, hostname or every device in the IP range (CIDR naming) will be allowed to delete images
|
||||
//by supplying the parameter "delete"
|
||||
//use multiple ips/hostnames/ranges: semicolon seperated
|
||||
//examples:
|
||||
//======
|
||||
//ip: define('MASTER_DELETE_IP', '8.8.8.8');
|
||||
//hostname: define('MASTER_DELETE_IP', 'home.example.com');
|
||||
//ip range: define('MASTER_DELETE_IP', '192.168.0.0/24'); //all IPs from 192.168.0.0 to 192.168.0.255 can delete
|
||||
//multiple: define('MASTER_DELETE_IP', '192.168.0.0/24;my.home.net;4.4.2.2');
|
||||
define('MASTER_DELETE_IP', false);
|
||||
|
||||
//If set, upload form will only be shown on that location
|
||||
//eg: define('UPLOAD_FORM_LOCATION', 'secret/upload'); then the upload form will only be visible
|
||||
//from http://your.domain/secret/upload
|
||||
define('UPLOAD_FORM_LOCATION', false);
|
||||
|
||||
//If set to true, the only page that will be rendered is the upload form
|
||||
//if a wrong link is provided, 404 will be shown instead of the error page
|
||||
//It's meant to be used to hide the fact that you're using pictshare and your site just looks like a content server
|
||||
//use in combination with UPLOAD_FORM_LOCATION for maximum sneakiness
|
||||
define('LOW_PROFILE', false);
|
||||
|
||||
//if set to a string, this string must be provided before upload.
|
||||
//you can set multiple codes by;separating;them;with;semicolons
|
||||
//if set to false, everybody can upload
|
||||
//for API uploads, the GET Variable 'upload_code' must be provided
|
||||
define('UPLOAD_CODE', false);
|
||||
|
||||
//if set to a string, this string must be provided in the URL to use any options (filters, resizes, etc..)
|
||||
//you can set multiple codes by;separating;them;with;semicolons
|
||||
//if set to false, everybody can use options on all images
|
||||
//if image change code is not provided but the requested image (with options) already exists, it will render to the user just fine
|
||||
define('IMAGE_CHANGE_CODE', false);
|
||||
|
||||
// shall we log all uploaders IP addresses?
|
||||
define('LOG_UPLOADER', true);
|
||||
|
||||
//how many resizes may one image have?
|
||||
//-1 = infinite
|
||||
//0 = none
|
||||
define('MAX_RESIZED_IMAGES',20);
|
||||
|
||||
//when the user requests a resize. Can the resized image be bigger than the original?
|
||||
define('ALLOW_BLOATING', false);
|
||||
|
||||
//Force a specific domain for this server. If set to false, will autodetect.
|
||||
//Format: https://your.domain.name/
|
||||
define('FORCE_DOMAIN', false);
|
||||
|
||||
//Shall errors be displayed to the user?
|
||||
//For dev environments: true, in production: false
|
||||
define('SHOW_ERRORS', false);
|
||||
|
||||
|
||||
//for scalability reasons you might want to upload images to cloud providers
|
||||
//remove comments to use
|
||||
|
||||
/* BACKBLAZE B2 */
|
||||
/* You can find your info here: https://secure.backblaze.com/b2_buckets.htm */
|
||||
//define('BACKBLAZE',true); //true=>use backblaze to upload images, false=>don't
|
||||
//define('BACKBLAZE_ID','');
|
||||
//define('BACKBLAZE_KEY', '');
|
||||
//define('BACKBLAZE_BUCKET_ID', '');
|
||||
//define('BACKBLAZE_BUCKET_NAME', '');
|
||||
<?php
|
||||
/**
|
||||
* All settings that are uncommented are mandatory
|
||||
* Others optional
|
||||
*
|
||||
* For all possible config options, check https://github.com/HaschekSolutions/pictshare/blob/master/rtfm/CONFIG.md
|
||||
* or /rtfm/CONFIG.md in your installation
|
||||
*/
|
||||
|
||||
//Use a specific domain for links presented to the user
|
||||
//Format: https://your.domain.name/
|
||||
// MUST HAVE TAILING /
|
||||
define('URL','https://dev.pictshare.net/');
|
||||
|
||||
//define('JPEG_COMPRESSION', 90);
|
||||
//define('FFMPEG_BINARY','');
|
||||
//define('ALT_FOLDER','/ftp/pictshare');
|
||||
//define('ALLOWED_SUBNET','192.168.0.0/24');
|
||||
|
||||
//S3 settings
|
||||
//
|
||||
//define('S3_BUCKET','bucketname');
|
||||
//define('S3_ACCESS_KEY','');
|
||||
//define('S3_SECRET_KEY','');
|
||||
//define('S3_ENDPOINT','http://localhost:9000'); //optional, only if you're using S3 compatible storage like Minio
|
||||
31
index.php
@@ -1,27 +1,22 @@
|
||||
<?php
|
||||
session_cache_limiter("public");
|
||||
$expiry = 90; //days
|
||||
session_cache_expire($expiry * 24 * 60);
|
||||
session_start();
|
||||
// basic path definitions
|
||||
define('DS', DIRECTORY_SEPARATOR);
|
||||
define('ROOT', dirname(__FILE__));
|
||||
define('PATH',((dirname($_SERVER['PHP_SELF'])=='/'||dirname($_SERVER['PHP_SELF'])=='\\'||dirname($_SERVER['PHP_SELF'])=='/index.php'||dirname($_SERVER['PHP_SELF'])=='/backend.php')?'/':dirname($_SERVER['PHP_SELF']).'/'));
|
||||
|
||||
//loading default settings if exist
|
||||
if(!file_exists(ROOT.DS.'inc'.DS.'config.inc.php'))
|
||||
exit('Rename /inc/example.config.inc.php to /inc/config.inc.php first!');
|
||||
include_once(ROOT.DS.'inc'.DS.'config.inc.php');
|
||||
|
||||
if(FORCE_DOMAIN)
|
||||
define('DOMAINPATH',FORCE_DOMAIN);
|
||||
else
|
||||
define('DOMAINPATH',(($_SERVER['HTTPS'])?'https':'http').'://'.$_SERVER['HTTP_HOST']);
|
||||
error_reporting(E_ALL & ~E_NOTICE);
|
||||
if(SHOW_ERRORS)
|
||||
ini_set('display_errors','On');
|
||||
else ini_set('display_errors','Off');
|
||||
|
||||
//loading core and controllers
|
||||
include_once(ROOT.DS.'inc'.DS.'core.php');
|
||||
$url = $_GET['url'];
|
||||
removeMagicQuotes();
|
||||
$GLOBALS['params'] = explode('/', $_GET['url']);
|
||||
callHook();
|
||||
loadAllContentControllers();
|
||||
|
||||
//load external things if existing
|
||||
if(file_exists(ROOT.'/lib/vendor/autoload.php'))
|
||||
require ROOT.'/lib/vendor/autoload.php';
|
||||
|
||||
|
||||
//send the URL to the architect. It'll know what to do
|
||||
$url = $_GET['url']?$_GET['url']:ltrim($_SERVER['REQUEST_URI'],'/');
|
||||
architect($url);
|
||||
45
interfaces/contentcontroller.interface.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Content controller interface for new content types
|
||||
*/
|
||||
|
||||
interface ContentController
|
||||
{
|
||||
/**
|
||||
* When implementing a new content controller, you must specify a constant with the name of "ctype"
|
||||
* This constant will be used to distinguish static controllers (which have files on disk) from dynamic ones (which don't, like the placeholder controller)
|
||||
*
|
||||
* Possible values: 'static' or 'dynamic'
|
||||
*/
|
||||
//const ctype = 'static';
|
||||
|
||||
/** This method will return all file extensions that will be associated with this content type
|
||||
* for example 'pdf' but it could be anything really. You just need a way later to confirm that a type is what it says it is
|
||||
*
|
||||
*
|
||||
* @return array the extensions of files associated with this controller. eg. return array('pdf');
|
||||
*/
|
||||
public function getRegisteredExtensions();
|
||||
|
||||
/** This method will be called whenever the system has to find out if a user requested (existing) hash
|
||||
* belongs to this controller.
|
||||
* In here the content should be rendered or processed like resized or something.
|
||||
* You can decide what it does by working with the $url array which gives you every element in the URL
|
||||
* Does not need to return anything for example you can just set the header and print your data right away
|
||||
*
|
||||
* @param string $hash the hash (with extension eg '5saB2.pdf') of the file this controller will work with
|
||||
* @param array $url contains all URL elements exploded with '/' so you can do your magic.
|
||||
*/
|
||||
public function handleHash($hash,$url);
|
||||
|
||||
/** This method will be called if the upload script detects the content of a newly uploaded file as one of the
|
||||
* extensions registered at "getRegisteredExtensions".
|
||||
* For Example if someone uploads a PDF and getRegisteredExtensions has registered "pdf", then this method of this
|
||||
* controller will be called
|
||||
*
|
||||
* @param string $tmpfile is the location on disk of the temp file that was uploaded. It is your job to put it somewhere, your handleHash method will find it again
|
||||
* @param array $hash (optional) if you want your upload to have a certain hash then add it here. This allows for user chosen hashes
|
||||
*/
|
||||
public function handleUpload($tmpfile,$hash=false);
|
||||
}
|
||||
69
interfaces/storagecontroller.interface.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* StorageController interface
|
||||
*
|
||||
* Must be implemented by all storage systems
|
||||
*/
|
||||
|
||||
interface StorageController
|
||||
{
|
||||
/**
|
||||
* Checks if this storage system is enabled.
|
||||
* For example check if all depenencies are met
|
||||
* or config vars are set
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function isEnabled();
|
||||
|
||||
/**
|
||||
* Is fired whenever a hash is not found locally
|
||||
* Use this to look in your storage system for the file
|
||||
*
|
||||
* @param string $hash is the hash of the file requested
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function hashExists($hash);
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array of all items in this storage controller
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getItems();
|
||||
|
||||
/**
|
||||
* If a file does exist in this storage system, then this method should
|
||||
* get the file and put it in the default data directory
|
||||
*
|
||||
* The file should be placed in /data/$hash/$hash where the first $hash is obviously
|
||||
* a folder that you might have to create first before putting the file in
|
||||
*
|
||||
* @param string $hash is the hash of the file that should be pulled from this storage system
|
||||
* @param string $location is the location where the downloaded file should be placed
|
||||
*
|
||||
* @return bool true if successful
|
||||
*/
|
||||
function pullFile($hash,$location);
|
||||
|
||||
/**
|
||||
* Whenever a new file is uploaded this method will be called
|
||||
* You should then upload it or do whatever your storage system is meant to do with new files
|
||||
*
|
||||
* @param string $hash is the hash of the new file. The file path of this file is always getDataDir().DS.$hash.DS.$hash
|
||||
*
|
||||
* @return bool true if successful
|
||||
*/
|
||||
function pushFile($source,$hash);
|
||||
|
||||
/**
|
||||
* If deletion of a file is requested, this method is called
|
||||
*
|
||||
* @param string $hash is the hash of the file. Delete this hash from your storage system
|
||||
*
|
||||
* @return bool true if successful
|
||||
*/
|
||||
function deleteFile($hash);
|
||||
}
|
||||
3530
js/dropzone.js
Normal file
2
js/highlight.pack.js
Normal file
40
js/pictshare.js
Normal file
@@ -0,0 +1,40 @@
|
||||
Dropzone.autoDiscover = false;
|
||||
|
||||
$(function () {
|
||||
var myDropzone = new Dropzone("#dropzone");
|
||||
//console.log(myDropzone.options);
|
||||
if (maxUploadFileSize !== undefined)
|
||||
myDropzone.options.maxFilesize = maxUploadFileSize;
|
||||
myDropzone.options.timeout = 0,
|
||||
myDropzone.on("sending", function(file, xhr, formData) {
|
||||
if(document.getElementById("uploadcode"))
|
||||
formData.append("uploadcode", document.getElementById("uploadcode").value);
|
||||
});
|
||||
myDropzone.on('error', function(file, response) {
|
||||
alert("Error: "+response.reason);
|
||||
});
|
||||
myDropzone.on("success", function (file, response) {
|
||||
console.log("raw response: " + response);
|
||||
if (response == null || response == "null")
|
||||
$("#uploadinfo").append("<div class='alert alert-danger' role='alert'><strong>Error uploading " + file.name + "</strong><br/>Reason is unknown :(</div>")
|
||||
else {
|
||||
var o = response;
|
||||
if (o.status == 'ok')
|
||||
$("#uploadinfo").append("<div class='alert alert-success' role='alert'><strong>" + file.name + "</strong> uploaded as <a target='_blank' href='/" + o.hash + "'>" + o.hash + "</a><br/>URL: <a target='_blank' href='" + o.url + "'>" + o.url + "</a> <button class='btn btn-xs' onClick='navigator.clipboard.writeText(\"" + o.url + "\");'>Copy URL</button></div>")
|
||||
else if (o.status == 'err')
|
||||
$("#uploadinfo").append("<div class='alert alert-danger' role='alert'><strong>Error uploading " + file.name + "</strong><br/>Reason: " + o.reason + "</div>")
|
||||
console.log(o)
|
||||
}
|
||||
});
|
||||
|
||||
document.onpaste = function (event) {
|
||||
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
|
||||
for (index in items) {
|
||||
var item = items[index];
|
||||
if (item.kind === 'file') {
|
||||
// adds the file to your dropzone instance
|
||||
myDropzone.addFile(item.getAsFile())
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
99
js/styles/a11y-dark.css
Normal file
@@ -0,0 +1,99 @@
|
||||
/* a11y-dark theme */
|
||||
/* Based on the Tomorrow Night Eighties theme: https://github.com/isagalaev/highlight.js/blob/master/src/styles/tomorrow-night-eighties.css */
|
||||
/* @author: ericwbailey */
|
||||
|
||||
/* Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #d4d0ab;
|
||||
}
|
||||
|
||||
/* Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class,
|
||||
.hljs-regexp,
|
||||
.hljs-deletion {
|
||||
color: #ffa07a;
|
||||
}
|
||||
|
||||
/* Orange */
|
||||
.hljs-number,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params,
|
||||
.hljs-meta,
|
||||
.hljs-link {
|
||||
color: #f5ab35;
|
||||
}
|
||||
|
||||
/* Yellow */
|
||||
.hljs-attribute {
|
||||
color: #ffd700;
|
||||
}
|
||||
|
||||
/* Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-addition {
|
||||
color: #abe338;
|
||||
}
|
||||
|
||||
/* Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #00e0e0;
|
||||
}
|
||||
|
||||
/* Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #dcc6e0;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #2b2b2b;
|
||||
color: #f8f8f2;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@media screen and (-ms-high-contrast: active) {
|
||||
.hljs-addition,
|
||||
.hljs-attribute,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-bullet,
|
||||
.hljs-comment,
|
||||
.hljs-link,
|
||||
.hljs-literal,
|
||||
.hljs-meta,
|
||||
.hljs-number,
|
||||
.hljs-params,
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-type,
|
||||
.hljs-quote {
|
||||
color: highlight;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
99
js/styles/a11y-light.css
Normal file
@@ -0,0 +1,99 @@
|
||||
/* a11y-light theme */
|
||||
/* Based on the Tomorrow Night Eighties theme: https://github.com/isagalaev/highlight.js/blob/master/src/styles/tomorrow-night-eighties.css */
|
||||
/* @author: ericwbailey */
|
||||
|
||||
/* Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #696969;
|
||||
}
|
||||
|
||||
/* Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class,
|
||||
.hljs-regexp,
|
||||
.hljs-deletion {
|
||||
color: #d91e18;
|
||||
}
|
||||
|
||||
/* Orange */
|
||||
.hljs-number,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params,
|
||||
.hljs-meta,
|
||||
.hljs-link {
|
||||
color: #aa5d00;
|
||||
}
|
||||
|
||||
/* Yellow */
|
||||
.hljs-attribute {
|
||||
color: #aa5d00;
|
||||
}
|
||||
|
||||
/* Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-addition {
|
||||
color: #008000;
|
||||
}
|
||||
|
||||
/* Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #007faa;
|
||||
}
|
||||
|
||||
/* Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #7928a1;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #fefefe;
|
||||
color: #545454;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@media screen and (-ms-high-contrast: active) {
|
||||
.hljs-addition,
|
||||
.hljs-attribute,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-bullet,
|
||||
.hljs-comment,
|
||||
.hljs-link,
|
||||
.hljs-literal,
|
||||
.hljs-meta,
|
||||
.hljs-number,
|
||||
.hljs-params,
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-type,
|
||||
.hljs-quote {
|
||||
color: highlight;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
108
js/styles/agate.css
Normal file
@@ -0,0 +1,108 @@
|
||||
/*!
|
||||
* Agate by Taufik Nurrohman <https://github.com/tovic>
|
||||
* ----------------------------------------------------
|
||||
*
|
||||
* #ade5fc
|
||||
* #a2fca2
|
||||
* #c6b4f0
|
||||
* #d36363
|
||||
* #fcc28c
|
||||
* #fc9b9b
|
||||
* #ffa
|
||||
* #fff
|
||||
* #333
|
||||
* #62c8f3
|
||||
* #888
|
||||
*
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: #333;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.hljs-name,
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-code,
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-tag {
|
||||
color: #62c8f3;
|
||||
}
|
||||
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #ade5fc;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-bullet {
|
||||
color: #a2fca2;
|
||||
}
|
||||
|
||||
.hljs-type,
|
||||
.hljs-title,
|
||||
.hljs-section,
|
||||
.hljs-attribute,
|
||||
.hljs-quote,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name {
|
||||
color: #ffa;
|
||||
}
|
||||
|
||||
.hljs-number,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #d36363;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-literal {
|
||||
color: #fcc28c;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-deletion,
|
||||
.hljs-code {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.hljs-regexp,
|
||||
.hljs-link {
|
||||
color: #c6b4f0;
|
||||
}
|
||||
|
||||
.hljs-meta {
|
||||
color: #fc9b9b;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background-color: #fc9b9b;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
background-color: #a2fca2;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.hljs a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.hljs a:focus,
|
||||
.hljs a:hover {
|
||||
color: inherit;
|
||||
text-decoration: underline;
|
||||
}
|
||||
89
js/styles/an-old-hope.css
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
|
||||
An Old Hope – Star Wars Syntax (c) Gustavo Costa <gusbemacbe@gmail.com>
|
||||
Original theme - Ocean Dark Theme – by https://github.com/gavsiu
|
||||
Based on Jesse Leite's Atom syntax theme 'An Old Hope' – https://github.com/JesseLeite/an-old-hope-syntax-atom
|
||||
|
||||
*/
|
||||
|
||||
/* Death Star Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote
|
||||
{
|
||||
color: #B6B18B;
|
||||
}
|
||||
|
||||
/* Darth Vader */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class,
|
||||
.hljs-regexp,
|
||||
.hljs-deletion
|
||||
{
|
||||
color: #EB3C54;
|
||||
}
|
||||
|
||||
/* Threepio */
|
||||
.hljs-number,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params,
|
||||
.hljs-meta,
|
||||
.hljs-link
|
||||
{
|
||||
color: #E7CE56;
|
||||
}
|
||||
|
||||
/* Luke Skywalker */
|
||||
.hljs-attribute
|
||||
{
|
||||
color: #EE7C2B;
|
||||
}
|
||||
|
||||
/* Obi Wan Kenobi */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-addition
|
||||
{
|
||||
color: #4FB4D7;
|
||||
}
|
||||
|
||||
/* Yoda */
|
||||
.hljs-title,
|
||||
.hljs-section
|
||||
{
|
||||
color: #78BB65;
|
||||
}
|
||||
|
||||
/* Mace Windu */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag
|
||||
{
|
||||
color: #B45EA4;
|
||||
}
|
||||
|
||||
/* Millenium Falcon */
|
||||
.hljs
|
||||
{
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #1C1D21;
|
||||
color: #c0c5ce;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
66
js/styles/androidstudio.css
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
Date: 24 Fev 2015
|
||||
Author: Pedro Oliveira <kanytu@gmail . com>
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
color: #a9b7c6;
|
||||
background: #282b2e;
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-number,
|
||||
.hljs-literal,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #6897BB;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-deletion {
|
||||
color: #cc7832;
|
||||
}
|
||||
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-link {
|
||||
color: #629755;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #808080;
|
||||
}
|
||||
|
||||
.hljs-meta {
|
||||
color: #bbb529;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-attribute,
|
||||
.hljs-addition {
|
||||
color: #6A8759;
|
||||
}
|
||||
|
||||
.hljs-section,
|
||||
.hljs-title,
|
||||
.hljs-type {
|
||||
color: #ffc66d;
|
||||
}
|
||||
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #e8bf6a;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
88
js/styles/arduino-light.css
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
|
||||
Arduino® Light Theme - Stefania Mellai <s.mellai@arduino.cc>
|
||||
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: #FFFFFF;
|
||||
}
|
||||
|
||||
.hljs,
|
||||
.hljs-subst {
|
||||
color: #434f54;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-attribute,
|
||||
.hljs-selector-tag,
|
||||
.hljs-doctag,
|
||||
.hljs-name {
|
||||
color: #00979D;
|
||||
}
|
||||
|
||||
.hljs-built_in,
|
||||
.hljs-literal,
|
||||
.hljs-bullet,
|
||||
.hljs-code,
|
||||
.hljs-addition {
|
||||
color: #D35400;
|
||||
}
|
||||
|
||||
.hljs-regexp,
|
||||
.hljs-symbol,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-link,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo {
|
||||
color: #00979D;
|
||||
}
|
||||
|
||||
.hljs-type,
|
||||
.hljs-string,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class,
|
||||
.hljs-quote,
|
||||
.hljs-template-tag,
|
||||
.hljs-deletion {
|
||||
color: #005C5F;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #880000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-comment {
|
||||
color: rgba(149,165,166,.8);
|
||||
}
|
||||
|
||||
.hljs-meta-keyword {
|
||||
color: #728E00;
|
||||
}
|
||||
|
||||
.hljs-meta {
|
||||
color: #728E00;
|
||||
color: #434f54;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-function {
|
||||
color: #728E00;
|
||||
}
|
||||
|
||||
.hljs-number {
|
||||
color: #8A7B52;
|
||||
}
|
||||
73
js/styles/arta.css
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
Date: 17.V.2011
|
||||
Author: pumbur <pumbur@pumbur.net>
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: #222;
|
||||
}
|
||||
|
||||
.hljs,
|
||||
.hljs-subst {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.hljs-section {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote,
|
||||
.hljs-meta {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-regexp {
|
||||
color: #ffcc33;
|
||||
}
|
||||
|
||||
.hljs-number,
|
||||
.hljs-addition {
|
||||
color: #00cc66;
|
||||
}
|
||||
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-link {
|
||||
color: #32aaee;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #6644aa;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-variable,
|
||||
.hljs-deletion,
|
||||
.hljs-template-tag {
|
||||
color: #bb1166;
|
||||
}
|
||||
|
||||
.hljs-section,
|
||||
.hljs-doctag,
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
45
js/styles/ascetic.css
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
|
||||
Original style from softwaremaniacs.org (c) Ivan Sagalaev <Maniac@SoftwareManiacs.Org>
|
||||
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-section,
|
||||
.hljs-addition,
|
||||
.hljs-attribute,
|
||||
.hljs-link {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote,
|
||||
.hljs-meta,
|
||||
.hljs-deletion {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-section,
|
||||
.hljs-name,
|
||||
.hljs-type,
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
83
js/styles/atelier-cave-dark.css
Normal file
@@ -0,0 +1,83 @@
|
||||
/* Base16 Atelier Cave Dark - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Cave Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #7e7887;
|
||||
}
|
||||
|
||||
/* Atelier-Cave Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #be4678;
|
||||
}
|
||||
|
||||
/* Atelier-Cave Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #aa573c;
|
||||
}
|
||||
|
||||
/* Atelier-Cave Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #2a9292;
|
||||
}
|
||||
|
||||
/* Atelier-Cave Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #576ddb;
|
||||
}
|
||||
|
||||
/* Atelier-Cave Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #955ae7;
|
||||
}
|
||||
|
||||
.hljs-deletion,
|
||||
.hljs-addition {
|
||||
color: #19171c;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background-color: #be4678;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
background-color: #2a9292;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #19171c;
|
||||
color: #8b8792;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
85
js/styles/atelier-cave-light.css
Normal file
@@ -0,0 +1,85 @@
|
||||
/* Base16 Atelier Cave Light - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Cave Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #655f6d;
|
||||
}
|
||||
|
||||
/* Atelier-Cave Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #be4678;
|
||||
}
|
||||
|
||||
/* Atelier-Cave Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #aa573c;
|
||||
}
|
||||
|
||||
/* Atelier-Cave Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #2a9292;
|
||||
}
|
||||
|
||||
/* Atelier-Cave Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #576ddb;
|
||||
}
|
||||
|
||||
/* Atelier-Cave Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #955ae7;
|
||||
}
|
||||
|
||||
.hljs-deletion,
|
||||
.hljs-addition {
|
||||
color: #19171c;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background-color: #be4678;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
background-color: #2a9292;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #efecf4;
|
||||
color: #585260;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
69
js/styles/atelier-dune-dark.css
Normal file
@@ -0,0 +1,69 @@
|
||||
/* Base16 Atelier Dune Dark - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Dune Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #999580;
|
||||
}
|
||||
|
||||
/* Atelier-Dune Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #d73737;
|
||||
}
|
||||
|
||||
/* Atelier-Dune Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #b65611;
|
||||
}
|
||||
|
||||
/* Atelier-Dune Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #60ac39;
|
||||
}
|
||||
|
||||
/* Atelier-Dune Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #6684e1;
|
||||
}
|
||||
|
||||
/* Atelier-Dune Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #b854d4;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #20201d;
|
||||
color: #a6a28c;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
69
js/styles/atelier-dune-light.css
Normal file
@@ -0,0 +1,69 @@
|
||||
/* Base16 Atelier Dune Light - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Dune Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #7d7a68;
|
||||
}
|
||||
|
||||
/* Atelier-Dune Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #d73737;
|
||||
}
|
||||
|
||||
/* Atelier-Dune Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #b65611;
|
||||
}
|
||||
|
||||
/* Atelier-Dune Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #60ac39;
|
||||
}
|
||||
|
||||
/* Atelier-Dune Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #6684e1;
|
||||
}
|
||||
|
||||
/* Atelier-Dune Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #b854d4;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #fefbec;
|
||||
color: #6e6b5e;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
84
js/styles/atelier-estuary-dark.css
Normal file
@@ -0,0 +1,84 @@
|
||||
/* Base16 Atelier Estuary Dark - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/estuary) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Estuary Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #878573;
|
||||
}
|
||||
|
||||
/* Atelier-Estuary Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #ba6236;
|
||||
}
|
||||
|
||||
/* Atelier-Estuary Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #ae7313;
|
||||
}
|
||||
|
||||
/* Atelier-Estuary Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #7d9726;
|
||||
}
|
||||
|
||||
/* Atelier-Estuary Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #36a166;
|
||||
}
|
||||
|
||||
/* Atelier-Estuary Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #5f9182;
|
||||
}
|
||||
|
||||
.hljs-deletion,
|
||||
.hljs-addition {
|
||||
color: #22221b;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background-color: #ba6236;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
background-color: #7d9726;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #22221b;
|
||||
color: #929181;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
84
js/styles/atelier-estuary-light.css
Normal file
@@ -0,0 +1,84 @@
|
||||
/* Base16 Atelier Estuary Light - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/estuary) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Estuary Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #6c6b5a;
|
||||
}
|
||||
|
||||
/* Atelier-Estuary Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #ba6236;
|
||||
}
|
||||
|
||||
/* Atelier-Estuary Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #ae7313;
|
||||
}
|
||||
|
||||
/* Atelier-Estuary Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #7d9726;
|
||||
}
|
||||
|
||||
/* Atelier-Estuary Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #36a166;
|
||||
}
|
||||
|
||||
/* Atelier-Estuary Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #5f9182;
|
||||
}
|
||||
|
||||
.hljs-deletion,
|
||||
.hljs-addition {
|
||||
color: #22221b;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background-color: #ba6236;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
background-color: #7d9726;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #f4f3ec;
|
||||
color: #5f5e4e;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
69
js/styles/atelier-forest-dark.css
Normal file
@@ -0,0 +1,69 @@
|
||||
/* Base16 Atelier Forest Dark - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/forest) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Forest Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #9c9491;
|
||||
}
|
||||
|
||||
/* Atelier-Forest Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #f22c40;
|
||||
}
|
||||
|
||||
/* Atelier-Forest Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #df5320;
|
||||
}
|
||||
|
||||
/* Atelier-Forest Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #7b9726;
|
||||
}
|
||||
|
||||
/* Atelier-Forest Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #407ee7;
|
||||
}
|
||||
|
||||
/* Atelier-Forest Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #6666ea;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #1b1918;
|
||||
color: #a8a19f;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
69
js/styles/atelier-forest-light.css
Normal file
@@ -0,0 +1,69 @@
|
||||
/* Base16 Atelier Forest Light - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/forest) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Forest Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #766e6b;
|
||||
}
|
||||
|
||||
/* Atelier-Forest Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #f22c40;
|
||||
}
|
||||
|
||||
/* Atelier-Forest Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #df5320;
|
||||
}
|
||||
|
||||
/* Atelier-Forest Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #7b9726;
|
||||
}
|
||||
|
||||
/* Atelier-Forest Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #407ee7;
|
||||
}
|
||||
|
||||
/* Atelier-Forest Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #6666ea;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #f1efee;
|
||||
color: #68615e;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
69
js/styles/atelier-heath-dark.css
Normal file
@@ -0,0 +1,69 @@
|
||||
/* Base16 Atelier Heath Dark - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/heath) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Heath Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #9e8f9e;
|
||||
}
|
||||
|
||||
/* Atelier-Heath Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #ca402b;
|
||||
}
|
||||
|
||||
/* Atelier-Heath Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #a65926;
|
||||
}
|
||||
|
||||
/* Atelier-Heath Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #918b3b;
|
||||
}
|
||||
|
||||
/* Atelier-Heath Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #516aec;
|
||||
}
|
||||
|
||||
/* Atelier-Heath Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #7b59c0;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #1b181b;
|
||||
color: #ab9bab;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
69
js/styles/atelier-heath-light.css
Normal file
@@ -0,0 +1,69 @@
|
||||
/* Base16 Atelier Heath Light - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/heath) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Heath Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #776977;
|
||||
}
|
||||
|
||||
/* Atelier-Heath Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #ca402b;
|
||||
}
|
||||
|
||||
/* Atelier-Heath Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #a65926;
|
||||
}
|
||||
|
||||
/* Atelier-Heath Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #918b3b;
|
||||
}
|
||||
|
||||
/* Atelier-Heath Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #516aec;
|
||||
}
|
||||
|
||||
/* Atelier-Heath Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #7b59c0;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #f7f3f7;
|
||||
color: #695d69;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
69
js/styles/atelier-lakeside-dark.css
Normal file
@@ -0,0 +1,69 @@
|
||||
/* Base16 Atelier Lakeside Dark - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/lakeside) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Lakeside Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #7195a8;
|
||||
}
|
||||
|
||||
/* Atelier-Lakeside Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #d22d72;
|
||||
}
|
||||
|
||||
/* Atelier-Lakeside Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #935c25;
|
||||
}
|
||||
|
||||
/* Atelier-Lakeside Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #568c3b;
|
||||
}
|
||||
|
||||
/* Atelier-Lakeside Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #257fad;
|
||||
}
|
||||
|
||||
/* Atelier-Lakeside Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #6b6bb8;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #161b1d;
|
||||
color: #7ea2b4;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
69
js/styles/atelier-lakeside-light.css
Normal file
@@ -0,0 +1,69 @@
|
||||
/* Base16 Atelier Lakeside Light - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/lakeside) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Lakeside Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #5a7b8c;
|
||||
}
|
||||
|
||||
/* Atelier-Lakeside Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #d22d72;
|
||||
}
|
||||
|
||||
/* Atelier-Lakeside Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #935c25;
|
||||
}
|
||||
|
||||
/* Atelier-Lakeside Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #568c3b;
|
||||
}
|
||||
|
||||
/* Atelier-Lakeside Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #257fad;
|
||||
}
|
||||
|
||||
/* Atelier-Lakeside Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #6b6bb8;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #ebf8ff;
|
||||
color: #516d7b;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
84
js/styles/atelier-plateau-dark.css
Normal file
@@ -0,0 +1,84 @@
|
||||
/* Base16 Atelier Plateau Dark - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/plateau) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Plateau Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #7e7777;
|
||||
}
|
||||
|
||||
/* Atelier-Plateau Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #ca4949;
|
||||
}
|
||||
|
||||
/* Atelier-Plateau Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #b45a3c;
|
||||
}
|
||||
|
||||
/* Atelier-Plateau Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #4b8b8b;
|
||||
}
|
||||
|
||||
/* Atelier-Plateau Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #7272ca;
|
||||
}
|
||||
|
||||
/* Atelier-Plateau Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #8464c4;
|
||||
}
|
||||
|
||||
.hljs-deletion,
|
||||
.hljs-addition {
|
||||
color: #1b1818;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background-color: #ca4949;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
background-color: #4b8b8b;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #1b1818;
|
||||
color: #8a8585;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
84
js/styles/atelier-plateau-light.css
Normal file
@@ -0,0 +1,84 @@
|
||||
/* Base16 Atelier Plateau Light - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/plateau) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Plateau Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #655d5d;
|
||||
}
|
||||
|
||||
/* Atelier-Plateau Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #ca4949;
|
||||
}
|
||||
|
||||
/* Atelier-Plateau Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #b45a3c;
|
||||
}
|
||||
|
||||
/* Atelier-Plateau Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #4b8b8b;
|
||||
}
|
||||
|
||||
/* Atelier-Plateau Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #7272ca;
|
||||
}
|
||||
|
||||
/* Atelier-Plateau Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #8464c4;
|
||||
}
|
||||
|
||||
.hljs-deletion,
|
||||
.hljs-addition {
|
||||
color: #1b1818;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background-color: #ca4949;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
background-color: #4b8b8b;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #f4ecec;
|
||||
color: #585050;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
84
js/styles/atelier-savanna-dark.css
Normal file
@@ -0,0 +1,84 @@
|
||||
/* Base16 Atelier Savanna Dark - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/savanna) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Savanna Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #78877d;
|
||||
}
|
||||
|
||||
/* Atelier-Savanna Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #b16139;
|
||||
}
|
||||
|
||||
/* Atelier-Savanna Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #9f713c;
|
||||
}
|
||||
|
||||
/* Atelier-Savanna Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #489963;
|
||||
}
|
||||
|
||||
/* Atelier-Savanna Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #478c90;
|
||||
}
|
||||
|
||||
/* Atelier-Savanna Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #55859b;
|
||||
}
|
||||
|
||||
.hljs-deletion,
|
||||
.hljs-addition {
|
||||
color: #171c19;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background-color: #b16139;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
background-color: #489963;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #171c19;
|
||||
color: #87928a;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
84
js/styles/atelier-savanna-light.css
Normal file
@@ -0,0 +1,84 @@
|
||||
/* Base16 Atelier Savanna Light - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/savanna) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Savanna Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #5f6d64;
|
||||
}
|
||||
|
||||
/* Atelier-Savanna Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #b16139;
|
||||
}
|
||||
|
||||
/* Atelier-Savanna Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #9f713c;
|
||||
}
|
||||
|
||||
/* Atelier-Savanna Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #489963;
|
||||
}
|
||||
|
||||
/* Atelier-Savanna Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #478c90;
|
||||
}
|
||||
|
||||
/* Atelier-Savanna Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #55859b;
|
||||
}
|
||||
|
||||
.hljs-deletion,
|
||||
.hljs-addition {
|
||||
color: #171c19;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background-color: #b16139;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
background-color: #489963;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #ecf4ee;
|
||||
color: #526057;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
69
js/styles/atelier-seaside-dark.css
Normal file
@@ -0,0 +1,69 @@
|
||||
/* Base16 Atelier Seaside Dark - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/seaside) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Seaside Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #809980;
|
||||
}
|
||||
|
||||
/* Atelier-Seaside Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #e6193c;
|
||||
}
|
||||
|
||||
/* Atelier-Seaside Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #87711d;
|
||||
}
|
||||
|
||||
/* Atelier-Seaside Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #29a329;
|
||||
}
|
||||
|
||||
/* Atelier-Seaside Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #3d62f5;
|
||||
}
|
||||
|
||||
/* Atelier-Seaside Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #ad2bee;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #131513;
|
||||
color: #8ca68c;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
69
js/styles/atelier-seaside-light.css
Normal file
@@ -0,0 +1,69 @@
|
||||
/* Base16 Atelier Seaside Light - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/seaside) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Seaside Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #687d68;
|
||||
}
|
||||
|
||||
/* Atelier-Seaside Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #e6193c;
|
||||
}
|
||||
|
||||
/* Atelier-Seaside Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #87711d;
|
||||
}
|
||||
|
||||
/* Atelier-Seaside Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #29a329;
|
||||
}
|
||||
|
||||
/* Atelier-Seaside Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #3d62f5;
|
||||
}
|
||||
|
||||
/* Atelier-Seaside Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #ad2bee;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #f4fbf4;
|
||||
color: #5e6e5e;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
69
js/styles/atelier-sulphurpool-dark.css
Normal file
@@ -0,0 +1,69 @@
|
||||
/* Base16 Atelier Sulphurpool Dark - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/sulphurpool) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Sulphurpool Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #898ea4;
|
||||
}
|
||||
|
||||
/* Atelier-Sulphurpool Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #c94922;
|
||||
}
|
||||
|
||||
/* Atelier-Sulphurpool Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #c76b29;
|
||||
}
|
||||
|
||||
/* Atelier-Sulphurpool Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #ac9739;
|
||||
}
|
||||
|
||||
/* Atelier-Sulphurpool Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #3d8fd1;
|
||||
}
|
||||
|
||||
/* Atelier-Sulphurpool Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #6679cc;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #202746;
|
||||
color: #979db4;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
69
js/styles/atelier-sulphurpool-light.css
Normal file
@@ -0,0 +1,69 @@
|
||||
/* Base16 Atelier Sulphurpool Light - Theme */
|
||||
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/sulphurpool) */
|
||||
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
|
||||
|
||||
/* Atelier-Sulphurpool Comment */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #6b7394;
|
||||
}
|
||||
|
||||
/* Atelier-Sulphurpool Red */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #c94922;
|
||||
}
|
||||
|
||||
/* Atelier-Sulphurpool Orange */
|
||||
.hljs-number,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #c76b29;
|
||||
}
|
||||
|
||||
/* Atelier-Sulphurpool Green */
|
||||
.hljs-string,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #ac9739;
|
||||
}
|
||||
|
||||
/* Atelier-Sulphurpool Blue */
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #3d8fd1;
|
||||
}
|
||||
|
||||
/* Atelier-Sulphurpool Purple */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag {
|
||||
color: #6679cc;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
background: #f5f7ff;
|
||||
color: #5e6687;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
77
js/styles/atom-one-dark-reasonable.css
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
|
||||
Atom One Dark With support for ReasonML by Gidi Morris, based off work by Daniel Gamage
|
||||
|
||||
Original One Dark Syntax theme from https://github.com/atom/one-dark-syntax
|
||||
|
||||
*/
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
line-height: 1.3em;
|
||||
color: #abb2bf;
|
||||
background: #282c34;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.hljs-keyword, .hljs-operator {
|
||||
color: #F92672;
|
||||
}
|
||||
.hljs-pattern-match {
|
||||
color: #F92672;
|
||||
}
|
||||
.hljs-pattern-match .hljs-constructor {
|
||||
color: #61aeee;
|
||||
}
|
||||
.hljs-function {
|
||||
color: #61aeee;
|
||||
}
|
||||
.hljs-function .hljs-params {
|
||||
color: #A6E22E;
|
||||
}
|
||||
.hljs-function .hljs-params .hljs-typing {
|
||||
color: #FD971F;
|
||||
}
|
||||
.hljs-module-access .hljs-module {
|
||||
color: #7e57c2;
|
||||
}
|
||||
.hljs-constructor {
|
||||
color: #e2b93d;
|
||||
}
|
||||
.hljs-constructor .hljs-string {
|
||||
color: #9CCC65;
|
||||
}
|
||||
.hljs-comment, .hljs-quote {
|
||||
color: #b18eb1;
|
||||
font-style: italic;
|
||||
}
|
||||
.hljs-doctag, .hljs-formula {
|
||||
color: #c678dd;
|
||||
}
|
||||
.hljs-section, .hljs-name, .hljs-selector-tag, .hljs-deletion, .hljs-subst {
|
||||
color: #e06c75;
|
||||
}
|
||||
.hljs-literal {
|
||||
color: #56b6c2;
|
||||
}
|
||||
.hljs-string, .hljs-regexp, .hljs-addition, .hljs-attribute, .hljs-meta-string {
|
||||
color: #98c379;
|
||||
}
|
||||
.hljs-built_in, .hljs-class .hljs-title {
|
||||
color: #e6c07b;
|
||||
}
|
||||
.hljs-attr, .hljs-variable, .hljs-template-variable, .hljs-type, .hljs-selector-class, .hljs-selector-attr, .hljs-selector-pseudo, .hljs-number {
|
||||
color: #d19a66;
|
||||
}
|
||||
.hljs-symbol, .hljs-bullet, .hljs-link, .hljs-meta, .hljs-selector-id, .hljs-title {
|
||||
color: #61aeee;
|
||||
}
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
.hljs-link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
96
js/styles/atom-one-dark.css
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
|
||||
Atom One Dark by Daniel Gamage
|
||||
Original One Dark Syntax theme from https://github.com/atom/one-dark-syntax
|
||||
|
||||
base: #282c34
|
||||
mono-1: #abb2bf
|
||||
mono-2: #818896
|
||||
mono-3: #5c6370
|
||||
hue-1: #56b6c2
|
||||
hue-2: #61aeee
|
||||
hue-3: #c678dd
|
||||
hue-4: #98c379
|
||||
hue-5: #e06c75
|
||||
hue-5-2: #be5046
|
||||
hue-6: #d19a66
|
||||
hue-6-2: #e6c07b
|
||||
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
color: #abb2bf;
|
||||
background: #282c34;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #5c6370;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-doctag,
|
||||
.hljs-keyword,
|
||||
.hljs-formula {
|
||||
color: #c678dd;
|
||||
}
|
||||
|
||||
.hljs-section,
|
||||
.hljs-name,
|
||||
.hljs-selector-tag,
|
||||
.hljs-deletion,
|
||||
.hljs-subst {
|
||||
color: #e06c75;
|
||||
}
|
||||
|
||||
.hljs-literal {
|
||||
color: #56b6c2;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-regexp,
|
||||
.hljs-addition,
|
||||
.hljs-attribute,
|
||||
.hljs-meta-string {
|
||||
color: #98c379;
|
||||
}
|
||||
|
||||
.hljs-built_in,
|
||||
.hljs-class .hljs-title {
|
||||
color: #e6c07b;
|
||||
}
|
||||
|
||||
.hljs-attr,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-type,
|
||||
.hljs-selector-class,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo,
|
||||
.hljs-number {
|
||||
color: #d19a66;
|
||||
}
|
||||
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-link,
|
||||
.hljs-meta,
|
||||
.hljs-selector-id,
|
||||
.hljs-title {
|
||||
color: #61aeee;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
96
js/styles/atom-one-light.css
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
|
||||
Atom One Light by Daniel Gamage
|
||||
Original One Light Syntax theme from https://github.com/atom/one-light-syntax
|
||||
|
||||
base: #fafafa
|
||||
mono-1: #383a42
|
||||
mono-2: #686b77
|
||||
mono-3: #a0a1a7
|
||||
hue-1: #0184bb
|
||||
hue-2: #4078f2
|
||||
hue-3: #a626a4
|
||||
hue-4: #50a14f
|
||||
hue-5: #e45649
|
||||
hue-5-2: #c91243
|
||||
hue-6: #986801
|
||||
hue-6-2: #c18401
|
||||
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
color: #383a42;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #a0a1a7;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-doctag,
|
||||
.hljs-keyword,
|
||||
.hljs-formula {
|
||||
color: #a626a4;
|
||||
}
|
||||
|
||||
.hljs-section,
|
||||
.hljs-name,
|
||||
.hljs-selector-tag,
|
||||
.hljs-deletion,
|
||||
.hljs-subst {
|
||||
color: #e45649;
|
||||
}
|
||||
|
||||
.hljs-literal {
|
||||
color: #0184bb;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-regexp,
|
||||
.hljs-addition,
|
||||
.hljs-attribute,
|
||||
.hljs-meta-string {
|
||||
color: #50a14f;
|
||||
}
|
||||
|
||||
.hljs-built_in,
|
||||
.hljs-class .hljs-title {
|
||||
color: #c18401;
|
||||
}
|
||||
|
||||
.hljs-attr,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-type,
|
||||
.hljs-selector-class,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo,
|
||||
.hljs-number {
|
||||
color: #986801;
|
||||
}
|
||||
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-link,
|
||||
.hljs-meta,
|
||||
.hljs-selector-id,
|
||||
.hljs-title {
|
||||
color: #4078f2;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
64
js/styles/brown-paper.css
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
|
||||
Brown Paper style from goldblog.com.ua (c) Zaripov Yura <yur4ik7@ukr.net>
|
||||
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background:#b7a68e url(./brown-papersq.png);
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-literal {
|
||||
color:#005599;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
.hljs,
|
||||
.hljs-subst {
|
||||
color: #363c69;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-title,
|
||||
.hljs-section,
|
||||
.hljs-type,
|
||||
.hljs-attribute,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-built_in,
|
||||
.hljs-addition,
|
||||
.hljs-variable,
|
||||
.hljs-template-tag,
|
||||
.hljs-template-variable,
|
||||
.hljs-link,
|
||||
.hljs-name {
|
||||
color: #2c009f;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote,
|
||||
.hljs-meta,
|
||||
.hljs-deletion {
|
||||
color: #802022;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-literal,
|
||||
.hljs-doctag,
|
||||
.hljs-title,
|
||||
.hljs-section,
|
||||
.hljs-type,
|
||||
.hljs-name,
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
BIN
js/styles/brown-papersq.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
60
js/styles/codepen-embed.css
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
codepen.io Embed Theme
|
||||
Author: Justin Perry <http://github.com/ourmaninamsterdam>
|
||||
Original theme - https://github.com/chriskempson/tomorrow-theme
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: #222;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-tag,
|
||||
.hljs-regexp,
|
||||
.hljs-meta,
|
||||
.hljs-number,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-params,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-link,
|
||||
.hljs-deletion {
|
||||
color: #ab875d;
|
||||
}
|
||||
|
||||
.hljs-section,
|
||||
.hljs-title,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class,
|
||||
.hljs-type,
|
||||
.hljs-attribute {
|
||||
color: #9b869b;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-addition {
|
||||
color: #8f9c6c;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
71
js/styles/color-brewer.css
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
|
||||
Colorbrewer theme
|
||||
Original: https://github.com/mbostock/colorbrewer-theme (c) Mike Bostock <mike@ocks.org>
|
||||
Ported by Fabrício Tavares de Oliveira
|
||||
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.hljs,
|
||||
.hljs-subst {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-meta,
|
||||
.hljs-symbol,
|
||||
.hljs-template-tag,
|
||||
.hljs-template-variable,
|
||||
.hljs-addition {
|
||||
color: #756bb1;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #636363;
|
||||
}
|
||||
|
||||
.hljs-number,
|
||||
.hljs-regexp,
|
||||
.hljs-literal,
|
||||
.hljs-bullet,
|
||||
.hljs-link {
|
||||
color: #31a354;
|
||||
}
|
||||
|
||||
.hljs-deletion,
|
||||
.hljs-variable {
|
||||
color: #88f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-title,
|
||||
.hljs-section,
|
||||
.hljs-built_in,
|
||||
.hljs-doctag,
|
||||
.hljs-type,
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class,
|
||||
.hljs-strong {
|
||||
color: #3182bd;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-attribute {
|
||||
color: #e6550d;
|
||||
}
|
||||
77
js/styles/darcula.css
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
|
||||
Darcula color scheme from the JetBrains family of IDEs
|
||||
|
||||
*/
|
||||
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: #2b2b2b;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
color: #bababa;
|
||||
}
|
||||
|
||||
.hljs-strong,
|
||||
.hljs-emphasis {
|
||||
color: #a8a8a2;
|
||||
}
|
||||
|
||||
.hljs-bullet,
|
||||
.hljs-quote,
|
||||
.hljs-link,
|
||||
.hljs-number,
|
||||
.hljs-regexp,
|
||||
.hljs-literal {
|
||||
color: #6896ba;
|
||||
}
|
||||
|
||||
.hljs-code,
|
||||
.hljs-selector-class {
|
||||
color: #a6e22e;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-section,
|
||||
.hljs-attribute,
|
||||
.hljs-name,
|
||||
.hljs-variable {
|
||||
color: #cb7832;
|
||||
}
|
||||
|
||||
.hljs-params {
|
||||
color: #b9b9b9;
|
||||
}
|
||||
|
||||
.hljs-string {
|
||||
color: #6a8759;
|
||||
}
|
||||
|
||||
.hljs-subst,
|
||||
.hljs-type,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-symbol,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo,
|
||||
.hljs-template-tag,
|
||||
.hljs-template-variable,
|
||||
.hljs-addition {
|
||||
color: #e0c46c;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-deletion,
|
||||
.hljs-meta {
|
||||
color: #7f7f7f;
|
||||
}
|
||||