Compare commits
No commits in common. "main" and "fix_overcharge" have entirely different histories.
main
...
fix_overch
|
@ -1,10 +0,0 @@
|
||||||
<VirtualHost *:80>
|
|
||||||
ErrorLog ${APACHE_LOG_DIR}/error.log
|
|
||||||
ServerName sohsot.local
|
|
||||||
DocumentRoot /var/www/public/
|
|
||||||
<Directory "/var/www/public/">
|
|
||||||
Require all granted
|
|
||||||
AllowOverride All
|
|
||||||
Options -Indexes
|
|
||||||
</Directory>
|
|
||||||
</VirtualHost>
|
|
|
@ -1,3 +0,0 @@
|
||||||
#/bin/bash
|
|
||||||
cron
|
|
||||||
/usr/sbin/apache2ctl -DFOREGROUND
|
|
9
.gitignore
vendored
|
@ -1,5 +1,4 @@
|
||||||
cache/
|
cache/*
|
||||||
composer.lock
|
!cache/index.html
|
||||||
datas/config.json
|
.project
|
||||||
datas/soshot.sqlite
|
.settings
|
||||||
vendor/
|
|
||||||
|
|
5
.htaccess
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
AddDefaultCharset UTF-8
|
||||||
|
Options -Indexes
|
||||||
|
DirectoryIndex index.php index.html
|
||||||
|
FileETag none
|
||||||
|
SetOutputFilter DEFLATE
|
|
@ -1,5 +0,0 @@
|
||||||
docker run -v soshot_datas:/var/www/datas -v soshot_cache_img:/var/www/cache/img -e TZ=UTC -p 8080:80 --name soshot soshot:0.3.0
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
docker run -v soshot_datas:/var/www/datas soshot --name soshot soshot
|
|
39
Dockerfile
|
@ -1,39 +0,0 @@
|
||||||
FROM ubuntu/apache2
|
|
||||||
|
|
||||||
MAINTAINER Knah Tsaeb <knah-tsaeb_soshot@knah-tsaeb.org>
|
|
||||||
|
|
||||||
LABEL version="0.3.0"
|
|
||||||
LABEL description="Apache 2 / PHP / SoShot"
|
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
|
||||||
|
|
||||||
RUN apt-get -y update && apt-get install -y php php-gd php-json php-sqlite3 php-mbstring php-xml php-curl wget gnupg git composer php-imagick sudo cron imagemagick && apt-get clean && apt-get autoclean && apt-get autoremove
|
|
||||||
|
|
||||||
RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && apt -y install ./google-chrome-stable_current_amd64.deb && apt-get -y update && apt-get install -y google-chrome-stable && apt-get clean && rm google-chrome-stable_current_amd64.deb && rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
RUN rm -r /var/www/ && mkdir /var/www/
|
|
||||||
|
|
||||||
WORKDIR /var/www/
|
|
||||||
RUN git clone https://forge.leslibres.org/Knah-Tsaeb/Soshot.git --branch main --single-branch --depth 1 .
|
|
||||||
RUN composer install --no-dev && chown -R www-data:www-data /var/www/
|
|
||||||
|
|
||||||
RUN cp .docker/start.sh /usr/bin/start.sh
|
|
||||||
RUN chmod +x /usr/bin/start.sh
|
|
||||||
|
|
||||||
RUN cp .docker/apache2/soshot.conf /etc/apache2/sites-available/soshot.conf
|
|
||||||
RUN a2dissite 000-default.conf && a2ensite soshot.conf && a2enmod rewrite
|
|
||||||
|
|
||||||
WORKDIR /
|
|
||||||
RUN echo '*/4 * * * * www-data php /var/www/bin/thumbShoter.php' > /etc/cron.d/soshot && chmod 0644 /etc/cron.d/soshot && crontab /etc/cron.d/soshot
|
|
||||||
|
|
||||||
EXPOSE 80
|
|
||||||
VOLUME soshot_datas
|
|
||||||
|
|
||||||
WORKDIR /var/www/
|
|
||||||
|
|
||||||
ENTRYPOINT "start.sh"
|
|
||||||
|
|
||||||
# Build image
|
|
||||||
# docker build -t soshot:0.3.0 .
|
|
||||||
# Run container
|
|
||||||
# docker run -v soshot_datas:/var/www/datas -v soshot_cache_img:/var/www/cache/img -e TZ=UTC -p 8080:80 --name soshot soshot:0.3.0
|
|
674
LICENSE
|
@ -1,674 +0,0 @@
|
||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
Version 3, 29 June 2007
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The GNU General Public License is a free, copyleft license for
|
|
||||||
software and other kinds of works.
|
|
||||||
|
|
||||||
The licenses for most software and other practical works are designed
|
|
||||||
to take away your freedom to share and change the works. By contrast,
|
|
||||||
the GNU General Public License is intended to guarantee your freedom to
|
|
||||||
share and change all versions of a program--to make sure it remains free
|
|
||||||
software for all its users. We, the Free Software Foundation, use the
|
|
||||||
GNU General Public License for most of our software; it applies also to
|
|
||||||
any other work released this way by its authors. You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
them if you wish), that you receive source code or can get it if you
|
|
||||||
want it, that you can change the software or use pieces of it in new
|
|
||||||
free programs, and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to prevent others from denying you
|
|
||||||
these rights or asking you to surrender the rights. Therefore, you have
|
|
||||||
certain responsibilities if you distribute copies of the software, or if
|
|
||||||
you modify it: responsibilities to respect the freedom of others.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
|
||||||
gratis or for a fee, you must pass on to the recipients the same
|
|
||||||
freedoms that you received. You must make sure that they, too, receive
|
|
||||||
or can get the source code. And you must show them these terms so they
|
|
||||||
know their rights.
|
|
||||||
|
|
||||||
Developers that use the GNU GPL protect your rights with two steps:
|
|
||||||
(1) assert copyright on the software, and (2) offer you this License
|
|
||||||
giving you legal permission to copy, distribute and/or modify it.
|
|
||||||
|
|
||||||
For the developers' and authors' protection, the GPL clearly explains
|
|
||||||
that there is no warranty for this free software. For both users' and
|
|
||||||
authors' sake, the GPL requires that modified versions be marked as
|
|
||||||
changed, so that their problems will not be attributed erroneously to
|
|
||||||
authors of previous versions.
|
|
||||||
|
|
||||||
Some devices are designed to deny users access to install or run
|
|
||||||
modified versions of the software inside them, although the manufacturer
|
|
||||||
can do so. This is fundamentally incompatible with the aim of
|
|
||||||
protecting users' freedom to change the software. The systematic
|
|
||||||
pattern of such abuse occurs in the area of products for individuals to
|
|
||||||
use, which is precisely where it is most unacceptable. Therefore, we
|
|
||||||
have designed this version of the GPL to prohibit the practice for those
|
|
||||||
products. If such problems arise substantially in other domains, we
|
|
||||||
stand ready to extend this provision to those domains in future versions
|
|
||||||
of the GPL, as needed to protect the freedom of users.
|
|
||||||
|
|
||||||
Finally, every program is threatened constantly by software patents.
|
|
||||||
States should not allow patents to restrict development and use of
|
|
||||||
software on general-purpose computers, but in those that do, we wish to
|
|
||||||
avoid the special danger that patents applied to a free program could
|
|
||||||
make it effectively proprietary. To prevent this, the GPL assures that
|
|
||||||
patents cannot be used to render the program non-free.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
0. Definitions.
|
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU General Public License.
|
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
|
||||||
works, such as semiconductor masks.
|
|
||||||
|
|
||||||
"The Program" refers to any copyrightable work licensed under this
|
|
||||||
License. Each licensee is addressed as "you". "Licensees" and
|
|
||||||
"recipients" may be individuals or organizations.
|
|
||||||
|
|
||||||
To "modify" a work means to copy from or adapt all or part of the work
|
|
||||||
in a fashion requiring copyright permission, other than the making of an
|
|
||||||
exact copy. The resulting work is called a "modified version" of the
|
|
||||||
earlier work or a work "based on" the earlier work.
|
|
||||||
|
|
||||||
A "covered work" means either the unmodified Program or a work based
|
|
||||||
on the Program.
|
|
||||||
|
|
||||||
To "propagate" a work means to do anything with it that, without
|
|
||||||
permission, would make you directly or secondarily liable for
|
|
||||||
infringement under applicable copyright law, except executing it on a
|
|
||||||
computer or modifying a private copy. Propagation includes copying,
|
|
||||||
distribution (with or without modification), making available to the
|
|
||||||
public, and in some countries other activities as well.
|
|
||||||
|
|
||||||
To "convey" a work means any kind of propagation that enables other
|
|
||||||
parties to make or receive copies. Mere interaction with a user through
|
|
||||||
a computer network, with no transfer of a copy, is not conveying.
|
|
||||||
|
|
||||||
An interactive user interface displays "Appropriate Legal Notices"
|
|
||||||
to the extent that it includes a convenient and prominently visible
|
|
||||||
feature that (1) displays an appropriate copyright notice, and (2)
|
|
||||||
tells the user that there is no warranty for the work (except to the
|
|
||||||
extent that warranties are provided), that licensees may convey the
|
|
||||||
work under this License, and how to view a copy of this License. If
|
|
||||||
the interface presents a list of user commands or options, such as a
|
|
||||||
menu, a prominent item in the list meets this criterion.
|
|
||||||
|
|
||||||
1. Source Code.
|
|
||||||
|
|
||||||
The "source code" for a work means the preferred form of the work
|
|
||||||
for making modifications to it. "Object code" means any non-source
|
|
||||||
form of a work.
|
|
||||||
|
|
||||||
A "Standard Interface" means an interface that either is an official
|
|
||||||
standard defined by a recognized standards body, or, in the case of
|
|
||||||
interfaces specified for a particular programming language, one that
|
|
||||||
is widely used among developers working in that language.
|
|
||||||
|
|
||||||
The "System Libraries" of an executable work include anything, other
|
|
||||||
than the work as a whole, that (a) is included in the normal form of
|
|
||||||
packaging a Major Component, but which is not part of that Major
|
|
||||||
Component, and (b) serves only to enable use of the work with that
|
|
||||||
Major Component, or to implement a Standard Interface for which an
|
|
||||||
implementation is available to the public in source code form. A
|
|
||||||
"Major Component", in this context, means a major essential component
|
|
||||||
(kernel, window system, and so on) of the specific operating system
|
|
||||||
(if any) on which the executable work runs, or a compiler used to
|
|
||||||
produce the work, or an object code interpreter used to run it.
|
|
||||||
|
|
||||||
The "Corresponding Source" for a work in object code form means all
|
|
||||||
the source code needed to generate, install, and (for an executable
|
|
||||||
work) run the object code and to modify the work, including scripts to
|
|
||||||
control those activities. However, it does not include the work's
|
|
||||||
System Libraries, or general-purpose tools or generally available free
|
|
||||||
programs which are used unmodified in performing those activities but
|
|
||||||
which are not part of the work. For example, Corresponding Source
|
|
||||||
includes interface definition files associated with source files for
|
|
||||||
the work, and the source code for shared libraries and dynamically
|
|
||||||
linked subprograms that the work is specifically designed to require,
|
|
||||||
such as by intimate data communication or control flow between those
|
|
||||||
subprograms and other parts of the work.
|
|
||||||
|
|
||||||
The Corresponding Source need not include anything that users
|
|
||||||
can regenerate automatically from other parts of the Corresponding
|
|
||||||
Source.
|
|
||||||
|
|
||||||
The Corresponding Source for a work in source code form is that
|
|
||||||
same work.
|
|
||||||
|
|
||||||
2. Basic Permissions.
|
|
||||||
|
|
||||||
All rights granted under this License are granted for the term of
|
|
||||||
copyright on the Program, and are irrevocable provided the stated
|
|
||||||
conditions are met. This License explicitly affirms your unlimited
|
|
||||||
permission to run the unmodified Program. The output from running a
|
|
||||||
covered work is covered by this License only if the output, given its
|
|
||||||
content, constitutes a covered work. This License acknowledges your
|
|
||||||
rights of fair use or other equivalent, as provided by copyright law.
|
|
||||||
|
|
||||||
You may make, run and propagate covered works that you do not
|
|
||||||
convey, without conditions so long as your license otherwise remains
|
|
||||||
in force. You may convey covered works to others for the sole purpose
|
|
||||||
of having them make modifications exclusively for you, or provide you
|
|
||||||
with facilities for running those works, provided that you comply with
|
|
||||||
the terms of this License in conveying all material for which you do
|
|
||||||
not control copyright. Those thus making or running the covered works
|
|
||||||
for you must do so exclusively on your behalf, under your direction
|
|
||||||
and control, on terms that prohibit them from making any copies of
|
|
||||||
your copyrighted material outside their relationship with you.
|
|
||||||
|
|
||||||
Conveying under any other circumstances is permitted solely under
|
|
||||||
the conditions stated below. Sublicensing is not allowed; section 10
|
|
||||||
makes it unnecessary.
|
|
||||||
|
|
||||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
|
||||||
|
|
||||||
No covered work shall be deemed part of an effective technological
|
|
||||||
measure under any applicable law fulfilling obligations under article
|
|
||||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
|
||||||
similar laws prohibiting or restricting circumvention of such
|
|
||||||
measures.
|
|
||||||
|
|
||||||
When you convey a covered work, you waive any legal power to forbid
|
|
||||||
circumvention of technological measures to the extent such circumvention
|
|
||||||
is effected by exercising rights under this License with respect to
|
|
||||||
the covered work, and you disclaim any intention to limit operation or
|
|
||||||
modification of the work as a means of enforcing, against the work's
|
|
||||||
users, your or third parties' legal rights to forbid circumvention of
|
|
||||||
technological measures.
|
|
||||||
|
|
||||||
4. Conveying Verbatim Copies.
|
|
||||||
|
|
||||||
You may convey verbatim copies of the Program's source code as you
|
|
||||||
receive it, in any medium, provided that you conspicuously and
|
|
||||||
appropriately publish on each copy an appropriate copyright notice;
|
|
||||||
keep intact all notices stating that this License and any
|
|
||||||
non-permissive terms added in accord with section 7 apply to the code;
|
|
||||||
keep intact all notices of the absence of any warranty; and give all
|
|
||||||
recipients a copy of this License along with the Program.
|
|
||||||
|
|
||||||
You may charge any price or no price for each copy that you convey,
|
|
||||||
and you may offer support or warranty protection for a fee.
|
|
||||||
|
|
||||||
5. Conveying Modified Source Versions.
|
|
||||||
|
|
||||||
You may convey a work based on the Program, or the modifications to
|
|
||||||
produce it from the Program, in the form of source code under the
|
|
||||||
terms of section 4, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) The work must carry prominent notices stating that you modified
|
|
||||||
it, and giving a relevant date.
|
|
||||||
|
|
||||||
b) The work must carry prominent notices stating that it is
|
|
||||||
released under this License and any conditions added under section
|
|
||||||
7. This requirement modifies the requirement in section 4 to
|
|
||||||
"keep intact all notices".
|
|
||||||
|
|
||||||
c) You must license the entire work, as a whole, under this
|
|
||||||
License to anyone who comes into possession of a copy. This
|
|
||||||
License will therefore apply, along with any applicable section 7
|
|
||||||
additional terms, to the whole of the work, and all its parts,
|
|
||||||
regardless of how they are packaged. This License gives no
|
|
||||||
permission to license the work in any other way, but it does not
|
|
||||||
invalidate such permission if you have separately received it.
|
|
||||||
|
|
||||||
d) If the work has interactive user interfaces, each must display
|
|
||||||
Appropriate Legal Notices; however, if the Program has interactive
|
|
||||||
interfaces that do not display Appropriate Legal Notices, your
|
|
||||||
work need not make them do so.
|
|
||||||
|
|
||||||
A compilation of a covered work with other separate and independent
|
|
||||||
works, which are not by their nature extensions of the covered work,
|
|
||||||
and which are not combined with it such as to form a larger program,
|
|
||||||
in or on a volume of a storage or distribution medium, is called an
|
|
||||||
"aggregate" if the compilation and its resulting copyright are not
|
|
||||||
used to limit the access or legal rights of the compilation's users
|
|
||||||
beyond what the individual works permit. Inclusion of a covered work
|
|
||||||
in an aggregate does not cause this License to apply to the other
|
|
||||||
parts of the aggregate.
|
|
||||||
|
|
||||||
6. Conveying Non-Source Forms.
|
|
||||||
|
|
||||||
You may convey a covered work in object code form under the terms
|
|
||||||
of sections 4 and 5, provided that you also convey the
|
|
||||||
machine-readable Corresponding Source under the terms of this License,
|
|
||||||
in one of these ways:
|
|
||||||
|
|
||||||
a) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by the
|
|
||||||
Corresponding Source fixed on a durable physical medium
|
|
||||||
customarily used for software interchange.
|
|
||||||
|
|
||||||
b) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by a
|
|
||||||
written offer, valid for at least three years and valid for as
|
|
||||||
long as you offer spare parts or customer support for that product
|
|
||||||
model, to give anyone who possesses the object code either (1) a
|
|
||||||
copy of the Corresponding Source for all the software in the
|
|
||||||
product that is covered by this License, on a durable physical
|
|
||||||
medium customarily used for software interchange, for a price no
|
|
||||||
more than your reasonable cost of physically performing this
|
|
||||||
conveying of source, or (2) access to copy the
|
|
||||||
Corresponding Source from a network server at no charge.
|
|
||||||
|
|
||||||
c) Convey individual copies of the object code with a copy of the
|
|
||||||
written offer to provide the Corresponding Source. This
|
|
||||||
alternative is allowed only occasionally and noncommercially, and
|
|
||||||
only if you received the object code with such an offer, in accord
|
|
||||||
with subsection 6b.
|
|
||||||
|
|
||||||
d) Convey the object code by offering access from a designated
|
|
||||||
place (gratis or for a charge), and offer equivalent access to the
|
|
||||||
Corresponding Source in the same way through the same place at no
|
|
||||||
further charge. You need not require recipients to copy the
|
|
||||||
Corresponding Source along with the object code. If the place to
|
|
||||||
copy the object code is a network server, the Corresponding Source
|
|
||||||
may be on a different server (operated by you or a third party)
|
|
||||||
that supports equivalent copying facilities, provided you maintain
|
|
||||||
clear directions next to the object code saying where to find the
|
|
||||||
Corresponding Source. Regardless of what server hosts the
|
|
||||||
Corresponding Source, you remain obligated to ensure that it is
|
|
||||||
available for as long as needed to satisfy these requirements.
|
|
||||||
|
|
||||||
e) Convey the object code using peer-to-peer transmission, provided
|
|
||||||
you inform other peers where the object code and Corresponding
|
|
||||||
Source of the work are being offered to the general public at no
|
|
||||||
charge under subsection 6d.
|
|
||||||
|
|
||||||
A separable portion of the object code, whose source code is excluded
|
|
||||||
from the Corresponding Source as a System Library, need not be
|
|
||||||
included in conveying the object code work.
|
|
||||||
|
|
||||||
A "User Product" is either (1) a "consumer product", which means any
|
|
||||||
tangible personal property which is normally used for personal, family,
|
|
||||||
or household purposes, or (2) anything designed or sold for incorporation
|
|
||||||
into a dwelling. In determining whether a product is a consumer product,
|
|
||||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
|
||||||
product received by a particular user, "normally used" refers to a
|
|
||||||
typical or common use of that class of product, regardless of the status
|
|
||||||
of the particular user or of the way in which the particular user
|
|
||||||
actually uses, or expects or is expected to use, the product. A product
|
|
||||||
is a consumer product regardless of whether the product has substantial
|
|
||||||
commercial, industrial or non-consumer uses, unless such uses represent
|
|
||||||
the only significant mode of use of the product.
|
|
||||||
|
|
||||||
"Installation Information" for a User Product means any methods,
|
|
||||||
procedures, authorization keys, or other information required to install
|
|
||||||
and execute modified versions of a covered work in that User Product from
|
|
||||||
a modified version of its Corresponding Source. The information must
|
|
||||||
suffice to ensure that the continued functioning of the modified object
|
|
||||||
code is in no case prevented or interfered with solely because
|
|
||||||
modification has been made.
|
|
||||||
|
|
||||||
If you convey an object code work under this section in, or with, or
|
|
||||||
specifically for use in, a User Product, and the conveying occurs as
|
|
||||||
part of a transaction in which the right of possession and use of the
|
|
||||||
User Product is transferred to the recipient in perpetuity or for a
|
|
||||||
fixed term (regardless of how the transaction is characterized), the
|
|
||||||
Corresponding Source conveyed under this section must be accompanied
|
|
||||||
by the Installation Information. But this requirement does not apply
|
|
||||||
if neither you nor any third party retains the ability to install
|
|
||||||
modified object code on the User Product (for example, the work has
|
|
||||||
been installed in ROM).
|
|
||||||
|
|
||||||
The requirement to provide Installation Information does not include a
|
|
||||||
requirement to continue to provide support service, warranty, or updates
|
|
||||||
for a work that has been modified or installed by the recipient, or for
|
|
||||||
the User Product in which it has been modified or installed. Access to a
|
|
||||||
network may be denied when the modification itself materially and
|
|
||||||
adversely affects the operation of the network or violates the rules and
|
|
||||||
protocols for communication across the network.
|
|
||||||
|
|
||||||
Corresponding Source conveyed, and Installation Information provided,
|
|
||||||
in accord with this section must be in a format that is publicly
|
|
||||||
documented (and with an implementation available to the public in
|
|
||||||
source code form), and must require no special password or key for
|
|
||||||
unpacking, reading or copying.
|
|
||||||
|
|
||||||
7. Additional Terms.
|
|
||||||
|
|
||||||
"Additional permissions" are terms that supplement the terms of this
|
|
||||||
License by making exceptions from one or more of its conditions.
|
|
||||||
Additional permissions that are applicable to the entire Program shall
|
|
||||||
be treated as though they were included in this License, to the extent
|
|
||||||
that they are valid under applicable law. If additional permissions
|
|
||||||
apply only to part of the Program, that part may be used separately
|
|
||||||
under those permissions, but the entire Program remains governed by
|
|
||||||
this License without regard to the additional permissions.
|
|
||||||
|
|
||||||
When you convey a copy of a covered work, you may at your option
|
|
||||||
remove any additional permissions from that copy, or from any part of
|
|
||||||
it. (Additional permissions may be written to require their own
|
|
||||||
removal in certain cases when you modify the work.) You may place
|
|
||||||
additional permissions on material, added by you to a covered work,
|
|
||||||
for which you have or can give appropriate copyright permission.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, for material you
|
|
||||||
add to a covered work, you may (if authorized by the copyright holders of
|
|
||||||
that material) supplement the terms of this License with terms:
|
|
||||||
|
|
||||||
a) Disclaiming warranty or limiting liability differently from the
|
|
||||||
terms of sections 15 and 16 of this License; or
|
|
||||||
|
|
||||||
b) Requiring preservation of specified reasonable legal notices or
|
|
||||||
author attributions in that material or in the Appropriate Legal
|
|
||||||
Notices displayed by works containing it; or
|
|
||||||
|
|
||||||
c) Prohibiting misrepresentation of the origin of that material, or
|
|
||||||
requiring that modified versions of such material be marked in
|
|
||||||
reasonable ways as different from the original version; or
|
|
||||||
|
|
||||||
d) Limiting the use for publicity purposes of names of licensors or
|
|
||||||
authors of the material; or
|
|
||||||
|
|
||||||
e) Declining to grant rights under trademark law for use of some
|
|
||||||
trade names, trademarks, or service marks; or
|
|
||||||
|
|
||||||
f) Requiring indemnification of licensors and authors of that
|
|
||||||
material by anyone who conveys the material (or modified versions of
|
|
||||||
it) with contractual assumptions of liability to the recipient, for
|
|
||||||
any liability that these contractual assumptions directly impose on
|
|
||||||
those licensors and authors.
|
|
||||||
|
|
||||||
All other non-permissive additional terms are considered "further
|
|
||||||
restrictions" within the meaning of section 10. If the Program as you
|
|
||||||
received it, or any part of it, contains a notice stating that it is
|
|
||||||
governed by this License along with a term that is a further
|
|
||||||
restriction, you may remove that term. If a license document contains
|
|
||||||
a further restriction but permits relicensing or conveying under this
|
|
||||||
License, you may add to a covered work material governed by the terms
|
|
||||||
of that license document, provided that the further restriction does
|
|
||||||
not survive such relicensing or conveying.
|
|
||||||
|
|
||||||
If you add terms to a covered work in accord with this section, you
|
|
||||||
must place, in the relevant source files, a statement of the
|
|
||||||
additional terms that apply to those files, or a notice indicating
|
|
||||||
where to find the applicable terms.
|
|
||||||
|
|
||||||
Additional terms, permissive or non-permissive, may be stated in the
|
|
||||||
form of a separately written license, or stated as exceptions;
|
|
||||||
the above requirements apply either way.
|
|
||||||
|
|
||||||
8. Termination.
|
|
||||||
|
|
||||||
You may not propagate or modify a covered work except as expressly
|
|
||||||
provided under this License. Any attempt otherwise to propagate or
|
|
||||||
modify it is void, and will automatically terminate your rights under
|
|
||||||
this License (including any patent licenses granted under the third
|
|
||||||
paragraph of section 11).
|
|
||||||
|
|
||||||
However, if you cease all violation of this License, then your
|
|
||||||
license from a particular copyright holder is reinstated (a)
|
|
||||||
provisionally, unless and until the copyright holder explicitly and
|
|
||||||
finally terminates your license, and (b) permanently, if the copyright
|
|
||||||
holder fails to notify you of the violation by some reasonable means
|
|
||||||
prior to 60 days after the cessation.
|
|
||||||
|
|
||||||
Moreover, your license from a particular copyright holder is
|
|
||||||
reinstated permanently if the copyright holder notifies you of the
|
|
||||||
violation by some reasonable means, this is the first time you have
|
|
||||||
received notice of violation of this License (for any work) from that
|
|
||||||
copyright holder, and you cure the violation prior to 30 days after
|
|
||||||
your receipt of the notice.
|
|
||||||
|
|
||||||
Termination of your rights under this section does not terminate the
|
|
||||||
licenses of parties who have received copies or rights from you under
|
|
||||||
this License. If your rights have been terminated and not permanently
|
|
||||||
reinstated, you do not qualify to receive new licenses for the same
|
|
||||||
material under section 10.
|
|
||||||
|
|
||||||
9. Acceptance Not Required for Having Copies.
|
|
||||||
|
|
||||||
You are not required to accept this License in order to receive or
|
|
||||||
run a copy of the Program. Ancillary propagation of a covered work
|
|
||||||
occurring solely as a consequence of using peer-to-peer transmission
|
|
||||||
to receive a copy likewise does not require acceptance. However,
|
|
||||||
nothing other than this License grants you permission to propagate or
|
|
||||||
modify any covered work. These actions infringe copyright if you do
|
|
||||||
not accept this License. Therefore, by modifying or propagating a
|
|
||||||
covered work, you indicate your acceptance of this License to do so.
|
|
||||||
|
|
||||||
10. Automatic Licensing of Downstream Recipients.
|
|
||||||
|
|
||||||
Each time you convey a covered work, the recipient automatically
|
|
||||||
receives a license from the original licensors, to run, modify and
|
|
||||||
propagate that work, subject to this License. You are not responsible
|
|
||||||
for enforcing compliance by third parties with this License.
|
|
||||||
|
|
||||||
An "entity transaction" is a transaction transferring control of an
|
|
||||||
organization, or substantially all assets of one, or subdividing an
|
|
||||||
organization, or merging organizations. If propagation of a covered
|
|
||||||
work results from an entity transaction, each party to that
|
|
||||||
transaction who receives a copy of the work also receives whatever
|
|
||||||
licenses to the work the party's predecessor in interest had or could
|
|
||||||
give under the previous paragraph, plus a right to possession of the
|
|
||||||
Corresponding Source of the work from the predecessor in interest, if
|
|
||||||
the predecessor has it or can get it with reasonable efforts.
|
|
||||||
|
|
||||||
You may not impose any further restrictions on the exercise of the
|
|
||||||
rights granted or affirmed under this License. For example, you may
|
|
||||||
not impose a license fee, royalty, or other charge for exercise of
|
|
||||||
rights granted under this License, and you may not initiate litigation
|
|
||||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
|
||||||
any patent claim is infringed by making, using, selling, offering for
|
|
||||||
sale, or importing the Program or any portion of it.
|
|
||||||
|
|
||||||
11. Patents.
|
|
||||||
|
|
||||||
A "contributor" is a copyright holder who authorizes use under this
|
|
||||||
License of the Program or a work on which the Program is based. The
|
|
||||||
work thus licensed is called the contributor's "contributor version".
|
|
||||||
|
|
||||||
A contributor's "essential patent claims" are all patent claims
|
|
||||||
owned or controlled by the contributor, whether already acquired or
|
|
||||||
hereafter acquired, that would be infringed by some manner, permitted
|
|
||||||
by this License, of making, using, or selling its contributor version,
|
|
||||||
but do not include claims that would be infringed only as a
|
|
||||||
consequence of further modification of the contributor version. For
|
|
||||||
purposes of this definition, "control" includes the right to grant
|
|
||||||
patent sublicenses in a manner consistent with the requirements of
|
|
||||||
this License.
|
|
||||||
|
|
||||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
|
||||||
patent license under the contributor's essential patent claims, to
|
|
||||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
|
||||||
propagate the contents of its contributor version.
|
|
||||||
|
|
||||||
In the following three paragraphs, a "patent license" is any express
|
|
||||||
agreement or commitment, however denominated, not to enforce a patent
|
|
||||||
(such as an express permission to practice a patent or covenant not to
|
|
||||||
sue for patent infringement). To "grant" such a patent license to a
|
|
||||||
party means to make such an agreement or commitment not to enforce a
|
|
||||||
patent against the party.
|
|
||||||
|
|
||||||
If you convey a covered work, knowingly relying on a patent license,
|
|
||||||
and the Corresponding Source of the work is not available for anyone
|
|
||||||
to copy, free of charge and under the terms of this License, through a
|
|
||||||
publicly available network server or other readily accessible means,
|
|
||||||
then you must either (1) cause the Corresponding Source to be so
|
|
||||||
available, or (2) arrange to deprive yourself of the benefit of the
|
|
||||||
patent license for this particular work, or (3) arrange, in a manner
|
|
||||||
consistent with the requirements of this License, to extend the patent
|
|
||||||
license to downstream recipients. "Knowingly relying" means you have
|
|
||||||
actual knowledge that, but for the patent license, your conveying the
|
|
||||||
covered work in a country, or your recipient's use of the covered work
|
|
||||||
in a country, would infringe one or more identifiable patents in that
|
|
||||||
country that you have reason to believe are valid.
|
|
||||||
|
|
||||||
If, pursuant to or in connection with a single transaction or
|
|
||||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
|
||||||
covered work, and grant a patent license to some of the parties
|
|
||||||
receiving the covered work authorizing them to use, propagate, modify
|
|
||||||
or convey a specific copy of the covered work, then the patent license
|
|
||||||
you grant is automatically extended to all recipients of the covered
|
|
||||||
work and works based on it.
|
|
||||||
|
|
||||||
A patent license is "discriminatory" if it does not include within
|
|
||||||
the scope of its coverage, prohibits the exercise of, or is
|
|
||||||
conditioned on the non-exercise of one or more of the rights that are
|
|
||||||
specifically granted under this License. You may not convey a covered
|
|
||||||
work if you are a party to an arrangement with a third party that is
|
|
||||||
in the business of distributing software, under which you make payment
|
|
||||||
to the third party based on the extent of your activity of conveying
|
|
||||||
the work, and under which the third party grants, to any of the
|
|
||||||
parties who would receive the covered work from you, a discriminatory
|
|
||||||
patent license (a) in connection with copies of the covered work
|
|
||||||
conveyed by you (or copies made from those copies), or (b) primarily
|
|
||||||
for and in connection with specific products or compilations that
|
|
||||||
contain the covered work, unless you entered into that arrangement,
|
|
||||||
or that patent license was granted, prior to 28 March 2007.
|
|
||||||
|
|
||||||
Nothing in this License shall be construed as excluding or limiting
|
|
||||||
any implied license or other defenses to infringement that may
|
|
||||||
otherwise be available to you under applicable patent law.
|
|
||||||
|
|
||||||
12. No Surrender of Others' Freedom.
|
|
||||||
|
|
||||||
If conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot convey a
|
|
||||||
covered work so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you may
|
|
||||||
not convey it at all. For example, if you agree to terms that obligate you
|
|
||||||
to collect a royalty for further conveying from those to whom you convey
|
|
||||||
the Program, the only way you could satisfy both those terms and this
|
|
||||||
License would be to refrain entirely from conveying the Program.
|
|
||||||
|
|
||||||
13. Use with the GNU Affero General Public License.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
|
||||||
permission to link or combine any covered work with a work licensed
|
|
||||||
under version 3 of the GNU Affero General Public License into a single
|
|
||||||
combined work, and to convey the resulting work. The terms of this
|
|
||||||
License will continue to apply to the part which is the covered work,
|
|
||||||
but the special requirements of the GNU Affero General Public License,
|
|
||||||
section 13, concerning interaction through a network will apply to the
|
|
||||||
combination as such.
|
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
|
||||||
the GNU General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Program specifies that a certain numbered version of the GNU General
|
|
||||||
Public License "or any later version" applies to it, you have the
|
|
||||||
option of following the terms and conditions either of that numbered
|
|
||||||
version or of any later version published by the Free Software
|
|
||||||
Foundation. If the Program does not specify a version number of the
|
|
||||||
GNU General Public License, you may choose any version ever published
|
|
||||||
by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
|
||||||
versions of the GNU General Public License can be used, that proxy's
|
|
||||||
public statement of acceptance of a version permanently authorizes you
|
|
||||||
to choose that version for the Program.
|
|
||||||
|
|
||||||
Later license versions may give you additional or different
|
|
||||||
permissions. However, no additional obligations are imposed on any
|
|
||||||
author or copyright holder as a result of your choosing to follow a
|
|
||||||
later version.
|
|
||||||
|
|
||||||
15. Disclaimer of Warranty.
|
|
||||||
|
|
||||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
|
||||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
|
||||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
|
||||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
|
||||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
|
||||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
16. Limitation of Liability.
|
|
||||||
|
|
||||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
|
||||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
|
||||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
|
||||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
|
||||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
|
||||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
|
||||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
|
||||||
SUCH DAMAGES.
|
|
||||||
|
|
||||||
17. Interpretation of Sections 15 and 16.
|
|
||||||
|
|
||||||
If the disclaimer of warranty and limitation of liability provided
|
|
||||||
above cannot be given local legal effect according to their terms,
|
|
||||||
reviewing courts shall apply local law that most closely approximates
|
|
||||||
an absolute waiver of all civil liability in connection with the
|
|
||||||
Program, unless a warranty or assumption of liability accompanies a
|
|
||||||
copy of the Program in return for a fee.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
state the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If the program does terminal interaction, make it output a short
|
|
||||||
notice like this when it starts in an interactive mode:
|
|
||||||
|
|
||||||
<program> Copyright (C) <year> <name of author>
|
|
||||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
||||||
This is free software, and you are welcome to redistribute it
|
|
||||||
under certain conditions; type `show c' for details.
|
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, your program's commands
|
|
||||||
might be different; for a GUI interface, you would use an "about box".
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
|
||||||
For more information on this, and how to apply and follow the GNU GPL, see
|
|
||||||
<https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
The GNU General Public License does not permit incorporating your program
|
|
||||||
into proprietary programs. If your program is a subroutine library, you
|
|
||||||
may consider it more useful to permit linking proprietary applications with
|
|
||||||
the library. If this is what you want to do, use the GNU Lesser General
|
|
||||||
Public License instead of this License. But first, please read
|
|
||||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
|
161
README.md
|
@ -1,161 +0,0 @@
|
||||||
# !!!! Be careful !!!!
|
|
||||||
## Use at your own risk
|
|
||||||
|
|
||||||
|
|
||||||
Soshot make webshot of internet page with headless machine (Google Chrome).
|
|
||||||
|
|
||||||
|
|
||||||
## Ideas
|
|
||||||
|
|
||||||
- If webshot exist in desired size, serve them, if not, verif if complete exist, if exist, crop and resize, save and serve
|
|
||||||
- If webshot not exist get information of page and add in the queue
|
|
||||||
- Cron job take a webshot of complete page and save them (1920 x complete lenth)
|
|
||||||
- Crop image and resize desired format (1920x1080, 1280x720, 160x90 ...), save and serve
|
|
||||||
|
|
||||||
SoShot always make complete webshot (1920x page lenght) + first demande size.
|
|
||||||
|
|
||||||
Size use 16/9 ratio :
|
|
||||||
|
|
||||||
- fav = define by config (default 48px)
|
|
||||||
- og = define by the website himself (no resize or crop)
|
|
||||||
- thumb = 160x90
|
|
||||||
- nhd = 640x360
|
|
||||||
- hd = 1280x720
|
|
||||||
- full = 1920x1080
|
|
||||||
- complete = 1920xpage height
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
### Docker (recommended)
|
|
||||||
|
|
||||||
For the moment I don't provide any image in any hub.
|
|
||||||
|
|
||||||
#### Build image
|
|
||||||
|
|
||||||
```shell
|
|
||||||
wget https://forge.leslibres.org/Knah-Tsaeb/Soshot/raw/branch/main/Dockerfile
|
|
||||||
docker buildx build --no-cache -t soshot:0.3.0 .
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Start container
|
|
||||||
|
|
||||||
You can use native docker volume.
|
|
||||||
|
|
||||||
docker run -v soshot_datas:/var/www/datas -v soshot_cache:/var/www/cache -e TZ=UTC -p 8187:80 --name soshot soshot:0.3.0
|
|
||||||
|
|
||||||
Or use absolute path
|
|
||||||
|
|
||||||
docker run -v /opt/soshot/datas:/var/www/datas -v /opt/soshot/cache:/var/www/public/cache -e TZ=UTC -p 8187:80 --name soshot soshot:0.3.0
|
|
||||||
|
|
||||||
### Classic way
|
|
||||||
|
|
||||||
#### Requirements
|
|
||||||
|
|
||||||
- PHP 8.*
|
|
||||||
- Sqlite3
|
|
||||||
- PDO
|
|
||||||
- Composer
|
|
||||||
- Imagick
|
|
||||||
- PHP-GD
|
|
||||||
- CRON
|
|
||||||
- Chrome / Chromium
|
|
||||||
|
|
||||||
Make directory on your web server and go in
|
|
||||||
|
|
||||||
```shell
|
|
||||||
mkdir /var/www/soshot && cd /var/www/soshot
|
|
||||||
```
|
|
||||||
|
|
||||||
Clone git repo
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git clone https://forge.leslibres.org/Knah-Tsaeb/Soshot.git .
|
|
||||||
```
|
|
||||||
|
|
||||||
Install dependencies
|
|
||||||
|
|
||||||
```shell
|
|
||||||
composer install --no-dev
|
|
||||||
```
|
|
||||||
|
|
||||||
Add cron task
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo crontab -u www-data -e
|
|
||||||
```
|
|
||||||
|
|
||||||
```shell
|
|
||||||
php /var/www/soshot/bin/thumbShoter.php
|
|
||||||
```
|
|
||||||
|
|
||||||
Configure your web server to serve in "public" directory.
|
|
||||||
|
|
||||||
Go to web page
|
|
||||||
https://shoshot.your-domain.tld
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
You can use a web interface (if option "use web gui" is set to true), https://shoshot.your-domain.tld/backend?page=settings
|
|
||||||
|
|
||||||
Or you can modify config file /datas/config.json.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"onlyLocalServer": true,
|
|
||||||
"webPage": false,
|
|
||||||
"log": true,
|
|
||||||
"alwaysMakePdf": false,
|
|
||||||
"icoSize": 48,
|
|
||||||
"expireCache": 12,
|
|
||||||
"maxGenPerBatch": 5,
|
|
||||||
"permitType": [],
|
|
||||||
"password": null,
|
|
||||||
"key": null,
|
|
||||||
"chromePath": null,
|
|
||||||
"fileFormat": "jpeg"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
| Option | Type | Default | Description |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| onlyLocalServer | bool | true | ShoShot only work for local machine, return 404 if use with remote machine |
|
|
||||||
| webPage | bool | false | Soshot only work with endpoint /api. Return 404 if not |
|
|
||||||
| log | bool | true | Not implemented yet |
|
|
||||||
| alwaysMakePdf | bool | false | If true, SoShot make a complete webshot and PDF of page |
|
|
||||||
| icoSize | int | 48 | Define size of favicon |
|
|
||||||
| expireCache | int | 12 | Not implemented yet |
|
|
||||||
| permitType | array | null | Select authorized size or type of webshot |
|
|
||||||
| maxGenPerBatch | int | 5 | Foreach cron task as launch, SoShot make 5 webshot |
|
|
||||||
| key | string | 12 | !!! DANGER !!! If you change key, all previous generation will be invalid. Soshot re make all previous generationt |
|
|
||||||
| password | string | null | Password for admin interface. No min or max character |
|
|
||||||
| chromePath | string | null | If path of Chrome/Chromium is not in PATH, you can define here |
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
For generating webshot the entry point is https://shoshot.your-domain.tld/api?
|
|
||||||
|
|
||||||
You need to define 3 parameters :
|
|
||||||
|
|
||||||
- type (fav, og, pdf, thumb, hd, full, complete)
|
|
||||||
- hmac (hash_hmac('sha1', url of page, your Api key);)
|
|
||||||
- url (url of page encode with url_encode)
|
|
||||||
|
|
||||||
|
|
||||||
Example : https://shoshot.your-domain.tld/api?type=fav&hmac=44a2b3f1bc43895c23779f4e71558e9976a4daf2&url=https%3A%2F%2Ffr.wikipedia.org%2Fwiki%2FLogiciel_libre
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
GNU General Public License v3.0
|
|
||||||
|
|
||||||
See LICENSE file for more detail.
|
|
||||||
|
|
||||||
**Thanks**
|
|
||||||
|
|
||||||
- [W3c](https://www.w3schools.com/w3css/) for w3.css
|
|
||||||
- [Fork Awesome](https://forkaweso.me/Fork-Awesome/) for icon
|
|
||||||
- [Iconify.design](https://icon-sets.iconify.design/iconamoon/star-off/) for default favicon
|
|
||||||
- [embed/embed](https://github.com/oscarotero/Embed) for embed (fav and og)
|
|
||||||
- [hassankhan/config](https://github.com/hassankhan/config) for config (config mananger)
|
|
||||||
- [chrome-php/chrome](https://github.com/chrome-php/chrome) for chrome-php (wrapper for chrome dev-tool)
|
|
||||||
- [stefangabos/zebra_image](https://github.com/stefangabos/Zebra_Image) for zebra-image (resize and manipulate image)
|
|
||||||
- [guzzlehttp/psr7](https://github.com/guzzle/psr7) for psr7 (PSR7 implement)
|
|
|
@ -1,319 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Controllers;
|
|
||||||
|
|
||||||
if (session_status() === PHP_SESSION_NONE) {
|
|
||||||
session_start();
|
|
||||||
}
|
|
||||||
|
|
||||||
use App\DataBase\DataBase;
|
|
||||||
use App\Utils\DeleteGen;
|
|
||||||
use App\Utils\Page;
|
|
||||||
use App\Utils\ShowImg;
|
|
||||||
use Noodlehaus\Config;
|
|
||||||
|
|
||||||
class Backend {
|
|
||||||
|
|
||||||
private $start = 0;
|
|
||||||
private $end = 15;
|
|
||||||
private $max = 15;
|
|
||||||
private $runningJob = false;
|
|
||||||
private $page = 'infos';
|
|
||||||
private $params;
|
|
||||||
private $conf;
|
|
||||||
private $title = 'Settings';
|
|
||||||
private $passwordRequired = false;
|
|
||||||
private $search = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the index action for the controller.
|
|
||||||
*
|
|
||||||
* This method performs various actions based on the provided parameters and
|
|
||||||
* configuration. It checks if the user is logged in, sets the page to display,
|
|
||||||
* checks if a job is running, and handles displaying images. It sets the
|
|
||||||
* configuration and parameters for the object. If the page is set to 'settings',
|
|
||||||
* it handles first run installation and option settings. Finally, it generates
|
|
||||||
* the HTML content for the page by requiring the navigation, infos or settings,
|
|
||||||
* and footer templates.
|
|
||||||
*
|
|
||||||
* @param object $params The parameters object.
|
|
||||||
* @param object $conf The configuration object.
|
|
||||||
*
|
|
||||||
* @return string The generated HTML content for the page.
|
|
||||||
*/
|
|
||||||
public function index(object $params, object $conf): string {
|
|
||||||
if (isset($params->loginPassword)) {
|
|
||||||
if (!Login::login($params->loginPassword, $conf->password)) {
|
|
||||||
$content = $this->showLogin();
|
|
||||||
return $content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Login::isLogin()) {
|
|
||||||
$content = $this->showLogin();
|
|
||||||
return $content;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($params->page)) {
|
|
||||||
$this->page = $params->page;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file_exists(__DIR__ . '/../../cache/tmp/chrome-php-socket')) {
|
|
||||||
$this->runningJob = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($params->showImg)) {
|
|
||||||
$img = new ShowImg($params->type, $params->showImg, $conf->fileFormat);
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($params->deleteGen)) {
|
|
||||||
$deleteGen = new DeleteGen();
|
|
||||||
$deleteGen->deleteGen($params->deleteGen);
|
|
||||||
$reset = new DataBase();
|
|
||||||
$reset->reset($params->deleteGen);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->conf = $conf;
|
|
||||||
$this->params = $params;
|
|
||||||
|
|
||||||
if ($this->page === 'settings') {
|
|
||||||
if (isset($_SESSION['firstRun']) && $_SESSION['firstRun'] === 1) {
|
|
||||||
$conf->webPage = false;
|
|
||||||
$this->title = 'Install';
|
|
||||||
$this->conf->key = bin2hex(random_bytes(12));
|
|
||||||
$this->passwordRequired = "required";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($this->params->token) && Page::verifToken($this->params->token)) {
|
|
||||||
$this->conf = $this->setOption($params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ob_start();
|
|
||||||
require_once __DIR__ . '/../../tpl/nav.php';
|
|
||||||
|
|
||||||
if ($this->page === 'infos') {
|
|
||||||
$this->showInfos();
|
|
||||||
} else {
|
|
||||||
$this->showSettings();
|
|
||||||
}
|
|
||||||
require_once __DIR__ . '/../../tpl/footer.php';
|
|
||||||
$content = ob_get_contents();
|
|
||||||
ob_end_clean();
|
|
||||||
return $content;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays information about the generated data.
|
|
||||||
*
|
|
||||||
* This method sets the start and end index for the data to display based on the
|
|
||||||
* provided parameters. It retrieves the data list, total count, error count, and
|
|
||||||
* queue count from the `DataBase` class. It calculates the start, maximum, next,
|
|
||||||
* and previous index values for pagination. It then requires the 'infos.php'
|
|
||||||
* template to display the information.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private function showInfos() {
|
|
||||||
if (!empty($this->params->search)) {
|
|
||||||
$search = htmlspecialchars(trim($this->params->search));
|
|
||||||
if (!empty($search)) {
|
|
||||||
$this->search = $search;
|
|
||||||
} else {
|
|
||||||
$this->search = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($this->params->start)) {
|
|
||||||
$this->start = $this->params->start;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($this->params->end)) {
|
|
||||||
$this->end = $this->max + $this->start;
|
|
||||||
}
|
|
||||||
|
|
||||||
$conx = new DataBase();
|
|
||||||
$genList = $conx->getList($this->start, $this->end, $this->search);
|
|
||||||
$total = $conx->getTotal();
|
|
||||||
$inError = $conx->getInError();
|
|
||||||
$inQueue = $this->getInQueue();
|
|
||||||
$start = $this->start;
|
|
||||||
|
|
||||||
$max = $this->max;
|
|
||||||
$next = $start + $max;
|
|
||||||
$previous = $start - ($max);
|
|
||||||
$search = $this->search;
|
|
||||||
|
|
||||||
if (count($genList) < $this->max) {
|
|
||||||
$next = $start;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($previous < 0) {
|
|
||||||
$previous = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
require __DIR__ . '/../../tpl/infos.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the settings page.
|
|
||||||
*
|
|
||||||
* This method sets the start and end index for the data to display based on the
|
|
||||||
* provided parameters. It retrieves the data list and total count from the
|
|
||||||
* `DataBase` class. It calculates the start and maximum index values for
|
|
||||||
* pagination. It generates a CSRF token using the `Page::genToken` method. It
|
|
||||||
* then requires the 'settings.php' template to display the settings page.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private function showSettings() {
|
|
||||||
if (!empty($this->params->start)) {
|
|
||||||
$this->start = $this->params->start;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($this->params->end)) {
|
|
||||||
$this->end = $this->max + $this->start;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->start < 0) {
|
|
||||||
$this->start = 0;
|
|
||||||
}
|
|
||||||
$conx = new DataBase();
|
|
||||||
$genList = $conx->getList($this->start, $this->end);
|
|
||||||
$total = $conx->getTotal();
|
|
||||||
$start = $this->start;
|
|
||||||
$max = $this->max;
|
|
||||||
$token = Page::genToken();
|
|
||||||
|
|
||||||
require __DIR__ . '/../../tpl/settings.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets and saves user configuration options.
|
|
||||||
*
|
|
||||||
* This method checks if the configuration file exists and creates an empty one if
|
|
||||||
* it doesn't. It then loads the user configuration from the file using the `Config`
|
|
||||||
* class. It sets various configuration options based on the provided `$post`
|
|
||||||
* parameter, such as server settings, logging, PDF generation, icon size, cache
|
|
||||||
* expiration, maximum generations per batch, permit types, file format, password,
|
|
||||||
* key, and Chrome path. It saves the updated configuration to the file using the
|
|
||||||
* `Config` class. Finally, it loads the updated configuration from the file and
|
|
||||||
* returns it as an object.
|
|
||||||
*
|
|
||||||
* @param object $post The POST data containing the configuration options.
|
|
||||||
*
|
|
||||||
* @return object The updated configuration object.
|
|
||||||
*/
|
|
||||||
private function setOption(object $post): object {
|
|
||||||
if (!file_exists(__DIR__ . '/../../datas/config.json')) {
|
|
||||||
file_put_contents(__DIR__ . '/../../datas/config.json', json_encode([]));
|
|
||||||
unset($_SESSION['login']);
|
|
||||||
unset($_SESSION['firstRun']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$userConfig = __DIR__ . '/../../datas/config.json';
|
|
||||||
$uConfig = new Config($userConfig);
|
|
||||||
|
|
||||||
if (empty($post->onlyLocalServer)) {
|
|
||||||
$uConfig['onlyLocalServer'] = false;
|
|
||||||
} else {
|
|
||||||
$uConfig['onlyLocalServer'] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($post->webPage)) {
|
|
||||||
$uConfig['webPage'] = false;
|
|
||||||
} else {
|
|
||||||
$uConfig['webPage'] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($post->log)) {
|
|
||||||
$uConfig['log'] = false;
|
|
||||||
} else {
|
|
||||||
$uConfig['log'] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($post->alwaysMakePdf)) {
|
|
||||||
$uConfig['alwaysMakePdf'] = false;
|
|
||||||
} else {
|
|
||||||
$uConfig['alwaysMakePdf'] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($post->icoSize)) {
|
|
||||||
$uConfig['icoSize'] = (int)$post->icoSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($post->expireCache)) {
|
|
||||||
$uConfig['expireCache'] = (int)$post->expireCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($post->maxGenPerBatch)) {
|
|
||||||
$uConfig['maxGenPerBatch'] = (int)$post->maxGenPerBatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($post->permitType)) {
|
|
||||||
$uConfig['permitType'] = $post->permitType;
|
|
||||||
} else {
|
|
||||||
$uConfig['permitType'] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($post->fileFormat)) {
|
|
||||||
$uConfig['fileFormat'] = $post->fileFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($post->password)) {
|
|
||||||
$uConfig['password'] = password_hash($post->password, PASSWORD_DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($post->key)) {
|
|
||||||
$uConfig['key'] = $post->key;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($post->chromePath)) {
|
|
||||||
$uConfig['chromePath'] = $post->chromePath;
|
|
||||||
} else {
|
|
||||||
$uConfig['chromePath'] = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
$uConfig->toFile($userConfig);
|
|
||||||
|
|
||||||
$newConfig = new Config($userConfig);
|
|
||||||
return (object)$newConfig->all();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the number of files in the queue directory.
|
|
||||||
*
|
|
||||||
* This method uses the `glob` function to search for JSON files in the queue
|
|
||||||
* directory. If any files are found, it returns the count of files. Otherwise,
|
|
||||||
* it returns 0.
|
|
||||||
*
|
|
||||||
* @return int The number of files in the queue directory.
|
|
||||||
*/
|
|
||||||
private function getInQueue(): int {
|
|
||||||
if (glob(__DIR__ . '/../../cache/queue/*.json') != false) {
|
|
||||||
$fileCount = count(glob(__DIR__ . '/../../cache/queue/*.json'));
|
|
||||||
} else {
|
|
||||||
$fileCount = 0;
|
|
||||||
}
|
|
||||||
return $fileCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the login page.
|
|
||||||
*
|
|
||||||
* This method generates a CSRF token using the `Page::genToken` method. It then
|
|
||||||
* requires the 'login.php' template to display the login page. Finally, it returns
|
|
||||||
* the generated HTML content as a string.
|
|
||||||
*
|
|
||||||
* @return string The generated HTML content for the login page.
|
|
||||||
*/
|
|
||||||
private function showLogin(): string {
|
|
||||||
ob_start();
|
|
||||||
$token = Page::genToken();
|
|
||||||
require_once __DIR__ . '/../../tpl/login.php';
|
|
||||||
$content = ob_get_contents();
|
|
||||||
ob_end_clean();
|
|
||||||
return $content;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
<?php
|
|
||||||
namespace App\Controllers;
|
|
||||||
|
|
||||||
class GenHmac {
|
|
||||||
function index($params, $conf) {
|
|
||||||
echo hash_hmac('sha1', $params->url, $conf->key);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Controllers;
|
|
||||||
|
|
||||||
use App\Utils\Hmac;
|
|
||||||
|
|
||||||
class Home {
|
|
||||||
public function index() {
|
|
||||||
ob_start();
|
|
||||||
require __DIR__ . '/../../tpl/home.php';
|
|
||||||
$content = ob_get_contents();
|
|
||||||
ob_end_clean();
|
|
||||||
return $content;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Controllers;
|
|
||||||
|
|
||||||
class Login {
|
|
||||||
static function isLogin() {
|
|
||||||
if (isset($_SESSION['login']) && $_SESSION['login'] === 1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static function login($password, $hash) {
|
|
||||||
if (password_verify($password, $hash)) {
|
|
||||||
$_SESSION['login'] = 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Controllers;
|
|
||||||
|
|
||||||
class Logout {
|
|
||||||
|
|
||||||
public function index() {
|
|
||||||
session_start();
|
|
||||||
session_destroy();
|
|
||||||
header("Location:/");
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Controllers;
|
|
||||||
|
|
||||||
use App\Soshot\GetThumb;
|
|
||||||
use App\Soshot\GetFav;
|
|
||||||
use App\Soshot\GetOg;
|
|
||||||
use App\Utils\Error;
|
|
||||||
|
|
||||||
class Result {
|
|
||||||
|
|
||||||
public function index($params, $conf) {
|
|
||||||
if (
|
|
||||||
!isset($params->type) ||
|
|
||||||
!isset($params->hmac) ||
|
|
||||||
!isset($params->url)
|
|
||||||
) {
|
|
||||||
$error = new Error();
|
|
||||||
$error->index((object)['status' => 400, 'message' => 'Missing parameters']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_array($params->type, $conf->permitType)) {
|
|
||||||
$error = new Error();
|
|
||||||
$error->index((object)['status' => 400, 'message' => 'Wrong type']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($params->type === 'fav') {
|
|
||||||
$favicon = new GetFav($params, $conf);
|
|
||||||
$favicon->show();
|
|
||||||
} elseif ($params->type === 'og') {
|
|
||||||
$favicon = new GetOg($params, $conf);
|
|
||||||
$favicon->show();
|
|
||||||
} else {
|
|
||||||
$result = new GetThumb($params, $conf);
|
|
||||||
$result->show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,309 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\DataBase;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use PDO;
|
|
||||||
|
|
||||||
use function App\Soshot\n_print as SoshotN_print;
|
|
||||||
|
|
||||||
if (!function_exists('n_print')) {
|
|
||||||
function n_print($data, $name = '') {
|
|
||||||
print_r($data, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DataBase {
|
|
||||||
|
|
||||||
private $dataBase = __DIR__ . '/../../datas/soshot.sqlite';
|
|
||||||
private $db;
|
|
||||||
private $params = [
|
|
||||||
'id' => '',
|
|
||||||
'url' => '',
|
|
||||||
'complete' => '',
|
|
||||||
'full' => '',
|
|
||||||
'hd' => '',
|
|
||||||
'nhd' => '',
|
|
||||||
'thumb' => '',
|
|
||||||
'fav' => '',
|
|
||||||
'og' => '',
|
|
||||||
'pdf' => '',
|
|
||||||
'created' => ''
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new instance of the DataBase class.
|
|
||||||
*
|
|
||||||
* This method creates a new SQLite database connection and sets the default fetch
|
|
||||||
* mode to PDO::FETCH_ASSOC. It also sets the error mode to PDO::ERRMODE_EXCEPTION.
|
|
||||||
* If the database file does not exist, it creates a new table named 'soshot' with
|
|
||||||
* the specified schema. If the $params parameter is not empty, the setParams()
|
|
||||||
* method is called to set the object's properties.
|
|
||||||
*
|
|
||||||
* @param object $params An associative array of parameters to set the object's
|
|
||||||
* properties.
|
|
||||||
*
|
|
||||||
* @return DataBase The constructed DataBase object.
|
|
||||||
*/
|
|
||||||
function __construct($params = null) {
|
|
||||||
try {
|
|
||||||
if (!file_exists($this->dataBase)) {
|
|
||||||
$this->db = new PDO('sqlite:' . $this->dataBase);
|
|
||||||
$this->db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
|
||||||
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION, PDO::ERRMODE_WARNING); // ERRMODE_WARNING | ERRMODE_EXCEPTION | ERRMODE_SILENT
|
|
||||||
|
|
||||||
$this->db->query("CREATE TABLE IF NOT EXISTS soshot (
|
|
||||||
id string PRIMARY KEY NOT NULL,
|
|
||||||
url text,
|
|
||||||
complete tinyint,
|
|
||||||
full tinyint,
|
|
||||||
hd tinyint,
|
|
||||||
nhd tinuyint,
|
|
||||||
thumb tinyint,
|
|
||||||
fav tinyint,
|
|
||||||
og tinyint,
|
|
||||||
pdf tinyint,
|
|
||||||
created DATETIME
|
|
||||||
);");
|
|
||||||
} else {
|
|
||||||
$this->db = new PDO('sqlite:' . $this->dataBase);
|
|
||||||
$this->db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
|
||||||
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // ERRMODE_WARNING | ERRMODE_EXCEPTION | ERRMODE_SILENT
|
|
||||||
|
|
||||||
$this->updateTable();
|
|
||||||
}
|
|
||||||
} catch (Exception $e) {
|
|
||||||
echo $e->getMessage();
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($params)) {
|
|
||||||
$this->setParams($params);
|
|
||||||
}
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function updateTable() {
|
|
||||||
$stmt = $this->db->prepare("SELECT * FROM soshot LIMIT 1;");
|
|
||||||
$stmt->execute();
|
|
||||||
$existingColumns = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
if (empty($existingColumns)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$existingColumns = array_keys($existingColumns);
|
|
||||||
|
|
||||||
$newColumns = array_diff(array_keys($this->params), $existingColumns);
|
|
||||||
|
|
||||||
foreach ($newColumns as $column) {
|
|
||||||
$sql = "ALTER TABLE soshot ADD `{$column}` tinyint";
|
|
||||||
$this->db->exec($sql);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the parameters for the database query.
|
|
||||||
*
|
|
||||||
* This method takes an object containing the parameters for the database query and
|
|
||||||
* sets the corresponding properties of the object.
|
|
||||||
*
|
|
||||||
* @param object $params An object containing the parameters for the database query.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function setParams(object $params) {
|
|
||||||
$this->params = (object)$this->params;
|
|
||||||
$this->params->id = $params->hmac;
|
|
||||||
$this->params->url = $params->url;
|
|
||||||
$this->params->type = $params->type;
|
|
||||||
$this->params->created = date("Y-m-d H:i:s");
|
|
||||||
$this->params = $this->params;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds or updates a record in the database.
|
|
||||||
*
|
|
||||||
* This method takes an update value and an optional type parameter. If the type
|
|
||||||
* parameter is not empty, it sets the type property of the object. It then checks
|
|
||||||
* if a record with the same ID already exists in the database using the testExit
|
|
||||||
* method. If a record exists, it calls the update method to update the existing
|
|
||||||
* record. If no record exists, it calls the insert method to insert a new record.
|
|
||||||
*
|
|
||||||
* @param int $update The update value to be inserted or updated in the database.
|
|
||||||
* @param string $type The type of the update.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function addUpdate(int $update, string $type = '') {
|
|
||||||
if (!empty($type)) {
|
|
||||||
$this->params->type = $type;
|
|
||||||
}
|
|
||||||
if ($this->testExit($this->params->id)) {
|
|
||||||
$this->update($update);
|
|
||||||
} else {
|
|
||||||
$this->insert($update);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inserts a new record into the database.
|
|
||||||
*
|
|
||||||
* This method prepares an SQL INSERT statement using the provided parameters, and
|
|
||||||
* executes it to insert a new record into the "soshot" table in the database.
|
|
||||||
*
|
|
||||||
* @param int $update The value to insert into the type column of the new record.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function insert(int $update) {
|
|
||||||
$stmt = $this->db->prepare("INSERT INTO soshot (id, url, " . $this->params->type . ", created) VALUES
|
|
||||||
(:id, :url, :" . $this->params->type . ", :created)");
|
|
||||||
//$stmt->debugDumpParams();
|
|
||||||
|
|
||||||
$result = $stmt->execute(array(
|
|
||||||
'id' => $this->params->id,
|
|
||||||
'url' => $this->params->url,
|
|
||||||
$this->params->type => $update,
|
|
||||||
'created' => $this->params->created
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates a record in the database.
|
|
||||||
*
|
|
||||||
* This method prepares an SQL UPDATE statement using the provided parameters, and
|
|
||||||
* executes it to update a record in the "soshot" table in the database.
|
|
||||||
*
|
|
||||||
* @param string $update The value to update in the type column of the record.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private function update(string $update) {
|
|
||||||
$stmt = $this->db->prepare("UPDATE soshot
|
|
||||||
SET " . $this->params->type . "=:" . $this->params->type . "
|
|
||||||
WHERE id=:id;");
|
|
||||||
|
|
||||||
$result = $stmt->execute([
|
|
||||||
':' . $this->params->type => $update,
|
|
||||||
':id' => $this->params->id
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset .
|
|
||||||
*
|
|
||||||
* This method prepares an SQL UPDATE statement using the provided parameters, and
|
|
||||||
* executes it to update a record in the "soshot" table in the database.
|
|
||||||
*
|
|
||||||
* @param string $update The value to update in the type column of the record.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function reset(string $id) {
|
|
||||||
|
|
||||||
$resetParam = [];
|
|
||||||
|
|
||||||
$updateParams = $this->params;
|
|
||||||
unset($updateParams['id'], $updateParams['url'], $updateParams['created']);
|
|
||||||
|
|
||||||
foreach ($updateParams as $key => $value) {
|
|
||||||
$resetParam[] = $key . ' = null';
|
|
||||||
}
|
|
||||||
|
|
||||||
$strUpdateParam = implode(',', $resetParam);
|
|
||||||
|
|
||||||
$stmt = $this->db->prepare("UPDATE soshot
|
|
||||||
SET $strUpdateParam
|
|
||||||
WHERE id=:id;");
|
|
||||||
|
|
||||||
$result = $stmt->execute([
|
|
||||||
':id' => $id
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a record with the given ID exists in the database.
|
|
||||||
*
|
|
||||||
* This method prepares an SQL SELECT statement using the provided ID, and executes
|
|
||||||
* it to retrieve the corresponding record from the "soshot" table in the database.
|
|
||||||
* If a record is found, the method returns true. Otherwise, it returns false.
|
|
||||||
*
|
|
||||||
* @param string $id The ID of the record to check.
|
|
||||||
*
|
|
||||||
* @return bool True if a record with the given ID exists in the database, false otherwise.
|
|
||||||
*/
|
|
||||||
private function testExit(string $id): bool {
|
|
||||||
$stmt = $this->db->prepare("SELECT id FROM soshot WHERE id=:id LIMIT 1;");
|
|
||||||
$stmt->execute(array(':id' => $id));
|
|
||||||
$result = $stmt->fetchAll(PDO::FETCH_OBJ);
|
|
||||||
if (!empty($result)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the total number of records in the "soshot" table.
|
|
||||||
*
|
|
||||||
* This method prepares an SQL SELECT statement to retrieve the total number of
|
|
||||||
* records in the "soshot" table, executes the statement, and returns the result.
|
|
||||||
*
|
|
||||||
* @return int The total number of records in the "soshot" table.
|
|
||||||
*/
|
|
||||||
public function getTotal(): int {
|
|
||||||
$stmt = $this->db->prepare("SELECT COUNT(id) AS nb FROM soshot;");
|
|
||||||
$stmt->execute();
|
|
||||||
$result = $stmt->fetch();
|
|
||||||
return $result['nb'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the number of records with errors in the "soshot" table.
|
|
||||||
*
|
|
||||||
* This method prepares an SQL SELECT statement to retrieve the number of records
|
|
||||||
* with errors in the "soshot" table, executes the statement, and returns the result.
|
|
||||||
*
|
|
||||||
* @return int The number of records with errors in the "soshot" table.
|
|
||||||
*/
|
|
||||||
public function getInError(): int {
|
|
||||||
$stmt = $this->db->prepare("SELECT COUNT(DISTINCT id) AS nb FROM soshot WHERE
|
|
||||||
complete = 2 OR
|
|
||||||
full = 2 OR
|
|
||||||
hd = 2 OR
|
|
||||||
nhd = 2 OR
|
|
||||||
thumb = 2 OR
|
|
||||||
fav = 2 OR
|
|
||||||
og = 2 OR
|
|
||||||
pdf = 2;");
|
|
||||||
$stmt->execute();
|
|
||||||
$result = $stmt->fetch();
|
|
||||||
return $result['nb'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves a list of records from the "soshot" table.
|
|
||||||
*
|
|
||||||
* This method prepares an SQL SELECT statement to retrieve a list of records from
|
|
||||||
* the "soshot" table, based on the specified start and end indices, orders the
|
|
||||||
* results by the "created" column in descending order, executes the statement, and
|
|
||||||
* returns the result set as an array of objects.
|
|
||||||
*
|
|
||||||
* @param int $start The starting index of the record to retrieve.
|
|
||||||
* @param int $end The ending index of the record to retrieve.
|
|
||||||
*
|
|
||||||
* @return array An array of objects representing the records in the "soshot" table.
|
|
||||||
*/
|
|
||||||
public function getList(int $start, int $end, string $search = null) {
|
|
||||||
if ($search != null) {
|
|
||||||
$stmt = $this->db->prepare("SELECT * FROM soshot WHERE url like '%$search%' ORDER BY created DESC limit :start, :end;");
|
|
||||||
} else {
|
|
||||||
$stmt = $this->db->prepare("SELECT * FROM soshot ORDER BY created DESC limit :start, :end;");
|
|
||||||
}
|
|
||||||
$stmt->execute(array(':start' => $start, ':end' => $end));
|
|
||||||
$result = $stmt->fetchAll(PDO::FETCH_OBJ);
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,71 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App;
|
|
||||||
|
|
||||||
use App\Utils\Error;
|
|
||||||
|
|
||||||
class Router {
|
|
||||||
private $routes;
|
|
||||||
private $params = [];
|
|
||||||
private $requestMethod;
|
|
||||||
private $path;
|
|
||||||
|
|
||||||
public function __construct() {
|
|
||||||
$this->routes = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addRoute($paths, $controller, $method = 'GET') {
|
|
||||||
|
|
||||||
if (!is_array($paths)) {
|
|
||||||
$paths = [$paths];
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($paths as $path) {
|
|
||||||
$this->routes[$path] = [
|
|
||||||
'controller' => $controller,
|
|
||||||
'method' => $method
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function match() {
|
|
||||||
$path = $_SERVER['REQUEST_URI'];
|
|
||||||
$parts = parse_url($path);
|
|
||||||
$this->path = $parts['path'];
|
|
||||||
|
|
||||||
$this->requestMethod = $_SERVER['REQUEST_METHOD'];
|
|
||||||
|
|
||||||
if (isset($this->routes[$this->path])) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function render($conf) {
|
|
||||||
if ($this->requestMethod === 'GET') {
|
|
||||||
$this->params = (object)$_GET;
|
|
||||||
} elseif ($this->requestMethod === 'POST') {
|
|
||||||
$this->params = (object)$_POST;
|
|
||||||
} else {
|
|
||||||
$error = new Error();
|
|
||||||
$error->index((object)['status' => 405, 'message' => 'Method not allowed']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($conf->webPage === false && $this->path !== '/api') {
|
|
||||||
$error = new Error();
|
|
||||||
$error->index((object)['status' => 404, 'message' => 'The page that you have requested could not be found.']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->path === '/debug') {
|
|
||||||
require_once __DIR__ . '/../bin/thumbShoter.php';
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
$className = '\\' . $this->routes[$this->path]['controller'];
|
|
||||||
$controllerInstance = new $className();
|
|
||||||
$content = $controllerInstance->index($this->params, $conf);
|
|
||||||
if (in_array($className, ['\App\Controllers\Home', '\App\Controllers\Backend']) && empty($this->params->showImg)) {
|
|
||||||
require_once __DIR__ . '/../tpl/bone.php';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,103 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Soshot;
|
|
||||||
|
|
||||||
use App\Soshot\GetThumb;
|
|
||||||
use App\Utils\ConvertIco;
|
|
||||||
use Embed\Embed;
|
|
||||||
use Zebra_Image;
|
|
||||||
|
|
||||||
class GetFav extends GetThumb {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a favicon for a given URL.
|
|
||||||
*
|
|
||||||
* This method takes the URL provided in the `demande` object and uses the Embed
|
|
||||||
* library to extract the favicon or icon from the website. If the favicon or icon
|
|
||||||
* cannot be extracted, a default error image is used. The favicon is then resized
|
|
||||||
* to the specified size and saved to the specified file path. If the favicon is in
|
|
||||||
* ICO or SVG format, it is converted to PNG format using the ConvertIco class. The
|
|
||||||
* method updates the database with the status of the favicon creation.
|
|
||||||
*
|
|
||||||
* @return bool True if the favicon was successfully created, false otherwise.
|
|
||||||
*/
|
|
||||||
public function makeFavicon() {
|
|
||||||
|
|
||||||
if (!is_dir($this->filePath)) {
|
|
||||||
mkdir($this->demande->filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$embed = new Embed();
|
|
||||||
$info = $embed->get($this->demande->url);
|
|
||||||
|
|
||||||
if (!is_null($info->favicon)) {
|
|
||||||
if (!$favicon = @file_get_contents($info->favicon)) {
|
|
||||||
copy(__DIR__ . '/../../src/images/error_fav.png', $this->demande->requestImg);
|
|
||||||
$this->db->addUpdate(2, $this->type);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} elseif (!is_null($info->icon)) {
|
|
||||||
if (!$favicon = @file_get_contents($info->icon)) {
|
|
||||||
copy(__DIR__ . '/../../src/images/error_fav.png', $this->demande->requestImg);
|
|
||||||
$this->db->addUpdate(2, $this->type);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
copy(__DIR__ . '/../../src/images/error_fav.png', $this->demande->requestImg);
|
|
||||||
$this->db->addUpdate(2, $this->type);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
file_put_contents($this->demande->requestImg, $favicon);
|
|
||||||
|
|
||||||
$realMimeType = mime_content_type($this->demande->requestImg);
|
|
||||||
|
|
||||||
if ($realMimeType === 'image/vnd.microsoft.icon') {
|
|
||||||
ConvertIco::convert($this->demande, $this->conf->icoSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($realMimeType === 'image/svg+xml') {
|
|
||||||
ConvertIco::convert($this->demande, $this->conf->icoSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
$image = new Zebra_Image();
|
|
||||||
$image->source_path = $this->demande->requestImg;
|
|
||||||
$image->target_path = $this->demande->requestImg;
|
|
||||||
$image->preserve_time = false;
|
|
||||||
$image->enlarge_smaller_images = false;
|
|
||||||
$image->resize($this->conf->icoSize, $this->conf->icoSize, ZEBRA_IMAGE_CROP_TOPLEFT);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
$this->db->addUpdate(2, $this->type);
|
|
||||||
copy(__DIR__ . '/../../src/images/error_fav.png', $this->demande->requestImg);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_file($this->demande->requestImg)) {
|
|
||||||
copy(__DIR__ . '/../../src/images/error_fav.png', $this->demande->requestImg);
|
|
||||||
$this->db->addUpdate(2, $this->type);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
$this->db->addUpdate(1, $this->type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the requested image.
|
|
||||||
*
|
|
||||||
* This method checks if the requested image file exists. If the requested image is
|
|
||||||
* a favicon and does not exist, it calls the makeFavicon method to generate it.
|
|
||||||
* Then, it sets the appropriate headers for the image and outputs its contents.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function show() {
|
|
||||||
if (!file_exists($this->requestImg) && $this->type === 'fav') {
|
|
||||||
$this->makeFavicon();
|
|
||||||
}
|
|
||||||
header("Content-type: image/$this->fileFormat");
|
|
||||||
header('Expires: ', gmdate('D, d M Y H:i:s', time()) . ' GMT');
|
|
||||||
echo file_get_contents($this->requestImg);
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Soshot;
|
|
||||||
|
|
||||||
use App\Soshot\GetThumb;
|
|
||||||
use Embed\Embed;
|
|
||||||
use App\Utils\ConvertToPng;
|
|
||||||
|
|
||||||
class GetOg extends GetThumb {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate the OG image for a given URL.
|
|
||||||
*
|
|
||||||
* This method retrieves the OG image from the provided URL using the Embed library.
|
|
||||||
* If the image cannot be retrieved, an error image is used instead. The image is
|
|
||||||
* then saved to the specified file path. If the image format is not PNG, it is
|
|
||||||
* converted to PNG using the ConvertToPng class. The method updates the database
|
|
||||||
* with the status of the OG image creation.
|
|
||||||
*
|
|
||||||
* @return bool True if the OG image was successfully created, false otherwise.
|
|
||||||
*/
|
|
||||||
public function makeOg() {
|
|
||||||
|
|
||||||
if (!is_dir($this->filePath)) {
|
|
||||||
mkdir($this->demande->filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$embed = new Embed();
|
|
||||||
$info = $embed->get($this->demande->url);
|
|
||||||
|
|
||||||
if (!is_null($info->image)) {
|
|
||||||
if (!$image = file_get_contents($info->image)) {
|
|
||||||
copy(__DIR__ . '/../../src/images/error_thumb.png', $this->demande->requestImg);
|
|
||||||
$this->db->addUpdate(2, $this->type);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
copy(__DIR__ . '/../../src/images/error_thumb.png', $this->demande->requestImg);
|
|
||||||
$this->db->addUpdate(2, $this->type);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($image)) {
|
|
||||||
copy(__DIR__ . '/../../src/images/error_thumb.png', $this->demande->requestImg);
|
|
||||||
$this->db->addUpdate(2, $this->type);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
file_put_contents($this->demande->requestImg, $image);
|
|
||||||
|
|
||||||
if (in_array(mime_content_type($this->demande->requestImg), ['image/jpg', 'image/jpeg', 'image/bmp', 'image/webp']) && $this->fileFormat === 'png') {
|
|
||||||
// @todo convertToWebp convertToJpg
|
|
||||||
ConvertToPng::convertToPng($this->demande);
|
|
||||||
}
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
copy(__DIR__ . '/../../src/images/error_thumb.png', $this->demande->requestImg);
|
|
||||||
$this->db->addUpdate(2, $this->type);
|
|
||||||
}
|
|
||||||
if (!is_file($this->demande->requestImg)) {
|
|
||||||
copy(__DIR__ . '/../../src/images/error_thumb.png', $this->demande->requestImg);
|
|
||||||
$this->db->addUpdate(2, $this->type);
|
|
||||||
} else {
|
|
||||||
$this->db->addUpdate(1, $this->type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the OG image for a given URL.
|
|
||||||
*
|
|
||||||
* This method checks if the OG image file exists and if the type is 'og'. If the
|
|
||||||
* file does not exist, it calls the makeOg() method to generate the OG image. It
|
|
||||||
* then sets the appropriate headers and outputs the contents of the OG image file.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function show() {
|
|
||||||
if (file_exists($this->requestImg) && $this->type === 'og') {
|
|
||||||
} else {
|
|
||||||
$this->makeOg();
|
|
||||||
}
|
|
||||||
|
|
||||||
//echo '<img src="data:' . mime_content_type($this->requestImg) . ';base64,' . base64_encode(file_get_contents($this->requestImg)) . '">';
|
|
||||||
header("Content-type: " . mime_content_type($this->requestImg));
|
|
||||||
header('Expires: ', gmdate('D, d M Y H:i:s', time()) . ' GMT');
|
|
||||||
echo file_get_contents($this->requestImg);
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,163 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Soshot;
|
|
||||||
|
|
||||||
use App\DataBase\DataBase;
|
|
||||||
use App\Utils\Hmac;
|
|
||||||
use App\Utils\Error;
|
|
||||||
use App\Utils\ResizeToDemande;
|
|
||||||
|
|
||||||
class GetThumb {
|
|
||||||
|
|
||||||
protected $params;
|
|
||||||
protected $type;
|
|
||||||
protected $filePath;
|
|
||||||
protected $receiveHmac;
|
|
||||||
protected $requestImg;
|
|
||||||
protected $queuePath = __DIR__ . '/../../cache/queue/';
|
|
||||||
protected $complete;
|
|
||||||
protected $conf;
|
|
||||||
protected $db;
|
|
||||||
protected $demande;
|
|
||||||
protected $fileFormat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new object.
|
|
||||||
*
|
|
||||||
* This method initializes the object properties based on the provided parameters
|
|
||||||
* and configuration. It first checks if the provided HMAC is valid using the
|
|
||||||
* Hmac class. If the HMAC is invalid, it returns an error message. It then sets
|
|
||||||
* the object properties for the request URL, HMAC, type, file format, file path,
|
|
||||||
* request image path, complete image path, and database connection.
|
|
||||||
*
|
|
||||||
* @param object $params The request parameters object containing the URL, HMAC, and type.
|
|
||||||
* @param object $conf The configuration object containing the file format and key.
|
|
||||||
*
|
|
||||||
* @return GetOg The constructed GetOg object.
|
|
||||||
*/
|
|
||||||
function __construct(object $params, object $conf) {
|
|
||||||
$hmac = new Hmac($conf->key);
|
|
||||||
$this->conf = $conf;
|
|
||||||
$this->receiveHmac = $params->hmac;
|
|
||||||
|
|
||||||
if ($hmac->checkHmac($this->receiveHmac, $params->url) === false) {
|
|
||||||
$message = (object) ['status' => 404, 'message' => 'Wrong Hmac'];
|
|
||||||
$error = new Error();
|
|
||||||
$error->index($message);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->params = $params;
|
|
||||||
$this->type = $params->type;
|
|
||||||
$this->fileFormat = $this->conf->fileFormat;
|
|
||||||
$this->filePath = $hmac->makeFilePath($this->receiveHmac);
|
|
||||||
if ($this->type === 'pdf') {
|
|
||||||
$this->requestImg = $this->filePath . $this->receiveHmac . '_' . $this->type . '.pdf';
|
|
||||||
} else {
|
|
||||||
$this->requestImg = $this->filePath . $this->receiveHmac . '_' . $this->type . '.' . $this->fileFormat;
|
|
||||||
}
|
|
||||||
$this->complete = __DIR__ . '/../../cache/img/' . substr($this->params->hmac, 0, 4) . '/' . $this->params->hmac . '_complete.' . $this->fileFormat;
|
|
||||||
|
|
||||||
$this->demande = (object)[
|
|
||||||
'url' => $this->params->url,
|
|
||||||
'hmac' => $this->params->hmac,
|
|
||||||
'filePath' => $this->filePath,
|
|
||||||
'requestImg' => $this->requestImg,
|
|
||||||
'type' => $this->params->type
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->db = new DataBase($this->demande);
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the requested image or PDF.
|
|
||||||
*
|
|
||||||
* This method checks if the requested file exists and serves it with the appropriate
|
|
||||||
* headers. If the requested file does not exist, it checks if a complete image exists
|
|
||||||
* and resizes it to the requested type. If neither the requested file nor a complete
|
|
||||||
* image exists, it adds a job to the queue to generate the requested image and serves
|
|
||||||
* a placeholder image.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function show() {
|
|
||||||
if ($this->type === 'pdf' && file_exists($this->requestImg)) {
|
|
||||||
header("Content-type:application/pdf");
|
|
||||||
header('Expires: ', gmdate('D, d M Y H:i:s', time()) . ' GMT');
|
|
||||||
header("Content-Disposition:attachment;filename=\"archive.pdf\"");
|
|
||||||
readfile($this->requestImg);
|
|
||||||
echo file_get_contents($this->requestImg);
|
|
||||||
exit();
|
|
||||||
} else if (file_exists($this->requestImg) && in_array($this->type, ['complete', 'full', 'hd', 'nhd', 'thumb'])) {
|
|
||||||
header("Content-type: image/$this->fileFormat");
|
|
||||||
header('Expires: ', gmdate('D, d M Y H:i:s', time()) . ' GMT');
|
|
||||||
echo file_get_contents($this->requestImg);
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
if (file_exists($this->complete) && in_array($this->type, ['complete', 'full', 'hd', 'nhd', 'thumb'])) {
|
|
||||||
if (ResizeToDemande::makeDemande((object)[
|
|
||||||
'complete' => $this->complete,
|
|
||||||
'filePath' => $this->requestImg,
|
|
||||||
'type' => $this->type
|
|
||||||
])) {
|
|
||||||
$this->db->addUpdate(1, $this->type);
|
|
||||||
header("Content-type: image/$this->fileFormat");
|
|
||||||
header('Expires: ', gmdate('D, d M Y H:i:s', time()) . ' GMT');
|
|
||||||
echo file_get_contents($this->requestImg);
|
|
||||||
exit();
|
|
||||||
} else {
|
|
||||||
// @todo log
|
|
||||||
}
|
|
||||||
exit();
|
|
||||||
} else {
|
|
||||||
$json = json_encode([
|
|
||||||
'type' => $this->params->type,
|
|
||||||
'hmac' => $this->params->hmac,
|
|
||||||
'url' => $this->params->url,
|
|
||||||
'filePath' => $this->requestImg,
|
|
||||||
'complete' => __DIR__ . '/../../cache/img/' . substr($this->params->hmac, 0, 4) . '/' . $this->params->hmac . '_complete.' . $this->fileFormat
|
|
||||||
]);
|
|
||||||
|
|
||||||
$completeDemande = (object)[
|
|
||||||
'url' => $this->params->url,
|
|
||||||
'hmac' => $this->params->hmac,
|
|
||||||
'filePath' => $this->filePath,
|
|
||||||
'requestImg' => $this->requestImg,
|
|
||||||
'type' => 'complete'
|
|
||||||
];
|
|
||||||
$complete = new DataBase($completeDemande);
|
|
||||||
$complete->addUpdate(3, $this->type);
|
|
||||||
|
|
||||||
if ($this->conf->alwaysMakePdf === true) {
|
|
||||||
$complete->addUpdate(3, 'pdf');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->addQueue($json);
|
|
||||||
|
|
||||||
header("Content-type: image/png");
|
|
||||||
header('Expires: ', gmdate('D, d M Y H:i:s', time()) . ' GMT');
|
|
||||||
if ($this->type === 'fav') {
|
|
||||||
echo file_get_contents(__DIR__ . '/../../src/images/error_fav.png');
|
|
||||||
} else {
|
|
||||||
echo file_get_contents(__DIR__ . '/../../src/images/' . $this->type . '_generation_in_progress.jpg');
|
|
||||||
}
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a JSON object to the queue file.
|
|
||||||
*
|
|
||||||
* @param string $json The JSON object to add to the queue file.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private function addQueue($json) {
|
|
||||||
$file = $this->queuePath . $this->receiveHmac . '.json';
|
|
||||||
$this->db->addUpdate(3, $this->type);
|
|
||||||
if (!file_exists($file)) {
|
|
||||||
file_put_contents($file, $json);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,297 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Soshot;
|
|
||||||
|
|
||||||
use App\DataBase\DataBase;
|
|
||||||
use App\Utils\ResizeToDemande;
|
|
||||||
use HeadlessChromium\Browser;
|
|
||||||
use HeadlessChromium\BrowserFactory;
|
|
||||||
use HeadlessChromium\Page;
|
|
||||||
use HeadlessChromium\Exception\BrowserConnectionFailed;
|
|
||||||
use HeadlessChromium\Exception\OperationTimedOut;
|
|
||||||
use Noodlehaus\Config;
|
|
||||||
|
|
||||||
if (!function_exists('n_print')) {
|
|
||||||
function n_print($data, $name = '') {
|
|
||||||
print_r($data, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MakeThumb {
|
|
||||||
|
|
||||||
private $queuePath = __DIR__ . '/../../cache/queue/';
|
|
||||||
private $thumbPath = __DIR__ . '/../../cache/img/';
|
|
||||||
private $fileSocket = __DIR__ . '/../../cache/tmp/chrome-php-socket';
|
|
||||||
private $fileList = [];
|
|
||||||
private $maxGenPerBatch = 2;
|
|
||||||
private $demandes = [];
|
|
||||||
private $open = false;
|
|
||||||
private $conf;
|
|
||||||
private $db;
|
|
||||||
private $chromePath = '';
|
|
||||||
private $tmpDir = '/tmp/chrome_soshot';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new instance of the class.
|
|
||||||
*
|
|
||||||
* This method loads the default and user configuration files using the `Config`
|
|
||||||
* class. It sets the maximum number of generations per batch, the Chrome path, and
|
|
||||||
* the queue path. It then retrieves the list of JSON files in the queue directory
|
|
||||||
* and decodes their contents to populate the `$demandes` property. Finally, it
|
|
||||||
* initializes the `DataBase` object and assigns it to the `$db` property.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function __construct() {
|
|
||||||
|
|
||||||
$this->conf = (object)Config::load([__DIR__ . '/../../datas/config.default.json', '?' . __DIR__ . '/../../datas/config.json'])->all();
|
|
||||||
$this->maxGenPerBatch = $this->conf->maxGenPerBatch;
|
|
||||||
|
|
||||||
$this->chromePath = $this->conf->chromePath;
|
|
||||||
|
|
||||||
foreach (array_slice(glob($this->queuePath . "*.json"), 0, $this->maxGenPerBatch) as $filename) {
|
|
||||||
$this->fileList[] = $filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($this->fileList as $demande) {
|
|
||||||
$this->demandes[] = json_decode(file_get_contents($demande));
|
|
||||||
}
|
|
||||||
$this->db = new DataBase();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes the demands in the queue.
|
|
||||||
*
|
|
||||||
* This method iterates over the list of demands in the `$demandes` property.
|
|
||||||
* For each demand, it sets the parameters for the `DataBase` object, writes the HMAC
|
|
||||||
* to a temporary file, and checks if the demand is already complete.
|
|
||||||
*
|
|
||||||
* If the demand is complete and not a PDF, it resizes the image to the demanded size using the
|
|
||||||
* `ResizeToDemande` class.
|
|
||||||
*
|
|
||||||
* If the demand is not complete, it generates the complete image using the `makeComplete` method.
|
|
||||||
*
|
|
||||||
* In either case, it deletes the demand from the queue using the `deleteQueue` method and
|
|
||||||
* updates the database using the `addUpdate` method.
|
|
||||||
*
|
|
||||||
* Finally, it sets the `$open` property to `true` to indicate that the queue is open.
|
|
||||||
* If the `$open` property is `true`, it generates a complete
|
|
||||||
* image for all demands in the queue using the `makeComplete` method.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function compute() {
|
|
||||||
foreach ($this->demandes as $demande) {
|
|
||||||
$this->db->setParams($demande);
|
|
||||||
file_put_contents('/tmp/soshot_queue', $demande->hmac);
|
|
||||||
|
|
||||||
// todo verif permit type
|
|
||||||
|
|
||||||
if ($this->testComplete($demande->complete) && $demande->type !== 'pdf') {
|
|
||||||
if (ResizeToDemande::makeDemande($demande)) {
|
|
||||||
$this->deleteQueue($demande->hmac);
|
|
||||||
$this->db->addUpdate(1, $demande->type);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$this->makeComplete($demande);
|
|
||||||
if ($demande->type !== 'pdf') {
|
|
||||||
if (!ResizeToDemande::makeDemande($demande)) {
|
|
||||||
// todo log
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->deleteQueue($demande->hmac);
|
|
||||||
$this->db->addUpdate(1, $demande->type);
|
|
||||||
|
|
||||||
$completeDemande = (object)[
|
|
||||||
'hmac' => $demande->hmac,
|
|
||||||
'url' => $demande->url,
|
|
||||||
'type' => 'complete'
|
|
||||||
];
|
|
||||||
$complete = new DataBase($completeDemande);
|
|
||||||
$complete->addUpdate(1, $demande->type);
|
|
||||||
}
|
|
||||||
$this->open = true;
|
|
||||||
|
|
||||||
if ($this->open === true) {
|
|
||||||
$this->makeComplete(null, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes a demand from the queue.
|
|
||||||
*
|
|
||||||
* This method takes an HMAC as a parameter and deletes the corresponding JSON file
|
|
||||||
* from the queue directory using the `unlink` function.
|
|
||||||
*
|
|
||||||
* @param string $hmac The HMAC of the demand to delete.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private function deleteQueue(string $hmac) {
|
|
||||||
if (file_exists($this->queuePath . $hmac . '.json')) {
|
|
||||||
unlink($this->queuePath . $hmac . '.json');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a file exists.
|
|
||||||
*
|
|
||||||
* This method takes a file path as a parameter and checks if the file exists using
|
|
||||||
* the `file_exists` function. It returns `true` if the file exists, and `false`
|
|
||||||
* otherwise.
|
|
||||||
*
|
|
||||||
* @param string $complete The file path to check.
|
|
||||||
*
|
|
||||||
* @return bool `true` if the file exists, `false` otherwise.
|
|
||||||
*/
|
|
||||||
private function testComplete(string $complete): bool {
|
|
||||||
if (file_exists($complete)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a complete image or PDF for a demand.
|
|
||||||
*
|
|
||||||
* This method takes a demand object as a parameter and generates a complete image
|
|
||||||
* or PDF for the demand.
|
|
||||||
*
|
|
||||||
* If the `$close` parameter is set to `true`, it closes the browser and deletes the socket file.
|
|
||||||
* The method first checks if a socket file exists and connects to an existing browser if it does.
|
|
||||||
*
|
|
||||||
* If not, it creates a new browser instance using the `BrowserFactory` class.
|
|
||||||
*
|
|
||||||
* It then navigates to the URL specified in the demand and takes a screenshot of the page.
|
|
||||||
*
|
|
||||||
* If the demand type is 'pdf' or the `alwaysMakePdf` configuration option is set to `true`, it also
|
|
||||||
* generates a PDF of the page.
|
|
||||||
*
|
|
||||||
* Finally, it saves the screenshot and PDF to the appropriate file paths and
|
|
||||||
* updates the database using the `addUpdate` method.
|
|
||||||
*
|
|
||||||
* If an `OperationTimedOut` exception is thrown, it logs the error, closes the browser,
|
|
||||||
* deletes the socket file, copies an error image to the file path, and updates the
|
|
||||||
* database with an error status.
|
|
||||||
*
|
|
||||||
* @param object|null $demande The demand object containing the URL, HMAC, file path, and type of the demand.
|
|
||||||
* @param bool $close Whether to close the browser and delete the socket file after
|
|
||||||
* generating the complete image or PDF. Defaults to `false`.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private function makeComplete(object|null $demande, bool $close = false) {
|
|
||||||
if (file_exists($this->fileSocket)) {
|
|
||||||
$socket = \file_get_contents($this->fileSocket);
|
|
||||||
try {
|
|
||||||
$browser = BrowserFactory::connectToBrowser($socket);
|
|
||||||
} catch (BrowserConnectionFailed $e) {
|
|
||||||
$browser = $this->openBrowser();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$factory = new BrowserFactory($this->chromePath);
|
|
||||||
$browser = $factory->createBrowser([
|
|
||||||
'userAgent' => 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
|
|
||||||
'keepAlive' => true,
|
|
||||||
'headless' => true,
|
|
||||||
'windowSize' => [1920, 1080],
|
|
||||||
'userDataDir' => $this->tmpDir,
|
|
||||||
'customFlags' => [
|
|
||||||
'--disable-dev-shm-usage',
|
|
||||||
'--disable-gpu'
|
|
||||||
],
|
|
||||||
'noSandbox' => true,
|
|
||||||
//'connectionDelay' => 0.8, // add 0.8 second of delay between each instruction sent to chrome,
|
|
||||||
//'debugLogger' => 'php://stdout',
|
|
||||||
]);
|
|
||||||
\file_put_contents($this->fileSocket, $browser->getSocketUri(), LOCK_EX);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($close === true) {
|
|
||||||
$socket = \file_get_contents($this->fileSocket);
|
|
||||||
$browser = BrowserFactory::connectToBrowser($socket);
|
|
||||||
$browser->close();
|
|
||||||
unlink($this->fileSocket);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$dir = $this->thumbPath . substr($demande->hmac, 0, 4) . '/';
|
|
||||||
|
|
||||||
if (!is_dir($dir)) {
|
|
||||||
mkdir($dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$page = $browser->createPage();
|
|
||||||
$page->navigate($demande->url)->waitForNavigation(Page::LOAD, 15000);
|
|
||||||
sleep(4);
|
|
||||||
|
|
||||||
$page->screenshot([
|
|
||||||
'captureBeyondViewport' => true,
|
|
||||||
'clip' => $page->getFullPageClip(),
|
|
||||||
'format' => $this->conf->fileFormat,
|
|
||||||
])->saveToFile($demande->complete);
|
|
||||||
|
|
||||||
if ($demande->type === 'pdf' || $this->conf->alwaysMakePdf === true) {
|
|
||||||
if ($this->conf->alwaysMakePdf === true) {
|
|
||||||
$pdfFile = str_replace($demande->type, 'pdf', $demande->filePath);
|
|
||||||
$pdfFile = str_replace($this->conf->fileFormat, 'pdf', $pdfFile);
|
|
||||||
} else {
|
|
||||||
$pdfFile = $demande->filePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
$page->pdf([
|
|
||||||
'printBackground' => true,
|
|
||||||
'displayHeaderFooter' => true,
|
|
||||||
'paperWidth' => 8.268,
|
|
||||||
'paperHeight' => 11.693,
|
|
||||||
'scale' => 1
|
|
||||||
])->saveToFile($pdfFile);
|
|
||||||
|
|
||||||
if ($this->conf->alwaysMakePdf === true) {
|
|
||||||
$this->db->addUpdate(1, 'pdf');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->db->addUpdate(1, 'complete');
|
|
||||||
} catch (OperationTimedOut $e) {
|
|
||||||
// todo log
|
|
||||||
$socket = \file_get_contents($this->fileSocket);
|
|
||||||
$browser = BrowserFactory::connectToBrowser($socket);
|
|
||||||
$browser->close();
|
|
||||||
unlink($this->fileSocket);
|
|
||||||
copy(__DIR__ . '/../../src/images/error_thumb.png', $demande->filePath);
|
|
||||||
$this->db->addUpdate(2, $demande->type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and opens a new browser instance.
|
|
||||||
*
|
|
||||||
* This method creates a new browser instance using the `BrowserFactory` class with
|
|
||||||
* the specified configuration options. It then saves the socket URI to a file and
|
|
||||||
* returns the browser instance.
|
|
||||||
*
|
|
||||||
* @return Browser The created browser instance.
|
|
||||||
*/
|
|
||||||
private function openBrowser(): Browser {
|
|
||||||
$factory = new BrowserFactory($this->chromePath);
|
|
||||||
|
|
||||||
// Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
|
|
||||||
$browser = $factory->createBrowser([
|
|
||||||
'userAgent' => 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
|
|
||||||
'keepAlive' => true,
|
|
||||||
'headless' => true,
|
|
||||||
'windowSize' => [1920, 1080],
|
|
||||||
'userDataDir' => $this->tmpDir,
|
|
||||||
'customFlags' => [
|
|
||||||
'--disable-dev-shm-usage',
|
|
||||||
'--disable-gpu'
|
|
||||||
],
|
|
||||||
'noSandbox' => true,
|
|
||||||
]);
|
|
||||||
|
|
||||||
\file_put_contents($this->fileSocket, $browser->getSocketUri(), LOCK_EX);
|
|
||||||
return $browser;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Utils;
|
|
||||||
|
|
||||||
use Imagick;
|
|
||||||
|
|
||||||
class ConvertIco {
|
|
||||||
|
|
||||||
static function convert($demande, $size) {
|
|
||||||
|
|
||||||
rename($demande->requestImg, $demande->requestImg . '.ico');
|
|
||||||
$icoFile = $demande->requestImg . '.ico';
|
|
||||||
|
|
||||||
if (empty(Imagick::queryFormats("ICO"))) {
|
|
||||||
throw new \Exception('Unsupported format');
|
|
||||||
}
|
|
||||||
|
|
||||||
$im = new Imagick($icoFile);
|
|
||||||
$targetWidth = $targetHeight = $size;
|
|
||||||
|
|
||||||
if ($im->getImageWidth() <> $targetWidth || $im->getImageHeight() <> $targetHeight) {
|
|
||||||
$im->cropThumbnailImage($targetWidth, $targetHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
$im->writeImage($demande->requestImg);
|
|
||||||
unlink($icoFile);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Utils;
|
|
||||||
|
|
||||||
class ConvertStatus {
|
|
||||||
static function convertToIcon($status) {
|
|
||||||
if ($status === 1) {
|
|
||||||
echo '<i class="fa fa-check gen" aria-hidden="true"></i>';
|
|
||||||
} elseif ($status === 2) {
|
|
||||||
echo '<i class="fa fa-check notGen" aria-hidden="true"></i>';
|
|
||||||
} elseif ($status === 3) {
|
|
||||||
echo '<i class="fa fa-clock-o pending" aria-hidden="true"></i>';
|
|
||||||
} else {
|
|
||||||
echo '<i class="fa fa-ban notGen" aria-hidden="true"></i>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Utils;
|
|
||||||
|
|
||||||
class ConvertToPng {
|
|
||||||
|
|
||||||
static function convertToPng($demande) {
|
|
||||||
|
|
||||||
rename($demande->requestImg, $demande->requestImg . '.tmp');
|
|
||||||
$tmpFile = $demande->requestImg . '.tmp';
|
|
||||||
|
|
||||||
|
|
||||||
if (!imagepng(imagecreatefromstring(file_get_contents($tmpFile)), $demande->requestImg)) {
|
|
||||||
}
|
|
||||||
unlink($tmpFile);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Utils;
|
|
||||||
|
|
||||||
class DeleteGen {
|
|
||||||
|
|
||||||
function deleteGen(string $hashFile) {
|
|
||||||
$dir = __DIR__ . '/../../cache/img/' . substr($hashFile, 0, 4) . '/';
|
|
||||||
if (is_dir($dir)) {
|
|
||||||
$listFile = glob($dir . '*');
|
|
||||||
foreach ($listFile as $file) {
|
|
||||||
if (is_file($file)) {
|
|
||||||
unlink($file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Utils;
|
|
||||||
|
|
||||||
class Domains {
|
|
||||||
|
|
||||||
static function getDomain($url) {
|
|
||||||
$sourceUrl = parse_url($url);
|
|
||||||
return $sourceUrl['host'];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
<?php
|
|
||||||
namespace App\Utils;
|
|
||||||
|
|
||||||
class Error {
|
|
||||||
|
|
||||||
private $errorType = [];
|
|
||||||
|
|
||||||
function index(object $error) {
|
|
||||||
http_response_code($error->status);
|
|
||||||
echo "<h1>404 Not Found</h1>";
|
|
||||||
echo "$error->message";
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Utils;
|
|
||||||
|
|
||||||
class Hmac {
|
|
||||||
private $key;
|
|
||||||
private $basePath = __DIR__ . '/../../cache/img/';
|
|
||||||
private $filePath;
|
|
||||||
private $hashPath;
|
|
||||||
|
|
||||||
public function __construct($key) {
|
|
||||||
$this->key = $key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function makeHmac($url) {
|
|
||||||
return hash_hmac('sha1', $url, $this->key);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function makeHashPath($hashUrl) {
|
|
||||||
$this->hashPath = substr($hashUrl, 0, 4) . '/';
|
|
||||||
return $this->hashPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function makeFilePath($hmac) {
|
|
||||||
$this->filePath = $this->basePath . $this->makeHashPath($hmac);
|
|
||||||
return $this->filePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function checkHmac($receiveHmac, $url) {
|
|
||||||
if ($receiveHmac === $this->makeHmac($url, $this->key)) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Utils;
|
|
||||||
|
|
||||||
class Page {
|
|
||||||
|
|
||||||
static function active($test, $attend, $class) {
|
|
||||||
if ($test === $attend) {
|
|
||||||
return $class;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static function checked($test, $attend) {
|
|
||||||
if ($test === $attend) {
|
|
||||||
return 'checked';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static function selected($test, $attend) {
|
|
||||||
if (is_array($attend)) {
|
|
||||||
if (in_array($test, $attend)) {
|
|
||||||
return 'selected';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ($test === $attend) {
|
|
||||||
return 'selected';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static function genToken() {
|
|
||||||
$token = sha1(uniqid(rand(), true) . '_' . mt_rand());
|
|
||||||
$_SESSION['token'] = $token;
|
|
||||||
return $token;
|
|
||||||
}
|
|
||||||
|
|
||||||
static function verifToken($token) {
|
|
||||||
if ($token === $_SESSION['token']) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Utils;
|
|
||||||
|
|
||||||
use Zebra_Image;
|
|
||||||
|
|
||||||
class ResizeToDemande {
|
|
||||||
|
|
||||||
static function makeDemande($demande) {
|
|
||||||
$image = new Zebra_Image();
|
|
||||||
$image->source_path = $demande->complete;
|
|
||||||
$image->target_path = $demande->filePath;
|
|
||||||
$image->preserve_time = false;
|
|
||||||
$image->enlarge_smaller_images = false;
|
|
||||||
|
|
||||||
if ($demande->type === 'full') {
|
|
||||||
$image->resize(1920, 1080, ZEBRA_IMAGE_CROP_TOPLEFT);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($demande->type === 'hd') {
|
|
||||||
$image->resize(1280, 720, ZEBRA_IMAGE_CROP_TOPLEFT);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($demande->type === 'nhd') {
|
|
||||||
$image->resize(640, 360, ZEBRA_IMAGE_CROP_TOPLEFT);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($demande->type === 'thumb') {
|
|
||||||
$image->resize(160, 90, ZEBRA_IMAGE_CROP_TOPLEFT);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Utils;
|
|
||||||
|
|
||||||
class ShowImg {
|
|
||||||
|
|
||||||
private $thumbPath = __DIR__ . '/../../cache/img/';
|
|
||||||
|
|
||||||
function __construct($type, $hmac, $fileFormat) {
|
|
||||||
|
|
||||||
$img = $this->thumbPath . substr($hmac, 0, 4) . '/' . $hmac . '_' . $type . '.'.$fileFormat;
|
|
||||||
|
|
||||||
header("Content-type: image/$fileFormat");
|
|
||||||
header('Expires: ', gmdate('D, d M Y H:i:s', time()) . ' GMT');
|
|
||||||
|
|
||||||
if (file_exists($img)) {
|
|
||||||
echo file_get_contents($img);
|
|
||||||
} else {
|
|
||||||
// todo not gen
|
|
||||||
echo file_get_contents(__DIR__ . '/../../src/images/hd_generation_in_progress.jpg');
|
|
||||||
}
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
}
|
|
2
bin/.htaccess
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Allow from none
|
||||||
|
Deny from all
|
BIN
bin/000.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
bin/404.png
Normal file
After Width: | Height: | Size: 1 KiB |
|
@ -1,7 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
FILE=/var/www/cache/tmp/chrome-php-socket
|
|
||||||
if [ ! -f "$FILE" ]; then
|
|
||||||
cd /tmp/chrome_soshot
|
|
||||||
rm -R Default
|
|
||||||
fi
|
|
14
bin/cronTask.sh
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/bash
|
||||||
|
queueDir="../cache/cronTask/"
|
||||||
|
|
||||||
|
for file in $queueDir*.hash
|
||||||
|
do
|
||||||
|
if [ -f $file ];
|
||||||
|
then
|
||||||
|
while read site hashUrl thumbSize sizeNameDir onlyThumb
|
||||||
|
do
|
||||||
|
bash thumb_server.sh "$site" "$hashUrl" "$thumbSize" "$sizeNameDir" "$onlyThumb" "0"
|
||||||
|
rm $file
|
||||||
|
done < $file
|
||||||
|
fi
|
||||||
|
done
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
BIN
bin/loadingGen.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
bin/loadingGen_thumb.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
16
bin/mon.sh
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#!/bin/bash
|
||||||
|
while [ 1 ]
|
||||||
|
do
|
||||||
|
clear
|
||||||
|
echo "#####################################################"
|
||||||
|
echo "#####################################################"
|
||||||
|
echo "#### Request thumbshot (thumb_server.sh) : " $(ps ax | grep -v grep | grep thumb_server.sh | wc -l) && # count thumb_server.sh process
|
||||||
|
echo "#### Nb of thumbshot are made now (phantomjs) : " $(ps ax | grep -v grep | grep phantomjs | wc -l) && # count phantomjs process
|
||||||
|
echo "#### Nb of test error now (curl) : " $(ps ax | grep -v grep | grep curl | wc -l) # count thumb_server.sh => curl process
|
||||||
|
echo "#### Nb of optimize operation (optipng) : " $(ps ax | grep -v grep | grep optipng | wc -l) # count thumb_server.sh => curl process
|
||||||
|
echo "#####################################################"
|
||||||
|
echo "########### PRESS CTRL+C FOR STOP MONITOR ###########"
|
||||||
|
echo "#####################################################"
|
||||||
|
|
||||||
|
sleep 3 # 3 second between two refresh
|
||||||
|
done
|
BIN
bin/phantomjs_x64
Executable file
BIN
bin/phantomjs_x86
Executable file
28
bin/rasterize.js
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
"use strict";
|
||||||
|
var page = require('webpage').create(),
|
||||||
|
system = require('system'),
|
||||||
|
address, output;
|
||||||
|
|
||||||
|
if (system.args.length < 2) {
|
||||||
|
console.log('Usage: rasterize.js URL filename [paperwidth*paperheight|paperformat] [zoom]');
|
||||||
|
console.log(' paper (pdf output) examples: "5in*7.5in", "10cm*20cm", "A4", "Letter"');
|
||||||
|
console.log(' image (png/jpg output) examples: "1920px" entire page, window width 1920px');
|
||||||
|
console.log(' "800px*600px" window, clipped to 800x600');
|
||||||
|
phantom.exit(1);
|
||||||
|
} else {
|
||||||
|
address = system.args[1];
|
||||||
|
output = system.args[2];
|
||||||
|
page.viewportSize = { width: 1280, height: 1024};
|
||||||
|
page.open(address, function (status) {
|
||||||
|
if (status !== 'success') {
|
||||||
|
console.log('Unable to load the address!');
|
||||||
|
phantom.exit(1);
|
||||||
|
} else {
|
||||||
|
window.setTimeout(function () {
|
||||||
|
page.render(output);
|
||||||
|
phantom.exit();
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
6
bin/reset.sh
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#/bin/bash
|
||||||
|
cd ../cache/tmp/
|
||||||
|
pwd
|
||||||
|
rm *.lock
|
||||||
|
rm *.png
|
||||||
|
rm *.jpg
|
4
bin/stop.sh
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/bash
|
||||||
|
kill -TERM $(ps ax | grep -v grep | grep thumb_server.sh | awk '{print $1}')
|
||||||
|
kill -TERM $(ps ax | grep -v grep | grep phantomjs | awk '{print $1}')
|
||||||
|
kill -TERM $(ps ax | grep -v grep | grep optipng | awk '{print $1}')
|
|
@ -1,16 +0,0 @@
|
||||||
<?php
|
|
||||||
namespace App\Bin;
|
|
||||||
|
|
||||||
session_start();
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
use App\Soshot\MakeThumb;
|
|
||||||
|
|
||||||
if(file_exists(__DIR__ . '/../cache/tmp/chrome-php-socket')){
|
|
||||||
echo 'Work in progress';
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
$makeThumb = new MakeThumb;
|
|
||||||
$makeThumb->compute();
|
|
195
bin/thumb_server.sh
Executable file
|
@ -0,0 +1,195 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# inspirated source http://www.cambus.net/creating-thumbnails-using-phantomjs-and-imagemagick/ for global idea
|
||||||
|
# https://gist.github.com/rsvp/1171304 for httpstatus code
|
||||||
|
# All info at http://forge.leslibres.org/projects/soshot
|
||||||
|
|
||||||
|
site=$1 # url for thumbshot
|
||||||
|
hashUrl=$2 # hash(url) is the name of final image
|
||||||
|
thumbSize=$3 # size of thumb widthxheight ex : 190x90
|
||||||
|
sizeNameDir=$4 # name of size dir
|
||||||
|
renderType=$5 # make only thumbshot / thumbshot + realSize / thumbshot + complete / thumbshot + complete + realSize
|
||||||
|
waitForResult=$6 # if true we try to make soon as possible or add to queue
|
||||||
|
noErrorLog=$7
|
||||||
|
|
||||||
|
##########################################
|
||||||
|
##### DON'T EDIT THIS PARAM USE #####
|
||||||
|
##### cache/config/serverOptions.php #####
|
||||||
|
##### for overwrite options #####
|
||||||
|
##########################################
|
||||||
|
maxThread=1 # max parralle work. For me the best is nb core - 1
|
||||||
|
timeOut=120 # default time out, after this time the site are declared in error
|
||||||
|
log=false # log all generation success and error
|
||||||
|
randomSleep=`echo $((RANDOM%40))`
|
||||||
|
optimizeTool='' # external tool form optimize png
|
||||||
|
maxQueue=50 # max process in queue
|
||||||
|
currentProcess=$(ps ax | grep -v grep | grep thumb_server.sh | wc -l)
|
||||||
|
firstLevel=${hashUrl:0:2}
|
||||||
|
secondLevel=${hashUrl:2:2}
|
||||||
|
startPath=$sizeNameDir/$firstLevel/$secondLevel/
|
||||||
|
getArch=$(getconf LONG_BIT)
|
||||||
|
#echo $getArch
|
||||||
|
|
||||||
|
if [ -f "../cache/config/serverOptions.php" ]
|
||||||
|
then
|
||||||
|
source "../cache/config/serverOptions.php"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $currentProcess -gt $maxQueue ]
|
||||||
|
then
|
||||||
|
rm "../cache/tmp/$hashUrl.lock"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$site" = "manual" ]
|
||||||
|
then
|
||||||
|
site=$(cat "../cache/tmp/manual.txt")
|
||||||
|
echo '' > "../cache/tmp/manual.txt"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "../cache/img/$startPath"
|
||||||
|
|
||||||
|
if [ ! $waitForResult ]
|
||||||
|
then
|
||||||
|
sleep $randomSleep
|
||||||
|
while [[ `ps -ax | grep -v grep | grep phantomjs | wc -l` -ge $maxThread ]]
|
||||||
|
do
|
||||||
|
sleep $randomSleep
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
start_time=`date +%s`
|
||||||
|
if [ $getArch -eq 64 ]
|
||||||
|
then
|
||||||
|
timeout $timeOut nice -n 5 ./phantomjs_x64 --disk-cache=false --local-storage-path=../cache/tmp --ignore-ssl-errors=true --web-security=false rasterize.js "$site" "../cache/tmp/$hashUrl.png"
|
||||||
|
exitStatus=$?
|
||||||
|
else
|
||||||
|
timeout $timeOut nice -n 5 ./phantomjs_x86 --disk-cache=false --local-storage-path=../cache/tmp --ignore-ssl-errors=true --web-security=false rasterize.js "$site" "../cache/tmp/$hashUrl.png"
|
||||||
|
exitStatus=$?
|
||||||
|
fi
|
||||||
|
|
||||||
|
#echo $exitStatus
|
||||||
|
|
||||||
|
if [ $exitStatus -eq 124 ]
|
||||||
|
then
|
||||||
|
echo 0
|
||||||
|
cp "000.png" "../cache/img/$startPath""$hashUrl""_thumb.png" && cp "000.png" "../cache/img/$startPath""$hashUrl.png" && cp "000.png" "../cache/img/$startPath""$hashUrl""_complete.png"
|
||||||
|
rm "../cache/tmp/$hashUrl.lock"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "../cache/tmp/$hashUrl.png" ]]
|
||||||
|
then
|
||||||
|
echo 0
|
||||||
|
errorCode=`echo $(curl -k -L --write-out %{http_code} --silent -S --connect-timeout $timeOut \--no-keepalive --output /dev/null $site)`
|
||||||
|
if [ $site == 'manual' ]
|
||||||
|
then
|
||||||
|
errorCode='manual'
|
||||||
|
fi
|
||||||
|
#echo $errorCode
|
||||||
|
case $errorCode in
|
||||||
|
000) cp "000.png" "../cache/img/$startPath""$hashUrl""_thumb.png" && cp "000.png" "../cache/img/$startPath""$hashUrl.png" && cp "000.png" "../cache/img/$startPath""$hashUrl""_complete.png";;
|
||||||
|
200) cp "error.png" "../cache/img/$startPath""$hashUrl""_thumb.png" && cp "error.png" "../cache/img/$startPath""$hashUrl.png" && cp "error.png" "../cache/img/$startPath""$hashUrl""_complete.png";;
|
||||||
|
404) cp "404.png" "../cache/img/$startPath""$hashUrl""_thumb.png" && cp "404.png" "../cache/img/$startPath""$hashUrl.png" && cp "404.png" "../cache/img/$startPath""$hashUrl""_complete.png";;
|
||||||
|
manual) rm "../cache/tmp/$hashUrl.lock" && exit;;
|
||||||
|
*) cp "error.png" "../cache/img/$startPath""$hashUrl""_thumb.png" && cp "error.png" "../cache/img/$startPath""$hashUrl.png" && cp "error.png" "../cache/img/$startPath""$hashUrl""_complete.png";;
|
||||||
|
esac
|
||||||
|
rm "../cache/tmp/$hashUrl.lock"
|
||||||
|
if $log == true
|
||||||
|
then
|
||||||
|
end_time=`date +%s`
|
||||||
|
logDate=`date +'[%a %d %b %Y] [%H:%M:%S]'`
|
||||||
|
if [ $noErrorLog == "noErrorLog" ]
|
||||||
|
then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
if [ $errorCode == 200 ]
|
||||||
|
then
|
||||||
|
echo "none --- "$site" --- "$hashUrl" --- "$thumbSize" --- "$sizeNameDir" --- "$onlyThumb" --- true --- "$errorCode > "../cache/logs/retry/"$hashUrl".log"
|
||||||
|
else
|
||||||
|
echo "none --- "$site" --- "$hashUrl" --- "$thumbSize" --- "$sizeNameDir" --- "$onlyThumb" --- true --- "$errorCode > "../cache/logs/other/"$hashUrl".log"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
case $renderType in
|
||||||
|
# thumbnail only
|
||||||
|
t)
|
||||||
|
nice -n 5 convert "../cache/tmp/$hashUrl.png" -crop 1280x1024+0+0 -filter Lanczos -thumbnail "$thumbSize" "../cache/tmp/$hashUrl""_thumb.png"
|
||||||
|
if [ $optimizeTool ]
|
||||||
|
then
|
||||||
|
eval nice -n 5 $optimizeTool "../cache/tmp/$hashUrl""_thumb.png" &>/dev/null
|
||||||
|
fi
|
||||||
|
mv "../cache/tmp/$hashUrl""_thumb.png" "../cache/img/$startPath""$hashUrl""_thumb.png"
|
||||||
|
if [[ -f "../cache/img/$startPath""$hashUrl""_thumb.png" ]]
|
||||||
|
then
|
||||||
|
echo 1
|
||||||
|
else
|
||||||
|
echo 0
|
||||||
|
fi
|
||||||
|
rm "../cache/tmp/$hashUrl.png"
|
||||||
|
rm "../cache/tmp/$hashUrl.lock"
|
||||||
|
;;
|
||||||
|
# thumbnail + complete
|
||||||
|
tc)
|
||||||
|
nice -n 5 convert "../cache/tmp/$hashUrl.png" -crop 1280x1024+0+0 -filter Lanczos -thumbnail "$thumbSize" "../cache/tmp/$hashUrl""_thumb.png"
|
||||||
|
if [ $optimizeTool ]
|
||||||
|
then
|
||||||
|
nice -n 5 eval $optimizeTool "../cache/tmp/$hashUrl""_thumb.png" "../cache/tmp/$hashUrl.png" &>/dev/null
|
||||||
|
fi
|
||||||
|
mv "../cache/tmp/$hashUrl.png" "../cache/img/$startPath""$hashUrl""_complete.png"
|
||||||
|
mv "../cache/tmp/$hashUrl""_thumb.png" "../cache/img/$startPath""$hashUrl""_thumb.png"
|
||||||
|
if [[ -f "../cache/img/$startPath""$hashUrl""_thumb.png" && -f "../cache/img/$startPath""$hashUrl""_complete.png" ]]
|
||||||
|
then
|
||||||
|
echo 1
|
||||||
|
else
|
||||||
|
echo 0
|
||||||
|
fi
|
||||||
|
rm "../cache/tmp/$hashUrl.lock"
|
||||||
|
;;
|
||||||
|
# thumbnail + realsize
|
||||||
|
tr)
|
||||||
|
nice -n 5 convert "../cache/tmp/$hashUrl.png" -crop 1280x1024+0+0 "../cache/tmp/$hashUrl.png"
|
||||||
|
nice -n 5 convert "../cache/tmp/$hashUrl.png" -filter Lanczos -thumbnail "$thumbSize" "../cache/tmp/$hashUrl""_thumb.png"
|
||||||
|
if [ $optimizeTool ]
|
||||||
|
then
|
||||||
|
eval nice -n 5 $optimizeTool "../cache/tmp/$hashUrl""_thumb.png" "../cache/tmp/$hashUrl.png" &>/dev/null
|
||||||
|
fi
|
||||||
|
mv "../cache/tmp/$hashUrl.png" "../cache/img/$startPath""$hashUrl.png"
|
||||||
|
mv "../cache/tmp/$hashUrl""_thumb.png" "../cache/img/$startPath""$hashUrl""_thumb.png"
|
||||||
|
if [[ -f "../cache/img/$startPath""$hashUrl""_thumb.png" && -f "../cache/img/$startPath""$hashUrl.png" ]]
|
||||||
|
then
|
||||||
|
echo 1
|
||||||
|
else
|
||||||
|
echo 0
|
||||||
|
fi
|
||||||
|
rm "../cache/tmp/$hashUrl.lock"
|
||||||
|
;;
|
||||||
|
# thumbnail + realsize + complete
|
||||||
|
trc)
|
||||||
|
cp "../cache/tmp/$hashUrl.png" "../cache/tmp/$hashUrl""_complete.png"
|
||||||
|
nice -n 5 convert "../cache/tmp/$hashUrl.png" -crop 1280x1024+0+0 "../cache/tmp/$hashUrl.png"
|
||||||
|
nice -n 5 convert "../cache/tmp/$hashUrl.png" -filter Lanczos -thumbnail "$thumbSize" "../cache/tmp/$hashUrl""_thumb.png"
|
||||||
|
if [ $optimizeTool ]
|
||||||
|
then
|
||||||
|
eval nice -n 5 $optimizeTool "../cache/tmp/$hashUrl""_thumb.png" "../cache/tmp/$hashUrl.png" "../cache/tmp/$hashUrl""_complete.png" &>/dev/null
|
||||||
|
fi
|
||||||
|
mv "../cache/tmp/$hashUrl.png" "../cache/img/$startPath""$hashUrl.png"
|
||||||
|
mv "../cache/tmp/$hashUrl""_thumb.png" "../cache/img/$startPath""$hashUrl""_thumb.png"
|
||||||
|
mv "../cache/tmp/$hashUrl""_complete.png" "../cache/img/$startPath""$hashUrl""_complete.png"
|
||||||
|
if [[ -f "../cache/img/$startPath""$hashUrl""_thumb.png" && -f "../cache/img/$startPath""$hashUrl.png" && -f "../cache/img/$startPath""$hashUrl""_complete.png" ]]
|
||||||
|
then
|
||||||
|
echo 1
|
||||||
|
else
|
||||||
|
echo 0
|
||||||
|
fi
|
||||||
|
rm "../cache/tmp/$hashUrl.lock"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if $log
|
||||||
|
then
|
||||||
|
end_time=`date +%s`
|
||||||
|
logDate=`date +'[%a %d %b %Y] [%H:%M:%S]'`
|
||||||
|
echo $logDate `expr $end_time - $start_time`s >> '../cache/logs/success.txt'
|
||||||
|
fi
|
0
cache/queue/.gitkeep → cache/index.html
vendored
0
cache/tmp/.gitkeep
vendored
|
@ -1,14 +0,0 @@
|
||||||
{
|
|
||||||
"require": {
|
|
||||||
"embed/embed": "^4.4.8",
|
|
||||||
"hassankhan/config": "^3.1",
|
|
||||||
"chrome-php/chrome": "^1.9",
|
|
||||||
"stefangabos/zebra_image": "^2.8.2",
|
|
||||||
"guzzlehttp/psr7": "^2.5"
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"App\\": "app/"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
{
|
|
||||||
"key": "",
|
|
||||||
"onlyLocalServer": true,
|
|
||||||
"webPage": false,
|
|
||||||
"log": true,
|
|
||||||
"alwaysMakePdf": false,
|
|
||||||
"permitType": [],
|
|
||||||
"expireCache": 12,
|
|
||||||
"maxGenPerBatch": 5,
|
|
||||||
"icoSize": 48,
|
|
||||||
"chromePath" : "",
|
|
||||||
"fileFormat" : "jpeg"
|
|
||||||
}
|
|
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 99 KiB |
2
inc/.htaccess
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Allow from none
|
||||||
|
Deny from all
|
311
inc/admin.php
Normal file
|
@ -0,0 +1,311 @@
|
||||||
|
<?php
|
||||||
|
$acceptParam['log'] = array(
|
||||||
|
'suspect',
|
||||||
|
'success',
|
||||||
|
'other',
|
||||||
|
'retry'
|
||||||
|
);
|
||||||
|
if (isset($ui['pwd'])) {
|
||||||
|
checkAdmin($ui['pwd']);
|
||||||
|
}
|
||||||
|
if (isset($ui['log']) && !in_array($ui['log'], $acceptParam['log']) || $_SESSION['login'] !== true) {
|
||||||
|
die('Tell me, Mr Anderson, what good is a phone call if you\'re unable to speak ?');
|
||||||
|
}
|
||||||
|
if (empty($ui['log']) && empty($ui['ac'])) {
|
||||||
|
$ui['log'] = 'success';
|
||||||
|
}
|
||||||
|
function clearLog($log) {
|
||||||
|
if (file_exists('cache/logs/'.$log.'.txt') && is_file('cache/logs/'.$log.'.txt')) {
|
||||||
|
file_put_contents('cache/logs/'.$log.'.txt', '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseSuccessLog() {
|
||||||
|
if (file_exists('cache/logs/success.txt')) {
|
||||||
|
$file = fopen('cache/logs/success.txt', "r");
|
||||||
|
$res = '';
|
||||||
|
if (!empty($file)) {
|
||||||
|
while (!feof($file)) {
|
||||||
|
$currentLine = trim(fgets($file));
|
||||||
|
$currentLine = explode(' ', $currentLine);
|
||||||
|
$currentLine = str_replace('s', '', $currentLine);
|
||||||
|
if (!empty($currentLine[5])) {
|
||||||
|
$res['genTime'][] = $currentLine[5];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$res['genTime'] = array();
|
||||||
|
}
|
||||||
|
fclose($file);
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseFailLog($log) {
|
||||||
|
if (empty($log) || ($log !== 'suspect' && $log !== 'retry' && $log !== 'other')) {
|
||||||
|
die('Are you sure about this.');
|
||||||
|
}
|
||||||
|
$res = '';
|
||||||
|
$list = glob('cache/logs/'.$log.'/*.log');
|
||||||
|
if (!empty($list)) {
|
||||||
|
foreach ($list as $value) {
|
||||||
|
$line = file_get_contents($value);
|
||||||
|
$line = trim($line);
|
||||||
|
$line = explode(' --- ', $line);
|
||||||
|
if (!empty($line[7])) {
|
||||||
|
$res[] = array(
|
||||||
|
$line[1],
|
||||||
|
$line[2],
|
||||||
|
$line[4],
|
||||||
|
'Error '.$line[7].' - '
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$res[] = array(
|
||||||
|
$line[1],
|
||||||
|
$line[2],
|
||||||
|
$line[4],
|
||||||
|
''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
function manualGen($hash, $log) {
|
||||||
|
$line = file_get_contents('cache/logs/'.$log.'/'.$hash.'.log');
|
||||||
|
$line = trim($line);
|
||||||
|
$line = explode(' --- ', $line);
|
||||||
|
$hash = sha1($GLOBALS['config']['salt'].rawurldecode($line[1]));
|
||||||
|
file_put_contents('cache/tmp/manual.txt', $line[1]);
|
||||||
|
chdir('bin/');
|
||||||
|
exec('bash thumb_server.sh manual '.escapeshellarg($hash).' '.escapeshellarg($line[3]).' '.escapeshellarg($line[4]).' trc 1', $result);
|
||||||
|
chdir('../');
|
||||||
|
if ((int)$result[0] == 1) {
|
||||||
|
$res['success'] = 1;
|
||||||
|
$res['filePath'] = pathForFile($line[4], $hash).'.png';
|
||||||
|
$res['base64'] = 'data:image/png;base64,'.base64_encode(file_get_contents($res['filePath']));
|
||||||
|
} else {
|
||||||
|
$res['error'] = 1;
|
||||||
|
$res['msg'] = 'Can\'t generate thumbshot manualy, try curl method.';
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
function delAndRegen($hash, $size) {
|
||||||
|
$path = pathForFile($size, $hash);
|
||||||
|
if (file_exists($path.'.png')) {
|
||||||
|
unlink($path.'.png');
|
||||||
|
}
|
||||||
|
if (file_exists($path.'_thumb.png')) {
|
||||||
|
unlink($path.'_thumb.png');
|
||||||
|
}
|
||||||
|
if (file_exists($path.'_complete.png')) {
|
||||||
|
unlink($path.'_complete.png');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function tryRootDomain($hash, $log) {
|
||||||
|
$line = file_get_contents('cache/logs/'.$log.'/'.$hash.'.log');
|
||||||
|
$line = trim($line);
|
||||||
|
$line = explode(' --- ', $line);
|
||||||
|
$hash = sha1($GLOBALS['config']['salt'].rawurldecode($line[1]));
|
||||||
|
$parts = parse_url($line[1]);
|
||||||
|
$url = $parts['scheme'].'://'.trim($parts['host']);
|
||||||
|
file_put_contents('cache/tmp/manual.txt', $url);
|
||||||
|
chdir('bin/');
|
||||||
|
exec('bash thumb_server.sh manual '.escapeshellarg($hash).' '.escapeshellarg($line[3]).' '.escapeshellarg($line[4]).' trc 1', $result);
|
||||||
|
chdir('../');
|
||||||
|
if ((int)$result[0] === 1) {
|
||||||
|
$res['success'] = 1;
|
||||||
|
$res['filePath'] = pathForFile($line[4], $hash).'.png';
|
||||||
|
$res['base64'] = 'data:image/png;base64,'.base64_encode(file_get_contents($res['filePath']));
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function keepThisThumb($hash, $log) {
|
||||||
|
unlink('cache/logs/'.$log.'/'.$hash.'.log');
|
||||||
|
}
|
||||||
|
|
||||||
|
function tryWithCurl($hash, $log) {
|
||||||
|
$line = file_get_contents('cache/logs/'.$log.'/'.$hash.'.log');
|
||||||
|
$line = trim($line);
|
||||||
|
$line = explode(' --- ', $line);
|
||||||
|
//$hash = sha1($GLOBALS['config']['salt'].rawurldecode($line[1]));
|
||||||
|
$ch = curl_init();
|
||||||
|
curl_setopt($ch, CURLOPT_URL, $line[1]);
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||||
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||||
|
curl_setopt($ch, CURLOPT_USERAGENT, 'SoShot - perSOnal thumbSHOTer');
|
||||||
|
$resultat = curl_exec($ch);
|
||||||
|
curl_close($ch);
|
||||||
|
$searchStr = array(
|
||||||
|
'href="//',
|
||||||
|
'src="//',
|
||||||
|
'content="//'
|
||||||
|
);
|
||||||
|
$replaceStr = array(
|
||||||
|
'href="http://',
|
||||||
|
'src="http://',
|
||||||
|
'content="http://'
|
||||||
|
);
|
||||||
|
$resultat = str_replace($searchStr, $replaceStr, $resultat);
|
||||||
|
file_put_contents('cache/tmp/'.$line[2].'.html', $resultat);
|
||||||
|
chdir('bin/');
|
||||||
|
exec('bash thumb_server.sh ../cache/tmp/'.$hash.'.html '.escapeshellarg($line[2]).' '.escapeshellarg($line[3]).' '.escapeshellarg($line[4]).' trc 1 noErrorLog', $result);
|
||||||
|
chdir('../');
|
||||||
|
unlink('cache/tmp/'.$hash.'.html');
|
||||||
|
if ((int)$result[0] == 1) {
|
||||||
|
$res['success'] = 1;
|
||||||
|
$res['filePath'] = pathForFile($line[4], $hash).'.png';
|
||||||
|
$res['base64'] = 'data:image/png;base64,'.base64_encode(file_get_contents($res['filePath']));
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($ui['clear']) && (int)$ui['clear'] === 1) {
|
||||||
|
clearLog($ui['log']);
|
||||||
|
}
|
||||||
|
if (isset($ui['ac']) && $ui['ac'] === 'delete' && isset($ui['thumb']) && !empty($ui['thumb'])) {
|
||||||
|
$imgUrl = pathForFile('m', $ui['thumb']);
|
||||||
|
if (file_exists($_SERVER['DOCUMENT_ROOT'].'/'.$imgUrl.'.png')) {
|
||||||
|
unlink($_SERVER['DOCUMENT_ROOT'].'/'.$imgUrl.'.png');
|
||||||
|
}
|
||||||
|
if (file_exists($imgUrl.'_thumb.png')) {
|
||||||
|
unlink($_SERVER['DOCUMENT_ROOT'].'/'.$imgUrl.'_thumb.png');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo '<div class="hMenu">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="?p=admin&log=success">Success</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="?p=admin&log=suspect">Suspect</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="?p=admin&log=retry">Retry</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="?p=admin&log=other">Other error</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="?p=admin&ac=delete">Delete thumbshot</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="?logout=1">Logout</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div id="log">';
|
||||||
|
if (isset($ui['ac']) && $ui['ac'] === 'delete') {
|
||||||
|
if ($ui['delThumb']) {
|
||||||
|
delAndRegen($ui['delThumb'], $size);
|
||||||
|
}
|
||||||
|
if (isset($ui['deleteUrl']) && testValidUrl($ui['deleteUrl']) !== true) {
|
||||||
|
unset($ui['deleteUrl']);
|
||||||
|
echo '<div>Not a valid url.</div>';
|
||||||
|
}
|
||||||
|
echo '
|
||||||
|
<form method="post" action="?">
|
||||||
|
<p>
|
||||||
|
<label>Url </label>';
|
||||||
|
if (empty($ui['deleteUrl'])) {
|
||||||
|
echo '<input type="text" name="deleteUrl"/>';
|
||||||
|
} else {
|
||||||
|
echo '<input type="text" name="deleteUrl" value="', $ui['deleteUrl'], '"/>';
|
||||||
|
}
|
||||||
|
echo '</p>
|
||||||
|
<p>
|
||||||
|
<input type="hidden" name="p" value="admin"/>
|
||||||
|
<input type="hidden" name="ac" value="delete"/>
|
||||||
|
<input type="submit"/>
|
||||||
|
</p>
|
||||||
|
</form>';
|
||||||
|
if (!empty($ui['deleteUrl'])) {
|
||||||
|
$ui['deleteUrl'] = trim(rawurldecode($ui['deleteUrl']));
|
||||||
|
$ui['deleteUrl'] = rtrim($ui['deleteUrl'], '/');
|
||||||
|
$hashUrl = sha1($GLOBALS['config']['salt'].$ui['deleteUrl']);
|
||||||
|
$imgUrl = pathForFile('', $hashUrl);
|
||||||
|
echo '</div>
|
||||||
|
<div id="result">
|
||||||
|
<p>
|
||||||
|
<a href="', $imgUrl, '.png"><img src="', $imgUrl, '_thumb.png"/></a>
|
||||||
|
</p>
|
||||||
|
<a href="?p=admin&ac=delete&delThumb=', $hashUrl, '">Delete this thumb</a>
|
||||||
|
</div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($ui['log']) && $ui['log'] === 'success') {
|
||||||
|
$logs = parseSuccessLog();
|
||||||
|
if (!empty($logs)) {
|
||||||
|
$nbThumb = 0;
|
||||||
|
$nbThumb = count($logs['genTime']);
|
||||||
|
echo 'Total request : ', $nbThumb, '</br>';
|
||||||
|
echo 'Moyenne per request : ', round(array_sum($logs['genTime']) / $nbThumb, 2), 's (min (', min($logs['genTime']), 's) max (', max($logs['genTime']), 's))</br>';
|
||||||
|
} else {
|
||||||
|
echo 'No result';
|
||||||
|
}
|
||||||
|
echo '<p class="clear" ><a href="?p=admin&log=success&clear=1">Clear success log</a></p>';
|
||||||
|
}
|
||||||
|
if (isset($ui['log']) && ($ui['log'] === 'suspect' || $ui['log'] === 'retry' || $ui['log'] === 'other')) {
|
||||||
|
if (isset($ui['hash']) && !empty($ui['hash'])) {
|
||||||
|
//$ui['hash'] = validHash($ui['hash']);
|
||||||
|
if (isset($ui['root']) && (int)$ui['root'] === 1) {
|
||||||
|
$response = tryRootDomain($ui['hash'], $ui['log']);
|
||||||
|
}
|
||||||
|
if (isset($ui['cache']) && (int)$ui['cache'] === 1) {
|
||||||
|
$response['success'] = 1;
|
||||||
|
$response['filePath'] = pathForFile($ui['s'], $ui['hash']).'.png';
|
||||||
|
$response['base64'] = 'data:image/png;base64,'.base64_encode(file_get_contents($response['filePath']));
|
||||||
|
if (!file_exists($response['filePath'])) {
|
||||||
|
$response['base64'] = 'data:image/png;base64,'.base64_encode(file_get_contents('bin/error.png'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($ui['keep']) && (int)$ui['keep'] === 1) {
|
||||||
|
keepThisThumb($ui['hash'], $ui['log']);
|
||||||
|
}
|
||||||
|
if (isset($ui['mGen']) && (int)$ui['mGen'] === 1) {
|
||||||
|
$response = manualGen($ui['hash'], $ui['log']);
|
||||||
|
}
|
||||||
|
if (isset($ui['tryCurl']) && (int)$ui['tryCurl'] === 1) {
|
||||||
|
$response = tryWithCurl($ui['hash'], $ui['log']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$logs = parseFailLog($ui['log']);
|
||||||
|
if (!empty($logs)) {
|
||||||
|
echo '<ul>';
|
||||||
|
foreach ($logs as $value) {
|
||||||
|
echo '<li>', htmlentities(strip_tags($value['3'])), htmlentities(strip_tags($value['0'])), '</br><a href="?p=admin&log=', $ui['log'], '&hash=', $value['1'], '&mGen=1#result">manuel launch</a> <a href="', htmlentities(strip_tags($value['0'])), '">view site</a> <a href="?p=admin&log=', $ui['log'], '&hash=', $value['1'], '&cache=1&s=', $value['2'], '#result">view image in cache</a></li>';
|
||||||
|
}
|
||||||
|
echo '</ul>';
|
||||||
|
} else {
|
||||||
|
echo 'No result';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo '</div>';
|
||||||
|
if (!empty($response) && $response['success'] === 1) {
|
||||||
|
echo '<div id="result">';
|
||||||
|
echo '<img src="', $response['base64'], '" style="width:100%;"/>';
|
||||||
|
echo '<p><input type="text" value="http://', $_SERVER['SERVER_NAME'], '/', $response['filePath'], '" onclick="this.select()"/></p>';
|
||||||
|
echo '<a href="?p=admin&log=', $ui['log'], '&hash=', $value['1'], '&mGen=1">Manuel launch</a> / ';
|
||||||
|
if (extension_loaded("curl")) {
|
||||||
|
echo '<a href="?p=admin&log=', $ui['log'], '&hash=', $value['1'], '&tryCurl=1">Try with curl</a> / ';
|
||||||
|
}
|
||||||
|
echo '<a href="?p=admin&log=', $ui['log'], '&hash=', $ui['hash'], '&root=1">Try with root domain</a> / ';
|
||||||
|
echo '<a href="?p=admin&log=', $ui['log'], '&hash=', $ui['hash'], '&keep=1">Keep this thumbshot</a>';
|
||||||
|
echo '</div>';
|
||||||
|
}
|
||||||
|
if (!empty($response) && $response['error'] === 1) {
|
||||||
|
echo '<div id="result">';
|
||||||
|
echo '<p>', $response['msg'], '</p>';
|
||||||
|
echo '<a href="?p=admin&log=', $ui['log'], '&hash=', $value['1'], '&mGen=1">Manuel launch</a> / ';
|
||||||
|
if (extension_loaded("curl")) {
|
||||||
|
echo '<a href="?p=admin&log=', $ui['log'], '&hash=', $value['1'], '&tryCurl=1">Try with curl</a> / ';
|
||||||
|
}
|
||||||
|
echo '<a href="?p=admin&log=', $ui['log'], '&hash=', $ui['hash'], '&root=1">Try with root domain</a> / ';
|
||||||
|
echo '<a href="?p=admin&log=', $ui['log'], '&hash=', $ui['hash'], '&keep=1">Keep this thumbshot</a>';
|
||||||
|
echo '</div>';
|
||||||
|
}
|
||||||
|
?>
|
44
inc/index.php
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<form method="post">
|
||||||
|
<p>
|
||||||
|
<input type="url" placeholder="<?php echo $defUrl; ?>" value="<?php echo $defUrl; ?>" name="url"/>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label>Size</label>
|
||||||
|
<select name="s">
|
||||||
|
<?php
|
||||||
|
foreach ($GLOBALS['config']['thumbSize'] as $key => $value) {
|
||||||
|
if ($value === $width) {
|
||||||
|
echo '<option value="', $key, '" selected="selected">', $value, '</option>';
|
||||||
|
} else {
|
||||||
|
echo '<option value="', $key, '">', $value, '</option>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label>Force refresh</label>
|
||||||
|
<input type="checkbox" value="1" name="fr" />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<input type="hidden" name="token" value="<?php echo genToken(); ?>" />
|
||||||
|
<input type="submit" value="Generate"/>
|
||||||
|
</p>
|
||||||
|
<p class="info">
|
||||||
|
<a href="http://forge.leslibres.org/projects/soshot">Homepage</a> <a href="http://knah-tsaeb.org/contact-page/">Contact</a>
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
if (!empty($success)) {
|
||||||
|
echo '<div id="result">';
|
||||||
|
echo '<h3>This image will be removed in ', $GLOBALS['config']['expireCache'], 'h</h3>';
|
||||||
|
echo '<img src="data:image/png;base64,',base64_encode(file_get_contents($success['thumb'])), '"/>';
|
||||||
|
echo '<p><label>Thumbshot</label><input type="text" value="http://', $_SERVER['SERVER_NAME'], '/', $success['thumb'], '" onclick="this.select()"/>';
|
||||||
|
if ($GLOBALS['config']['activeFullSize'] === true) {
|
||||||
|
echo '<p><label>1280x1024</label><input type="text" value="http://', $_SERVER['SERVER_NAME'], '/', $success['normal'], '" onclick="this.select()"/></p>';
|
||||||
|
}
|
||||||
|
if ($GLOBALS['config']['activeComplete'] === true) {
|
||||||
|
echo '<p><label>Complete</label><input type="text" value="http://', $_SERVER['SERVER_NAME'], '/', $success['complete'], '" onclick="this.select()"/></p>';
|
||||||
|
}
|
||||||
|
echo '</div>';
|
||||||
|
}
|
32
inc/install.php
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
if(file_exists('cache/config/genConf.php') && $GLOBALS['config']['pwd'] !== 'install'){
|
||||||
|
die ('Seriously Dude, Where\'s My Car ?');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isset($ui['passOne'])){
|
||||||
|
savePass($ui['passOne'], $ui['passTwo'], $ui['token']);
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<div class="message">
|
||||||
|
This is the key for generate thumbnail whith GET method. Save it !
|
||||||
|
<p class="alert">
|
||||||
|
<?php
|
||||||
|
echo $serverKey;
|
||||||
|
?>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<form action="?" method="post">
|
||||||
|
<p>
|
||||||
|
<label>Password</label>
|
||||||
|
<input type="password" name="passOne" />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label>Confirm</label>
|
||||||
|
<input type="password" name="passTwo" />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<input type="hidden" name="token" value="<?php echo genToken();?>"/>
|
||||||
|
<input type="hidden" name="p" value="install"/>
|
||||||
|
<input type="submit">
|
||||||
|
</p>
|
||||||
|
</form>
|
11
inc/login.php
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<form action="?" method="post">
|
||||||
|
<p>
|
||||||
|
<label>Password</label>
|
||||||
|
<input type="password" name="pwd" />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<input type="hidden" name="token" value="<?php echo genToken();?>"/>
|
||||||
|
<input type="hidden" name="p" value="admin" />
|
||||||
|
<input type="submit">
|
||||||
|
</p>
|
||||||
|
</form>
|
675
index.php
Normal file
|
@ -0,0 +1,675 @@
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
if (empty($_SESSION['login'])) {
|
||||||
|
$_SESSION['login'] = false;
|
||||||
|
}
|
||||||
|
// change if you want no inpact
|
||||||
|
date_default_timezone_set('Europe/Paris');
|
||||||
|
// soshot only accept request by 127.0.0.1
|
||||||
|
$GLOBALS['config']['onlyLocalServer'] = false;
|
||||||
|
// No form for post url only acces by GET method
|
||||||
|
$GLOBALS['config']['NoWebPage'] = false;
|
||||||
|
// After 3 critical error ban user
|
||||||
|
$GLOBALS['config']['maxErrorBeforeBan'] = 3;
|
||||||
|
// Ban for 60 minutes
|
||||||
|
$GLOBALS['config']['banTime'] = 60;
|
||||||
|
// default url for form
|
||||||
|
$GLOBALS['config']['defaultUrl'] = 'https://duckduckgo.com/';
|
||||||
|
// default size for thumbnail
|
||||||
|
$GLOBALS['config']['defaultThumbSize'] = '120x90';
|
||||||
|
// list of available size for thumb
|
||||||
|
$GLOBALS['config']['thumbSize'] = array(
|
||||||
|
's' => '120x90',
|
||||||
|
'm' => '200x160',
|
||||||
|
'l' => '300x240',
|
||||||
|
'xl' => '400x320',
|
||||||
|
'xxl' => '500x400'
|
||||||
|
);
|
||||||
|
// create thumshot 1280x1024
|
||||||
|
$GLOBALS['config']['activeFullSize'] = false;
|
||||||
|
// create thumbshot of complete page
|
||||||
|
$GLOBALS['config']['activeComplete'] = false;
|
||||||
|
// Remove image older than 12 hours
|
||||||
|
$GLOBALS['config']['expireCache'] = 12;
|
||||||
|
// Disable exec command and use cron task
|
||||||
|
$GLOBALS['config']['disableExec'] = false;
|
||||||
|
// Enable log for success, suspect, error
|
||||||
|
$GLOBALS['config']['log'] = true;
|
||||||
|
if (file_exists('cache/config/options.php')) {
|
||||||
|
require 'cache/config/options.php';
|
||||||
|
}
|
||||||
|
if (get_magic_quotes_gpc()) {
|
||||||
|
function stripslashes_deep($value) {
|
||||||
|
$value = is_array($value) ? array_map('stripslashes_deep', $value) : stripslashes($value);
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
$_POST = array_map('stripslashes_deep', $_POST);
|
||||||
|
$_GET = array_map('stripslashes_deep', $_GET);
|
||||||
|
$_COOKIE = array_map('stripslashes_deep', $_COOKIE);
|
||||||
|
}
|
||||||
|
if (!empty($_POST)) {
|
||||||
|
$ui = $_POST;
|
||||||
|
$ui['request'] = 'form';
|
||||||
|
$ui['iw'] = 1;
|
||||||
|
unset($_POST);
|
||||||
|
}
|
||||||
|
if (!empty($_GET)) {
|
||||||
|
$ui = $_GET;
|
||||||
|
$ui['request'] = 'api';
|
||||||
|
unset($_GET);
|
||||||
|
}
|
||||||
|
if (empty($ui['request'])) {
|
||||||
|
$ui['request'] = '';
|
||||||
|
}
|
||||||
|
if (empty($ui['p'])) {
|
||||||
|
$ui['p'] = 'index';
|
||||||
|
}
|
||||||
|
if (empty($ui['fr'])) {
|
||||||
|
$ui['fr'] = '';
|
||||||
|
}
|
||||||
|
if (empty($ui['t'])) {
|
||||||
|
$ui['t'] = 't';
|
||||||
|
}
|
||||||
|
if (isset($ui['logout']) && (int)$ui['logout'] === 1) {
|
||||||
|
session_destroy();
|
||||||
|
header("Location:?");
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
if (!file_exists('cache/config/genConf.php')) {
|
||||||
|
$serverKey = install();
|
||||||
|
$ui['p'] = 'install';
|
||||||
|
}
|
||||||
|
require 'cache/config/genConf.php';
|
||||||
|
if ($GLOBALS['config']['pwd'] === 'install' && $ui['p'] !== 'install') {
|
||||||
|
reloadInstall();
|
||||||
|
header("Location:?");
|
||||||
|
}
|
||||||
|
if (($GLOBALS['config']['onlyLocalServer'] === true && $_SERVER['REMOTE_ADDR'] !== '127.0.0.1') || checkIfBan() === true) {
|
||||||
|
header("HTTP/1.0 404 Not Found");
|
||||||
|
echo "<h1>404 Not Found</h1>";
|
||||||
|
echo "The page that you have requested could not be found.";
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
if ($GLOBALS['config']['NoWebPage'] === true && empty($_GET)) {
|
||||||
|
header("HTTP/1.0 404 Not Found");
|
||||||
|
echo "<h1>404 Not Found</h1>";
|
||||||
|
echo "The page that you have requested could not be found.";
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
function testExistImg($file) {
|
||||||
|
if ($GLOBALS['config']['activeFullSize'] && $GLOBALS['config']['activeComplete']) {
|
||||||
|
if (file_exists($file.'_thumb.png') && file_exists($file.'.png') && file_exists($file.'_complete.png')) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} elseif ($GLOBALS['config']['activeFullSize']) {
|
||||||
|
if (file_exists($file.'_thumb.png') && file_exists($file.'.png')) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} elseif ($GLOBALS['config']['activeComplete']) {
|
||||||
|
if (file_exists($file.'_thumb.png') && file_exists($file.'_complete.png')) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (file_exists($file.'_thumb.png')) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the bash script for generate thumbnail
|
||||||
|
*
|
||||||
|
* @author Knah Tsaeb
|
||||||
|
* @date 2013-02-12
|
||||||
|
* @param $url (string) url for thumbshot
|
||||||
|
* @param $hashUrl (hash) hash($url)
|
||||||
|
* @param $width (string) size of thumbnail 190x90
|
||||||
|
* @param $onlyThumb (bool)
|
||||||
|
* @param $waitForResult (bool)
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
function launchScript($url, $hashUrl, $width, $size, $waitForResult = false) {
|
||||||
|
$oriHash = $hashUrl;
|
||||||
|
$hashUrl = escapeshellarg($hashUrl);
|
||||||
|
$url = escapeshellarg($url);
|
||||||
|
$width = escapeshellarg($width);
|
||||||
|
if ($GLOBALS['config']['activeFullSize'] && $GLOBALS['config']['activeComplete']) {
|
||||||
|
$renderType = 'trc';
|
||||||
|
} elseif ($GLOBALS['config']['activeFullSize']) {
|
||||||
|
$renderType = 'tr';
|
||||||
|
} elseif ($GLOBALS['config']['activeComplete']) {
|
||||||
|
$renderType = 'tc';
|
||||||
|
} else {
|
||||||
|
$renderType = 't';
|
||||||
|
}
|
||||||
|
if ($GLOBALS['config']['disableExec'] === false) {
|
||||||
|
if (!file_exists('cache/tmp/'.$oriHash.'.lock')) {
|
||||||
|
touch('cache/tmp/'.$oriHash.'.lock');
|
||||||
|
chdir('bin/');
|
||||||
|
if ($waitForResult === false) {
|
||||||
|
exec('bash thumb_server.sh '.$url.' '.$hashUrl.' '.$width.' '.$size.' '.$renderType.' > /dev/null &', $result);
|
||||||
|
} else {
|
||||||
|
exec('bash thumb_server.sh '.$url.' '.$hashUrl.' '.$width.' '.$size.' '.$renderType.' 1', $result);
|
||||||
|
}
|
||||||
|
chdir('../');
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
makeQueueFile($url, $hashUrl, $width, $size, $renderType);
|
||||||
|
$result = 0;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeQueueFile($url, $hashUrl, $width, $size, $renderType) {
|
||||||
|
$url = str_replace('\'', '', $url);
|
||||||
|
$hashUrl = str_replace('\'', '', $hashUrl);
|
||||||
|
$width = str_replace('\'', '', $width);
|
||||||
|
if (!file_exists('cache/cronTask/'.$hashUrl.'.hash')) {
|
||||||
|
$data = $url.' '.$hashUrl.' '.$width.' '.$size.' '.$renderType."\n";
|
||||||
|
file_put_contents('cache/cronTask/'.$hashUrl.'.hash', $data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function testValidUrl($url) {
|
||||||
|
$url = trim($url);
|
||||||
|
if (filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED)) {
|
||||||
|
$url = parse_url($url);
|
||||||
|
if (!in_array($url['scheme'], array(
|
||||||
|
'http',
|
||||||
|
'https'
|
||||||
|
))) {
|
||||||
|
return array('msg' => 'Url must be start by http or https.');
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return array('msg' => 'Not a valid url.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function genToken() {
|
||||||
|
$token = sha1(uniqid(rand(), true).'_'.mt_rand());
|
||||||
|
$_SESSION['token'] = $token;
|
||||||
|
$_SESSION['tokenTime'] = time();
|
||||||
|
return $token;
|
||||||
|
}
|
||||||
|
|
||||||
|
function verifToken($token) {
|
||||||
|
if ($token !== $_SESSION['token'] || $_SESSION['tokenTime'] <= time() - 24000) {
|
||||||
|
ban();
|
||||||
|
die('So Long, and Thanks for All the Fish.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkIfBan() {
|
||||||
|
require 'cache/logs/banUser.php';
|
||||||
|
$userIp = $_SERVER['REMOTE_ADDR'];
|
||||||
|
if (isset($banList[$userIp]) && $banList[$userIp]['nbBan'] >= $GLOBALS['config']['maxErrorBeforeBan'] && $banList[$userIp]['lastBan'] + $GLOBALS['config']['banTime'] > time()) {
|
||||||
|
return true;
|
||||||
|
} elseif (isset($banList[$userIp]) && $banList[$userIp]['lastBan'] + $GLOBALS['config']['banTime'] < time()) {
|
||||||
|
unban();
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ban() {
|
||||||
|
require 'cache/logs/banUser.php';
|
||||||
|
$userIp = $_SERVER['REMOTE_ADDR'];
|
||||||
|
if (isset($banList[$userIp])) {
|
||||||
|
$banList[$userIp]['lastBan'] = time();
|
||||||
|
$banList[$userIp]['nbBan']++;
|
||||||
|
} else {
|
||||||
|
$banList[$userIp]['lastBan'] = time();
|
||||||
|
$banList[$userIp]['nbBan'] = 1;
|
||||||
|
}
|
||||||
|
file_put_contents('cache/logs/banUser.php', "<?php\n\$banList=".var_export($banList, true).";\n?>");
|
||||||
|
}
|
||||||
|
|
||||||
|
function unBan() {
|
||||||
|
require 'cache/logs/banUser.php';
|
||||||
|
$userIp = $_SERVER['REMOTE_ADDR'];
|
||||||
|
unset($banList[$userIp]);
|
||||||
|
file_put_contents('cache/logs/banUser.php', "<?php\n\$banList=".var_export($banList, true).";\n?>");
|
||||||
|
}
|
||||||
|
|
||||||
|
function install() {
|
||||||
|
if (!is_writable('cache')) {
|
||||||
|
die('Make dir "cache" writable');
|
||||||
|
}
|
||||||
|
if (!is_dir('cache/config') && !mkdir('cache/config', 0705)) {
|
||||||
|
die('Error on create dir "cache/config".');
|
||||||
|
}
|
||||||
|
if (!is_dir('cache/img') && !mkdir('cache/img', 0705)) {
|
||||||
|
die('Error on create dir "cache/img".');
|
||||||
|
}
|
||||||
|
if (!is_dir('cache/logs') && !mkdir('cache/logs', 0705)) {
|
||||||
|
die('Error on create dir "cache/logs".');
|
||||||
|
}
|
||||||
|
if (!is_dir('cache/logs/suspect') && !mkdir('cache/logs/suspect', 0705)) {
|
||||||
|
die('Error on create dir "cache/logs/suspect".');
|
||||||
|
}
|
||||||
|
if (!is_dir('cache/logs/retry') && !mkdir('cache/logs/retry', 0705)) {
|
||||||
|
die('Error on create dir "cache/logs/retry".');
|
||||||
|
}
|
||||||
|
if (!is_dir('cache/logs/other') && !mkdir('cache/logs/other', 0705)) {
|
||||||
|
die('Error on create dir "cache/logs/other".');
|
||||||
|
}
|
||||||
|
if (!is_dir('cache/tmp') && !mkdir('cache/tmp', 0705)) {
|
||||||
|
die('Error on create dir "cache/tmp".');
|
||||||
|
}
|
||||||
|
if (!is_dir('cache/cronTask') && !mkdir('cache/cronTask', 0705)) {
|
||||||
|
die('Error on create dir "cache/cronTask".');
|
||||||
|
}
|
||||||
|
$salt = sha1(uniqid(rand(), true).'_'.mt_rand());
|
||||||
|
$serverKey = substr(sha1(uniqid(rand(), true).'_'.mt_rand().$salt), 0, 12);
|
||||||
|
$encryptServerKey = sha1($serverKey.$salt);
|
||||||
|
if (!is_file('cache/config/genConf.php')) {
|
||||||
|
file_put_contents('cache/config/genConf.php', "
|
||||||
|
<?php
|
||||||
|
\$GLOBALS['config']['serverKey'] = '$encryptServerKey';
|
||||||
|
\$GLOBALS['config']['salt'] = '$salt';
|
||||||
|
\$GLOBALS['config']['pwd'] = 'install';
|
||||||
|
\$GLOBALS['config']['apikey'] = '$serverKey';
|
||||||
|
?>");
|
||||||
|
}
|
||||||
|
if (!is_file('cache/config/serverOptions.php')) {
|
||||||
|
touch('cache/config/serverOptions.php');
|
||||||
|
}
|
||||||
|
if (!is_file('cache/index.html')) {
|
||||||
|
touch('cache/index.html');
|
||||||
|
}
|
||||||
|
if (!is_file('cache/config/options.php')) {
|
||||||
|
file_put_contents('cache/config/options.php', "<?php\n\n?>");
|
||||||
|
}
|
||||||
|
if (!is_file('cache/logs/banUser.php')) {
|
||||||
|
file_put_contents('cache/logs/banUser.php', "<?php\n\n?>");
|
||||||
|
}
|
||||||
|
$GLOBALS['config']['serverKey'] = $encryptServerKey;
|
||||||
|
$GLOBALS['config']['salt'] = $salt;
|
||||||
|
$GLOBALS['config']['pwd'] = 'install';
|
||||||
|
$GLOBALS['config']['apikey'] = $serverKey;
|
||||||
|
return $serverKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkInstall() {
|
||||||
|
if (!is_file('.htaccess')) {
|
||||||
|
file_put_contents('.htaccess', "AddDefaultCharset UTF-8\nOptions -Indexes\nDirectoryIndex index.php index.html\nFileETag none\nSetOutputFilter DEFLATE\n");
|
||||||
|
}
|
||||||
|
if (!is_file('cache/logs/.htaccess')) {
|
||||||
|
file_put_contents('cache/logs/.htaccess', "Allow from none\nDeny from all\n");
|
||||||
|
}
|
||||||
|
if (!is_file('cache/config/.htaccess')) {
|
||||||
|
file_put_contents('cache/config/.htaccess', "Allow from none\nDeny from all\n");
|
||||||
|
}
|
||||||
|
if (!is_file('cache/cronTask/.htaccess')) {
|
||||||
|
file_put_contents('cache/config/.htaccess', "Allow from none\nDeny from all\n");
|
||||||
|
}
|
||||||
|
if (!is_file('bin/.htaccess')) {
|
||||||
|
file_put_contents('bin/.htaccess', "Allow from none\nDeny from all\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeOlderThan($dir = 'cache/img/shortLive') {
|
||||||
|
if (is_dir($dir)) {
|
||||||
|
$objects = scandir($dir);
|
||||||
|
foreach ($objects as $object) {
|
||||||
|
if ($object !== '.' && $object !== '..' && $object) {
|
||||||
|
if (filetype($dir.'/'.$object) === 'dir') {
|
||||||
|
removeOlderThan($dir.'/'.$object);
|
||||||
|
} else {
|
||||||
|
if (fileatime($dir.'/'.$object) < time() - 3600 * $GLOBALS['config']['expireCache']) {
|
||||||
|
unlink($dir.'/'.$object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reset($objects);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pathForFile($size, $hashUrl) {
|
||||||
|
$startPath = substr($hashUrl, 0, 2).'/'.substr($hashUrl, 2, 2).'/';
|
||||||
|
if (empty($size)) {
|
||||||
|
$size = tryDetectSize($startPath.$hashUrl);
|
||||||
|
}
|
||||||
|
$file = 'cache/img/'.$size.'/'.$startPath.$hashUrl;
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
function tryDetectSize($file) {
|
||||||
|
if (is_file('cache/img/s/'.$file.'_thumb.png')) {
|
||||||
|
return 's';
|
||||||
|
}
|
||||||
|
if (is_file('cache/img/m/'.$file.'_thumb.png')) {
|
||||||
|
return 'm';
|
||||||
|
}
|
||||||
|
if (is_file('cache/img/l/'.$file.'_thumb.png')) {
|
||||||
|
return 'l';
|
||||||
|
}
|
||||||
|
if (is_file('cache/img/xl/'.$file.'_thumb.png')) {
|
||||||
|
return 'xl';
|
||||||
|
}
|
||||||
|
if (is_file('cache/img/xxl/'.$file.'_thumb.png')) {
|
||||||
|
return 'xxl';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validHash($hash) {
|
||||||
|
if (empty($hash)) {
|
||||||
|
die('You talking to me');
|
||||||
|
}
|
||||||
|
if (!preg_match('/^[0-9a-f]{40}$/i', $hash)) {
|
||||||
|
die('I don\'t understand biiip bip bip biiiip bip bip bip biiiiiiip biip ...');
|
||||||
|
}
|
||||||
|
return $hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkAdmin($pwd) {
|
||||||
|
$pwd = sha1($GLOBALS['config']['salt'].$pwd.$GLOBALS['config']['serverKey']);
|
||||||
|
if (validHash($pwd) !== $GLOBALS['config']['pwd']) {
|
||||||
|
ban();
|
||||||
|
die('1, 2, 3, 4, 5 ? That\'s amazing ! I\'ve got the same combination on my luggage !');
|
||||||
|
}
|
||||||
|
$_SESSION['login'] = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function savePass($passOne, $passTwo, $token) {
|
||||||
|
verifToken($token);
|
||||||
|
if ($passOne !== $passTwo || empty($passOne) || empty($passTwo)) {
|
||||||
|
reloadInstall();
|
||||||
|
} else {
|
||||||
|
$GLOBALS['config']['pwd'] = sha1($GLOBALS['config']['salt'].$passOne.$GLOBALS['config']['serverKey']);
|
||||||
|
$confServerKey = $GLOBALS['config']['serverKey'];
|
||||||
|
$confSalt = $GLOBALS['config']['salt'];
|
||||||
|
$confPwd = $GLOBALS['config']['pwd'];
|
||||||
|
$apikey = $GLOBALS['config']['apikey'];
|
||||||
|
$confFile = '
|
||||||
|
<?php
|
||||||
|
$GLOBALS[\'config\'][\'serverKey\'] = \''.$confServerKey.'\';
|
||||||
|
$GLOBALS[\'config\'][\'salt\'] = \''.$confSalt.'\';
|
||||||
|
$GLOBALS[\'config\'][\'pwd\'] = \''.$confPwd.'\';
|
||||||
|
$GLOBALS[\'config\'][\'apikey\'] = \''.$apikey.'\';
|
||||||
|
?>';
|
||||||
|
file_put_contents('cache/config/genConf.php', $confFile);
|
||||||
|
}
|
||||||
|
header("Location:?");
|
||||||
|
}
|
||||||
|
|
||||||
|
function reloadInstall() {
|
||||||
|
array_map('unlink', glob("cache/config/*"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Améliore la sortie print
|
||||||
|
*
|
||||||
|
* @author Tatane http://www.tatane.info/index.php/print_rn
|
||||||
|
* @author http://www.blog.cactuscrew.com/77-print_rn.html
|
||||||
|
* @param $data (array) tableau ou variable à examiner
|
||||||
|
* @param $name (string) nom a afficher
|
||||||
|
* @return false affiche les clef valeur du tableau $data
|
||||||
|
* @example n_print($array, 'Tableau de valeur');
|
||||||
|
*/
|
||||||
|
function n_print($data, $name = '') {
|
||||||
|
$aBackTrace = debug_backtrace();
|
||||||
|
echo '<h2>', $name, '</h2>';
|
||||||
|
echo '<fieldset style="border: 1px solid orange; padding: 5px;color: #333; background-color: #fff;">';
|
||||||
|
echo '<legend style="border:1px solid orange;padding: 1px;background-color:#eee;color:orange;">
|
||||||
|
', basename($aBackTrace[0]['file']), ' ligne => ', $aBackTrace[0]['line'], '
|
||||||
|
</legend>';
|
||||||
|
echo '<pre>', htmlentities(print_r($data, 1)), '</pre>';
|
||||||
|
echo '
|
||||||
|
</fieldset>
|
||||||
|
<br />
|
||||||
|
';
|
||||||
|
}
|
||||||
|
|
||||||
|
function printThumbShot($file, $renderType) {
|
||||||
|
ob_end_clean();
|
||||||
|
header("Content-type: image/png");
|
||||||
|
header('Expires: ', gmdate('D, d M Y H:i:s', time()).' GMT');
|
||||||
|
switch ($renderType) {
|
||||||
|
case 'c' :
|
||||||
|
echo file_get_contents($file.'_complete.png');
|
||||||
|
break;
|
||||||
|
case 'r' :
|
||||||
|
echo file_get_contents($file.'.png');
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
echo file_get_contents($file.'_thumb.png');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPage($page) {
|
||||||
|
$page = htmlspecialchars($page);
|
||||||
|
switch ($page) {
|
||||||
|
case 'login' :
|
||||||
|
return 'inc/login.php';
|
||||||
|
break;
|
||||||
|
case 'install' :
|
||||||
|
return 'inc/install.php';
|
||||||
|
break;
|
||||||
|
case 'admin' :
|
||||||
|
return 'inc/admin.php';
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
return 'inc/index.php';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function testIfImg($url) {
|
||||||
|
$ext = strtolower(pathinfo($url, PATHINFO_EXTENSION));
|
||||||
|
if ($ext === 'jpg' || $ext === 'jpeg' || $ext === 'png' || $ext === 'gif') {
|
||||||
|
return $ext;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeImgThumb($url, $ext, $hashUrl, $width, $path, $renderType) {
|
||||||
|
if (!function_exists('imagecreatefromjpeg')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$image = file_get_contents($url);
|
||||||
|
$fullSize = file_put_contents('cache/tmp/'.$hashUrl.'.'.$ext, $image);
|
||||||
|
if ($ext === 'jpg' || $ext === 'jpeg') {
|
||||||
|
$tmpImg = imagecreatefromjpeg('cache/tmp/'.$hashUrl.'.'.$ext);
|
||||||
|
}
|
||||||
|
if ($ext === 'png') {
|
||||||
|
$tmpImg = imagecreatefrompng('cache/tmp/'.$hashUrl.'.'.$ext);
|
||||||
|
}
|
||||||
|
if ($ext === 'gif') {
|
||||||
|
$tmpImg = imagecreatefromgif('cache/tmp/'.$hashUrl.'.'.$ext);
|
||||||
|
}
|
||||||
|
if (!$tmpImg) {
|
||||||
|
unlink('cache/tmp/'.$hashUrl.'.'.$ext);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$w = imagesx($tmpImg);
|
||||||
|
$h = imagesy($tmpImg);
|
||||||
|
$ystart = 0;
|
||||||
|
$yheight = $h;
|
||||||
|
if ($h > $w) { $ystart = ($h / 2) - ($w / 2);
|
||||||
|
$yheight = $w / 2;
|
||||||
|
}
|
||||||
|
$nh = min(floor(($h * $width) / $w), $width);
|
||||||
|
$im2 = imagecreatetruecolor($width, $nh);
|
||||||
|
imagecopyresampled($im2, $tmpImg, 0, 0, 0, $ystart, $width, $nh, $w, $yheight);
|
||||||
|
$tempname = 'cache/tmp/'.$hashUrl.'_TEMP.png';
|
||||||
|
imagepng($im2, $tempname, 9);
|
||||||
|
if (!is_dir($path)) {
|
||||||
|
mkdir($path, 0775, true);
|
||||||
|
}
|
||||||
|
imagedestroy($tmpImg);
|
||||||
|
imagedestroy($im2);
|
||||||
|
unlink('cache/tmp/'.$hashUrl.'.'.$ext);
|
||||||
|
rename($tempname, $path.$hashUrl.'_thumb.png');
|
||||||
|
if (file_exists($path.$hashUrl.'_thumb.png')) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkHmac($receiveHmac, $url){
|
||||||
|
if($receiveHmac === makeHmac($url, $GLOBALS['config']['apikey'])){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeHmac($url){
|
||||||
|
return hash_hmac('sha1',$url, $GLOBALS['config']['apikey']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
$image = file_get_contents('http://www.url.com/image.jpg');
|
||||||
|
file_put_contents('/images/image.jpg', $image); //save the image on your server
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
checkInstall();
|
||||||
|
removeOlderThan();
|
||||||
|
if (empty($defUrl)) {
|
||||||
|
$defUrl = $GLOBALS['config']['defaultUrl'];
|
||||||
|
}
|
||||||
|
if (isset($ui['s']) && array_key_exists($ui['s'], $GLOBALS['config']['thumbSize'])) {
|
||||||
|
$width = $GLOBALS['config']['thumbSize'][$ui['s']];
|
||||||
|
} else {
|
||||||
|
$width = $GLOBALS['config']['defaultThumbSize'];
|
||||||
|
}
|
||||||
|
// Generate or return img
|
||||||
|
if (!empty($ui['request']) && $ui['p'] !== 'install' && $ui['p'] !== 'login' && $ui['p'] !== 'admin') {
|
||||||
|
if (empty($ui['url'])) {
|
||||||
|
die('You see in this world there\'s two kinds of people, my friend. Those with loaded guns, and those who dig. You dig.');
|
||||||
|
}
|
||||||
|
$ui['sendUrl'] = $ui['url'];
|
||||||
|
$ui['url'] = trim(rawurldecode($ui['url']));
|
||||||
|
$ui['url'] = rtrim($ui['url'], '/');
|
||||||
|
$hashUrl = sha1($GLOBALS['config']['salt'].$ui['url']);
|
||||||
|
$startPath = substr($hashUrl, 0, 2).'/'.substr($hashUrl, 2, 2).'/';
|
||||||
|
$file = 'cache/img/'.$ui['s'].'/'.$startPath.$hashUrl;
|
||||||
|
$testUrl = testValidUrl($ui['url']);
|
||||||
|
$defUrl = $ui['url'];
|
||||||
|
if ($ui['request'] === 'form') {
|
||||||
|
$file = 'cache/img/shortLive/'.$startPath.$hashUrl;
|
||||||
|
$file = 'cache/img/shortLive/'.$startPath.$hashUrl;
|
||||||
|
}
|
||||||
|
if (testExistImg($file) === true && (int)$ui['fr'] !== 1) {
|
||||||
|
if ($ui['request'] === 'api') {
|
||||||
|
if (checkHmac($ui['hm'], $ui['sendUrl'])){
|
||||||
|
printThumbShot($file, $ui['t']);
|
||||||
|
} else {
|
||||||
|
ban();
|
||||||
|
die('I take a chips and give it to Godzilla. I give high kick in Chuck Norris face and I go to ... Humm .... Ehh .... Arg ....... KAMOULOX ! Well done Jean Pierre.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($ui['request'] === 'form') {
|
||||||
|
$success = array(
|
||||||
|
'normal' => $file.'.png',
|
||||||
|
'thumb' => $file.'_thumb.png',
|
||||||
|
'complete' => $file.'_complete.png'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($ui['request'] === 'api') {
|
||||||
|
if (empty($ui['hm']) || empty($ui['hm'])) {
|
||||||
|
die('Are you Ken ?');
|
||||||
|
}
|
||||||
|
if (!checkHmac($ui['hm'], $ui['sendUrl'])) {
|
||||||
|
ban();
|
||||||
|
die('I take a chips and give it to Godzilla. I give high kick in Chuck Norris face and I go to ... Humm .... Ehh .... Arg ....... KAMOULOX ! Well done Jean Pierre.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
verifToken($ui['token']);
|
||||||
|
}
|
||||||
|
if ($testUrl !== true) {
|
||||||
|
if (!file_exists('cache/logs/'.$hashUrl.'log')) {
|
||||||
|
file_put_contents('cache/logs/suspect/'.$hashUrl.'.log', $_SERVER['REMOTE_ADDR'].' --- '.$ui['url'].' --- '.$hashUrl.' --- '.$width.' --- '.$ui['s'].' --- '.$renderType.' --- true'."\n");
|
||||||
|
}
|
||||||
|
if ($ui['request'] === 'api') {
|
||||||
|
printThumbShot('bin/error', $ui['t']);
|
||||||
|
} else {
|
||||||
|
$success = array(
|
||||||
|
'normal' => 'bin/error.png',
|
||||||
|
'thumb' => 'bin/error_thumb.png',
|
||||||
|
'complete' => 'bin/error.png'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$ext = testIfImg($ui['url']);
|
||||||
|
if ($ext !== false) {
|
||||||
|
$genWidth = explode("x", $width);
|
||||||
|
if ($ui['request'] === 'api') {
|
||||||
|
$makeImg = makeImgThumb($ui['url'], $ext, $hashUrl, $genWidth[0], 'cache/img/'.$ui['s'].'/'.$startPath, $ui['t']);
|
||||||
|
} else {
|
||||||
|
$makeImg = makeImgThumb($ui['url'], $ext, $hashUrl, $genWidth[0], 'cache/img/shortLive/'.$startPath, $ui['t']);
|
||||||
|
}
|
||||||
|
if ($makeImg === true) {
|
||||||
|
$GLOBALS['config']['disableExec'] = true;
|
||||||
|
if ($ui['request'] === 'api') {
|
||||||
|
printThumbShot($file, $ui['t']);
|
||||||
|
} else {
|
||||||
|
$success = array(
|
||||||
|
'normal' => $file.'.png',
|
||||||
|
'thumb' => $file.'_thumb.png',
|
||||||
|
'complete' => $file.'_complete.png'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((isset($ui['iw']) && (int)$ui['iw'] === 1 && $ui['request'] === 'api')) {
|
||||||
|
$res = launchScript($defUrl, $hashUrl, $width, $ui['s'], true);
|
||||||
|
} elseif (isset($ui['iw']) && (int)$ui['iw'] === 1 && $ui['request'] === 'form') {
|
||||||
|
$res = launchScript($defUrl, $hashUrl, $width, 'shortLive', true);
|
||||||
|
} else {
|
||||||
|
$res = launchScript($defUrl, $hashUrl, $width, $ui['s'], false);
|
||||||
|
}
|
||||||
|
if ($ui['request'] === 'api') {
|
||||||
|
$file = 'bin/loadingGen';
|
||||||
|
printThumbShot($file, $ui['t']);
|
||||||
|
} else {
|
||||||
|
if ($GLOBALS['config']['disableExec'] === true) {
|
||||||
|
$file = 'bin/loadingGen';
|
||||||
|
}
|
||||||
|
$success = array(
|
||||||
|
'normal' => $file.'.png',
|
||||||
|
'thumb' => $file.'_thumb.png',
|
||||||
|
'complete' => $file.'_complete.png'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>SoShot</title>
|
||||||
|
<meta name="description" content="Personal webshot">
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<?php
|
||||||
|
require getPage($ui['p']);
|
||||||
|
?>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,12 +0,0 @@
|
||||||
AddDefaultCharset UTF-8
|
|
||||||
Options -Indexes
|
|
||||||
DirectoryIndex index.php index.html
|
|
||||||
FileETag none
|
|
||||||
SetOutputFilter DEFLATE
|
|
||||||
|
|
||||||
|
|
||||||
RewriteEngine On
|
|
||||||
|
|
||||||
RewriteCond %{REQUEST_FILENAME} !-f
|
|
||||||
RewriteCond %{REQUEST_FILENAME} !-d
|
|
||||||
RewriteRule ^(.*)$ index.php [QSA,L]
|
|
12
public/assets/css/fork-awesome.min.css
vendored
|
@ -1,248 +0,0 @@
|
||||||
:root {
|
|
||||||
color-scheme: dark light;
|
|
||||||
|
|
||||||
--primary: #cc2027;
|
|
||||||
--primary-darken: #8E161B;
|
|
||||||
--primary-lighten: #D64C52;
|
|
||||||
--primary-text-contrast: #FFF;
|
|
||||||
|
|
||||||
--secondary: #20ccc5;
|
|
||||||
--secondary-darken: #168E89;
|
|
||||||
--secondary-lighten: #4CD6D0;
|
|
||||||
--secondary-text-contrast: #FFF;
|
|
||||||
|
|
||||||
--error: #c43933;
|
|
||||||
--error-darken: #892723;
|
|
||||||
--error-lighten: #CF605B;
|
|
||||||
--error-text-contrast: #FFF;
|
|
||||||
|
|
||||||
--info: #206ccc;
|
|
||||||
--info-darken: #164B8E;
|
|
||||||
--info-lighten: #4C89D6;
|
|
||||||
--info-text-contrast: #FFF;
|
|
||||||
|
|
||||||
--success: #7dcc20;
|
|
||||||
--success-darken: #578E16;
|
|
||||||
--success-lighten: #97D64C;
|
|
||||||
--success-text-contrast: #000;
|
|
||||||
|
|
||||||
--warning: #cc5e20;
|
|
||||||
--warning-darken: #8E4116;
|
|
||||||
--warning-lighten: #D67E4C;
|
|
||||||
--warning-text-contrast: #FFF;
|
|
||||||
|
|
||||||
--background-color: light-dark(#fffbfb, #171414);
|
|
||||||
--background-color-darken: light-dark(#B2AFAF, #100E0E);
|
|
||||||
--background-color-lighten: light-dark(#FFFBFB, #454343);
|
|
||||||
|
|
||||||
--header-background-color: light-dark(#171414, #fffbfb);
|
|
||||||
--header-background-color-darken: light-dark(#100E0E, #B2AFAF);
|
|
||||||
--header-background-color-lighten: light-dark(#454343, #FFFBFB);
|
|
||||||
|
|
||||||
--header-text-color: light-dark(#fffbfb, #171414);
|
|
||||||
--header-text-color-secondary: #ffffffb3;
|
|
||||||
--header-text-color-disable: light-dark(#ffffff80, #454343);
|
|
||||||
|
|
||||||
--text-color: light-dark(#171414, #fffbfb);
|
|
||||||
--text-color-secondary: #ffffffb3;
|
|
||||||
--text-color-disable: light-dark(#454343, #ffffff80);
|
|
||||||
|
|
||||||
--text-color-inverse: light-dark(#fffbfb, #171414);
|
|
||||||
--text-color-secondary-inverse: #ffffffb3;
|
|
||||||
--text-color-disable-inverse: light-dark(#ffffff80, #454343);
|
|
||||||
|
|
||||||
--h1-color: var(--primary);
|
|
||||||
--h2-color: #c33d35;
|
|
||||||
--h3-color: #b94f44;
|
|
||||||
--h4-color: #ae5e52;
|
|
||||||
--h5-color: #a16a61;
|
|
||||||
--h6-color: #927671;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="light"] {
|
|
||||||
--background-color: #fffbfb;
|
|
||||||
--text-color: #171414;
|
|
||||||
--text-color-inverse: #fffbfb;
|
|
||||||
.title:hover {
|
|
||||||
color: var(--text-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="dark"] {
|
|
||||||
table {
|
|
||||||
color: var(--text-color);
|
|
||||||
}
|
|
||||||
.title:hover {
|
|
||||||
color: var(--text-color-inverse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
|
||||||
font-family: arial, sans-serif;
|
|
||||||
font-weight: bold;
|
|
||||||
line-height: 2em;
|
|
||||||
background-color: var(--background-color);
|
|
||||||
overflow: auto;
|
|
||||||
color: var(--text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
html,
|
|
||||||
body,
|
|
||||||
h1,
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6 {
|
|
||||||
font-family: "Roboto", sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
color: var(--primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.fa {
|
|
||||||
/*color: var(--primary);*/
|
|
||||||
}
|
|
||||||
|
|
||||||
.w3-sidebar {
|
|
||||||
z-index: 3;
|
|
||||||
width: 250px;
|
|
||||||
height: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: var(--primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
text-decoration: none;
|
|
||||||
color: var(--primary-darken)
|
|
||||||
}
|
|
||||||
|
|
||||||
a:visited {
|
|
||||||
color: var(--primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.centerBlock {
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.homeForm {
|
|
||||||
width: 49.9%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.w3-bar {
|
|
||||||
background-color: var(--background-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#mySidebar {
|
|
||||||
top: 84px;
|
|
||||||
background-color: var(--header-background-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
#mySidebar>:hover {
|
|
||||||
text-decoration: none;
|
|
||||||
color: var(--primary-darken);
|
|
||||||
}
|
|
||||||
|
|
||||||
.w3-bar-block .w3-bar-item {
|
|
||||||
padding: 4px 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.w3-bar {
|
|
||||||
background-color: var(--header-background-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.w3-bar-item-selected {
|
|
||||||
background-color: var(--secondary);
|
|
||||||
color: var(--secondary-text-contrast);
|
|
||||||
}
|
|
||||||
|
|
||||||
#myFooter {
|
|
||||||
position: fixed;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.w3-main {
|
|
||||||
margin: 64px auto 46px 270px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.soshot-main {
|
|
||||||
padding-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
form label {
|
|
||||||
width: 48% !important;
|
|
||||||
display: inline-block;
|
|
||||||
text-align: right;
|
|
||||||
margin-right: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.w3-input,
|
|
||||||
.w3-select {
|
|
||||||
display: inline-block;
|
|
||||||
width: 48%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.w3-input {
|
|
||||||
background-color: var(--primary-lighten);
|
|
||||||
color: var(--text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
button,
|
|
||||||
.w3-button {
|
|
||||||
background-color: var(--primary) !important;
|
|
||||||
color: var(--text-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:hover,
|
|
||||||
.w3-button:hover {
|
|
||||||
background-color: var(--primary-darken) !important;
|
|
||||||
color: var(--text-color-inverse) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.zoom {
|
|
||||||
cursor: zoom-in;
|
|
||||||
}
|
|
||||||
|
|
||||||
.delete,
|
|
||||||
.notGen {
|
|
||||||
color: var(--error);
|
|
||||||
}
|
|
||||||
|
|
||||||
.gen {
|
|
||||||
color: var(--success);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pending {
|
|
||||||
color: var(--warning);
|
|
||||||
}
|
|
||||||
|
|
||||||
#myFooter {
|
|
||||||
background-color: var(--header-background-color);
|
|
||||||
color: var(--header-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
#myFooter a:hover {
|
|
||||||
color: var(--primary-darken);
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
color: var(--text-color-inverse);
|
|
||||||
padding: .5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width:768px) {
|
|
||||||
|
|
||||||
#mySidebar {
|
|
||||||
background-color: var(--header-background-color) !important;
|
|
||||||
width: 100%;
|
|
||||||
height: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Before Width: | Height: | Size: 547 KiB |
Before Width: | Height: | Size: 331 KiB |
|
@ -1,68 +0,0 @@
|
||||||
<?php
|
|
||||||
require_once '../vendor/autoload.php';
|
|
||||||
|
|
||||||
ini_set('display_errors', '1');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Améliore la sortie print
|
|
||||||
*
|
|
||||||
* @author Tatane http://www.tatane.info/index.php/print_rn
|
|
||||||
* @author http://www.blog.cactuscrew.com/77-print_rn.html
|
|
||||||
* @param $data (array) tableau ou variable à examiner
|
|
||||||
* @param $name (string) nom a afficher
|
|
||||||
* @return false affiche les clef valeur du tableau $data
|
|
||||||
* @example n_print($array, 'Tableau de valeur');
|
|
||||||
*/
|
|
||||||
function n_print($data, $name = '') {
|
|
||||||
$aBackTrace = debug_backtrace();
|
|
||||||
echo '<h2>', $name, '</h2>';
|
|
||||||
echo '<fieldset style="border: 1px solid orange; padding: 5px;color: #333; background-color: #fff;">';
|
|
||||||
echo '<legend style="border:1px solid orange;padding: 1px;background-color:#eee;color:orange;">
|
|
||||||
', basename($aBackTrace[0]['file']), ' ligne => ', $aBackTrace[0]['line'], '
|
|
||||||
</legend>';
|
|
||||||
echo '<pre>', htmlentities(print_r($data, 1)), '</pre>';
|
|
||||||
echo '
|
|
||||||
</fieldset>
|
|
||||||
<br />
|
|
||||||
';
|
|
||||||
}
|
|
||||||
|
|
||||||
use App\Router;
|
|
||||||
use App\Utils\Error;
|
|
||||||
use Noodlehaus\Config;
|
|
||||||
|
|
||||||
$router = new Router();
|
|
||||||
|
|
||||||
$router->addRoute(['/', '/index.php', '/index'], 'App\Controllers\Home', 'GET');
|
|
||||||
$router->addRoute('/api', 'App\Controllers\Result', 'GET');
|
|
||||||
$router->addRoute('/hmac', 'App\Controllers\GenHmac', 'GET');
|
|
||||||
$router->addRoute('/debug', 'App\Bin\ThumbShoter', 'GET');
|
|
||||||
$router->addRoute('/backend', 'App\Controllers\Backend', 'GET');
|
|
||||||
$router->addRoute('/logout', 'App\Controllers\Logout', 'GET');
|
|
||||||
|
|
||||||
$conf = (object)Config::load([__DIR__ . '/../datas/config.default.json', '?' . __DIR__ . '/../datas/config.json'])->all();
|
|
||||||
|
|
||||||
if (!file_exists(__DIR__ . '/../datas/config.json')) {
|
|
||||||
session_start();
|
|
||||||
$conf->webPage = true;
|
|
||||||
$_SESSION['login'] = 1;
|
|
||||||
$_SESSION['firstRun'] = 1;
|
|
||||||
$_SESSION['webPage'] = 1;
|
|
||||||
if ($_SERVER['REQUEST_URI'] !== '/backend?page=settings') {
|
|
||||||
header("Location:/backend?page=settings");
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($conf->onlyLocalServer === true && $_SERVER['REMOTE_ADDR'] !== '127.0.0.1') {
|
|
||||||
$error = new Error();
|
|
||||||
$error->index((object)['status' => 404, 'message' => 'The page that you have requested could not be found.']);
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($router->match()) {
|
|
||||||
$router->render($conf);
|
|
||||||
} else {
|
|
||||||
$error = new Error();
|
|
||||||
$error->index((object)['status' => 404, 'message' => 'The page that you have requested could not be found.']);
|
|
||||||
}
|
|
13
readme.md
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# !!!! Be careful !!!!
|
||||||
|
## This script can overcharge your server.
|
||||||
|
## Use at your own risk
|
||||||
|
|
||||||
|
|
||||||
|
All info in the homepage http://forge.leslibres.org/projects/soshot
|
||||||
|
|
||||||
|
**Thanks**
|
||||||
|
|
||||||
|
* Icon by http://www.iconfinder.com/icondetails/7917/128/camera_file_image_icon
|
||||||
|
* Bash script idea by http://www.cambus.net/blog/page/3/
|
||||||
|
* Httpstatus in bash by https://gist.github.com/rsvp/1171304
|
||||||
|
* The engine phantomjs by http://phantomjs.org/
|
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 99 KiB |
|
@ -1,113 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
width="1920"
|
|
||||||
height="1080"
|
|
||||||
viewBox="0 0 507.99994 285.74997"
|
|
||||||
version="1.1"
|
|
||||||
id="svg5"
|
|
||||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
|
||||||
sodipodi:docname="generation_in_progress.svg"
|
|
||||||
inkscape:export-filename="generation_in_progress.jpg"
|
|
||||||
inkscape:export-xdpi="96"
|
|
||||||
inkscape:export-ydpi="96"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview7"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:showpageshadow="2"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pagecheckerboard="0"
|
|
||||||
inkscape:deskcolor="#d1d1d1"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:zoom="0.5946522"
|
|
||||||
inkscape:cx="914.82046"
|
|
||||||
inkscape:cy="412.00554"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1150"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="24"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:current-layer="layer1" />
|
|
||||||
<defs
|
|
||||||
id="defs2">
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
id="linearGradient1515">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#000000;stop-opacity:1;"
|
|
||||||
offset="0"
|
|
||||||
id="stop1511" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#000000;stop-opacity:0;"
|
|
||||||
offset="1"
|
|
||||||
id="stop1513" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient1515"
|
|
||||||
id="linearGradient1517"
|
|
||||||
x1="0.55058265"
|
|
||||||
y1="22.141287"
|
|
||||||
x2="41.490334"
|
|
||||||
y2="19.506355"
|
|
||||||
gradientUnits="userSpaceOnUse" />
|
|
||||||
</defs>
|
|
||||||
<g
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer3"
|
|
||||||
inkscape:label="Calque 3"
|
|
||||||
style="fill:#ff0000" />
|
|
||||||
<g
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer2"
|
|
||||||
inkscape:label="Calque 2" />
|
|
||||||
<g
|
|
||||||
inkscape:label="Calque 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1">
|
|
||||||
<g
|
|
||||||
id="g2134"
|
|
||||||
transform="matrix(11.965877,0,0,11.819126,0.86251738,2.3240735)">
|
|
||||||
<rect
|
|
||||||
style="opacity:1;fill:#ffffff;stroke:none;stroke-width:0.16;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:0.4"
|
|
||||||
id="rect1746"
|
|
||||||
width="42.55217"
|
|
||||||
height="24.264963"
|
|
||||||
x="-0.078654662"
|
|
||||||
y="-0.19663666" />
|
|
||||||
<rect
|
|
||||||
style="opacity:0.375168;fill:url(#linearGradient1517);fill-opacity:1;stroke:none;stroke-width:0.16;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:0.4"
|
|
||||||
id="rect779"
|
|
||||||
width="41.097057"
|
|
||||||
height="2.7922401"
|
|
||||||
x="0.51125532"
|
|
||||||
y="19.427702" />
|
|
||||||
<text
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-style:normal;font-weight:normal;font-size:7.56121px;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.18903"
|
|
||||||
x="1.2073866"
|
|
||||||
y="6.6335373"
|
|
||||||
id="text113"
|
|
||||||
transform="scale(1.0116028,0.98853033)"><tspan
|
|
||||||
sodipodi:role="line"
|
|
||||||
id="tspan111"
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.56121px;font-family:C059;-inkscape-font-specification:'C059, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.18903"
|
|
||||||
x="1.2073866"
|
|
||||||
y="6.6335373">Generation</tspan><tspan
|
|
||||||
sodipodi:role="line"
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.56121px;font-family:C059;-inkscape-font-specification:'C059, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.18903"
|
|
||||||
x="1.2073866"
|
|
||||||
y="16.447044"
|
|
||||||
id="tspan115">in progress</tspan></text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 4 KiB |
Before Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 5.1 KiB |
125
style.css
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
html {
|
||||||
|
padding: 1em;
|
||||||
|
font-family: arial, sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 2em;
|
||||||
|
background-color: #dedede;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color:#8AC007;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:visited {
|
||||||
|
color : #8AC007;
|
||||||
|
}
|
||||||
|
|
||||||
|
form, #result, #header, .message, .hMenu, #log {
|
||||||
|
padding: 1em;
|
||||||
|
text-align: center;
|
||||||
|
width: 60%;
|
||||||
|
margin: 1em auto;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-shadow: 0 0 8px rgba(0, 0, 0, 0.50), 0 85px 180px 0 #FFFFFF, 0 12px 8px -5px rgba(0, 0, 0, 0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
input, select {
|
||||||
|
height: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#result input[type=text] {
|
||||||
|
width: 80%;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=url] {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#result label {
|
||||||
|
margin-right: 1em;
|
||||||
|
width: 15%;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .info {
|
||||||
|
text-align: right;
|
||||||
|
margin: 0 0;
|
||||||
|
line-height: 0.8em;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#result, #header {
|
||||||
|
text-align: center;
|
||||||
|
padding: 1em;
|
||||||
|
margin: 1em auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#result img {
|
||||||
|
box-shadow: 3px 3px 3px #cdcdcd;
|
||||||
|
border: 1px solid #cdcdcd;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
background-color: orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hMenu li {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hMenu li:after {
|
||||||
|
content: " / ";
|
||||||
|
}
|
||||||
|
|
||||||
|
.hMenu li:last-child:after {
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
.clear {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#log li {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 320px) and (max-width: 800px) {
|
||||||
|
|
||||||
|
html {
|
||||||
|
padding: 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
form, #result {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=url] {
|
||||||
|
width: 99%;
|
||||||
|
height: 2em;
|
||||||
|
}
|
||||||
|
input[type=submit] {
|
||||||
|
width: 99%;
|
||||||
|
height: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
width: 99%;
|
||||||
|
height: 2em;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
19
tpl/bone.php
|
@ -1,19 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<title>SoShot</title>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="description" content="Personal webshot">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="stylesheet" href="assets/css/w3.css">
|
|
||||||
<link rel="stylesheet" href="https://www.w3schools.com/lib/w3-theme-black.css">
|
|
||||||
<link rel="stylesheet" href="assets/css/fork-awesome.min.css">
|
|
||||||
<link rel="stylesheet" href="assets/css/style.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<?= $content; ?>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -1,24 +0,0 @@
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
function switchTheme(e) {
|
|
||||||
let actualTheme = document.documentElement.getAttribute('data-theme');
|
|
||||||
if (actualTheme === null || actualTheme === 'light') {
|
|
||||||
document.documentElement.setAttribute('data-theme', 'dark');
|
|
||||||
localStorage.setItem('theme', 'dark');
|
|
||||||
} else {
|
|
||||||
document.documentElement.setAttribute('data-theme', 'light');
|
|
||||||
localStorage.setItem('theme', 'light');
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentTheme = localStorage.getItem('theme') ? localStorage.getItem('theme') : null;
|
|
||||||
if (currentTheme) {
|
|
||||||
document.documentElement.setAttribute('data-theme', currentTheme);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<footer id="myFooter" class="w3-bottom">
|
|
||||||
<div class="w3-container">
|
|
||||||
<p>Powered by <a href="https://forge.leslibres.org/Knah-Tsaeb/Soshot" target="_blank"> Soshot </a>| Theme by <a href="https://www.w3schools.com/w3css/default.asp" target="_blank">w3.css</a></p>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
12
tpl/home.php
|
@ -1,12 +0,0 @@
|
||||||
<div class="w3-row-padding centerBlock homeForm">
|
|
||||||
<h1 class="w3-center">SoShot</h1>
|
|
||||||
<p>
|
|
||||||
<h3>Per<b>so</b>nal web<b>shot</b>er</h3>
|
|
||||||
</p>
|
|
||||||
<div class="w3-center">
|
|
||||||
<img src="assets/img/wikipedia_logiciel_libre.png" alt="Thumbshot of french wikipedia home page" width="720px">
|
|
||||||
</div>
|
|
||||||
<p class="w3-center">
|
|
||||||
<a href="https://forge.leslibres.org/Knah-Tsaeb/Soshot">Homepage</a> | <a href="https://knah-tsaeb.org/contact-page/">Contact</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
158
tpl/infos.php
|
@ -1,158 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use App\Utils\ConvertStatus;
|
|
||||||
use App\Utils\Domains;
|
|
||||||
|
|
||||||
?>
|
|
||||||
<div class="w3-row soshot-main w3-margin-bottom">
|
|
||||||
<div class="w3-container">
|
|
||||||
<h1 class="w3-text">Infos</h1>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Total : <?= $total; ?></li>
|
|
||||||
<li>Queue : <?= $inQueue; ?></li>
|
|
||||||
<li>Error : <?= $inError; ?></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<form>
|
|
||||||
<input class="w3-input" type="text" name="search" value="<?= $search; ?>" placeholder="Search">
|
|
||||||
<input class="w3-button" type="submit" value="Rechercher">
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<table class="w3-table-all w3-hoverable" data-theme="light">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<td>Domain</td>
|
|
||||||
<td>Created</td>
|
|
||||||
<td>Complete</td>
|
|
||||||
<td>Full</td>
|
|
||||||
<td>HD</td>
|
|
||||||
<td>nHD</td>
|
|
||||||
<td>Thumb</td>
|
|
||||||
<td>Favicon</td>
|
|
||||||
<td>Og</td>
|
|
||||||
<td>PDF</td>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php foreach ($genList as $value) : ?>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<span class="w3-left ">
|
|
||||||
<a href="#" class="linkDetail" data-hmac="<?= $value->id; ?>" data-href="<?= $value->url; ?>"><?= Domains::getDomain($value->url); ?></a>
|
|
||||||
</span>
|
|
||||||
<span class="w3-right" style="width:40px">
|
|
||||||
<a href="?page=infos&deleteGen=<?= $value->id; ?>"><i class="fa fa-trash-o delete" aria-hidden="true"></i></a>
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td><?= $value->created; ?></td>
|
|
||||||
<td><?= ConvertStatus::convertToIcon($value->complete); ?></td>
|
|
||||||
<td><?= ConvertStatus::convertToIcon($value->full); ?></td>
|
|
||||||
<td><?= ConvertStatus::convertToIcon($value->hd); ?></td>
|
|
||||||
<td><?= ConvertStatus::convertToIcon($value->nhd); ?></td>
|
|
||||||
<td><?= ConvertStatus::convertToIcon($value->thumb); ?></td>
|
|
||||||
<td><?= ConvertStatus::convertToIcon($value->fav); ?></td>
|
|
||||||
<td><?= ConvertStatus::convertToIcon($value->og); ?></td>
|
|
||||||
<td><?= ConvertStatus::convertToIcon($value->pdf); ?></td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<div class="w3-center w3-margin-top">
|
|
||||||
<div class="w3-bar">
|
|
||||||
<?php if ($start > 0) : ?>
|
|
||||||
<a href="?page=infos&start=<?= $previous; ?>" class="w3 w3-button">« Previous</a>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if ($next != $start) :; ?>
|
|
||||||
<a href="?page=infos&start=<?= $next; ?>" class="w3 w3-button">Next » </a>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="detail" class="w3-modal">
|
|
||||||
<div class="w3-modal-content w3-animate-opacity">
|
|
||||||
<div class="w3-container">
|
|
||||||
<span onclick="document.getElementById('detail').style.display='none'" class="w3-button w3-display-topright w3-xxlarge">×</span>
|
|
||||||
<p>
|
|
||||||
<img src="" id="fav" height="32px">
|
|
||||||
<a href="" id="titlePreview" target="_blanck"></a>
|
|
||||||
</p>
|
|
||||||
<img class="w3-border w3c-margin zoom" src="" id="complete" width="45%" onclick="fullNewtab(this.src);">
|
|
||||||
<img class="w3-border w3c-margin zoom" src="" id="full" width="35%" onclick="fullNewtab(this.src);">
|
|
||||||
<img class="w3-border w3c-margin zoom" src="" id="hd" width="30%" onclick="fullNewtab(this.src);">
|
|
||||||
<img class="w3-border w3c-margin zoom" src="" id="og" width="25%" onclick="fullNewtab(this.src);">
|
|
||||||
<img class="w3-border w3c-margin zoom" src="" id="nhd" width="20%" onclick="fullNewtab(this.src);">
|
|
||||||
<img class="w3-border w3c-margin zoom" src="" id="thumb" width="15%" onclick="fullNewtab(this.src);">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- END MAIN -->
|
|
||||||
<script>
|
|
||||||
// Get the Sidebar
|
|
||||||
var mySidebar = document.getElementById("mySidebar");
|
|
||||||
|
|
||||||
// Get the DIV with overlay effect
|
|
||||||
var overlayBg = document.getElementById("myOverlay");
|
|
||||||
|
|
||||||
// Toggle between showing and hiding the sidebar, and add overlay effect
|
|
||||||
function w3_open() {
|
|
||||||
if (mySidebar.style.display === 'block') {
|
|
||||||
mySidebar.style.display = 'none';
|
|
||||||
overlayBg.style.display = "none";
|
|
||||||
} else {
|
|
||||||
mySidebar.style.display = 'block';
|
|
||||||
overlayBg.style.display = "block";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close the sidebar with the close button
|
|
||||||
function w3_close() {
|
|
||||||
mySidebar.style.display = "none";
|
|
||||||
overlayBg.style.display = "none";
|
|
||||||
}
|
|
||||||
|
|
||||||
const el = document.querySelectorAll('.linkDetail');
|
|
||||||
el.forEach(element => {
|
|
||||||
element.addEventListener("click", (el) => {
|
|
||||||
let $hmac = el.srcElement.dataset.hmac;
|
|
||||||
let $href = el.srcElement.dataset.href;
|
|
||||||
let $title = document.getElementById("titlePreview");
|
|
||||||
let $complete = document.getElementById("complete");
|
|
||||||
let $full = document.getElementById("full");
|
|
||||||
let $hd = document.getElementById("hd");
|
|
||||||
let $nhd = document.getElementById("nhd");
|
|
||||||
let $thumb = document.getElementById("thumb");
|
|
||||||
let $og = document.getElementById("og");
|
|
||||||
let $fav = document.getElementById("fav");
|
|
||||||
|
|
||||||
$title.href = $href;
|
|
||||||
$title.textContent = $href;
|
|
||||||
$complete.src = "?type=complete&showImg=" + $hmac;
|
|
||||||
$full.src = "?type=full&showImg=" + $hmac;
|
|
||||||
$hd.src = "?type=hd&showImg=" + $hmac;
|
|
||||||
$nhd.src = "?type=nhd&showImg=" + $hmac;
|
|
||||||
$thumb.src = "?type=thumb&showImg=" + $hmac;
|
|
||||||
$og.src = "?type=og&showImg=" + $hmac;
|
|
||||||
$fav.src = "?type=fav&showImg=" + $hmac;
|
|
||||||
document.getElementById('detail').style.display = 'block';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function fullNewtab(imgSrc) {
|
|
||||||
window.open(imgSrc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the modal
|
|
||||||
var modal = document.getElementById('detail');
|
|
||||||
|
|
||||||
// When the user clicks anywhere outside of the modal, close it
|
|
||||||
window.onclick = function(event) {
|
|
||||||
if (event.target == modal) {
|
|
||||||
modal.style.display = "none";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,11 +0,0 @@
|
||||||
<div class="w3-center w3-container w3-half w3-display-middle">
|
|
||||||
<i class="fa fa-5x fa-lock" aria-hidden="true"></i>
|
|
||||||
|
|
||||||
<form class="w3-container" action="?" method="post">
|
|
||||||
<div class="w3-section">
|
|
||||||
<input class="w3-input w3-border" type="password" placeholder="Password" name="loginPassword" required>
|
|
||||||
<input type="hidden" name="token" value="<?= $token; ?>" />
|
|
||||||
<button class="w3-button w3-block w3-section w3-padding" style="width:30%; margin:0 auto" type="submit">Login</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
32
tpl/nav.php
|
@ -1,32 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use App\Utils\Page;
|
|
||||||
?>
|
|
||||||
<div class="w3-top w3-round">
|
|
||||||
<div class="w3-bar w3-theme w3-top w3-left-align w3-large">
|
|
||||||
<a class="w3-bar-item w3-button w3-right w3-hide-large w3-hover-white w3-large w3-theme-l1" href="javascript:void(0)" onclick="w3_open()"><i class="fa fa-bars"></i></a>
|
|
||||||
<h1><a href="#" class="title"><i class="fa fa-camera" aria-hidden="true"></i> SoShot</a></h1>
|
|
||||||
<?php if ($this->runningJob) : ?><i class="fa fa-refresh fa-spin w3-text-red"></i><?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Sidebar -->
|
|
||||||
<nav class="w3-sidebar w3-bar-block w3-collapse w3-large w3-theme-l5 w3-round" id="mySidebar">
|
|
||||||
<a href="javascript:void(0)" onclick="w3_close()" class="w3-right w3-xlarge w3-padding-large w3-hover-black w3-hide-large" title="Close Menu">
|
|
||||||
<i class="fa fa-remove"></i>
|
|
||||||
</a>
|
|
||||||
<a class="w3-bar-item <?= Page::active($params->page, 'infos', 'w3-bar-item-selected') ?>" href="?page=infos"> <i class="fa fa-info"></i> Infos</a>
|
|
||||||
<a class="w3-bar-item <?= Page::active($params->page, 'settings', 'w3-bar-item-selected') ?>" href="?page=settings"><i class="fa fa-cog"></i> Settings</a>
|
|
||||||
|
|
||||||
<a class="w3-bar-item w3-margin-top" onclick="switchTheme();" href="#" ><i class="fa fa-moon" aria-hidden="true"></i> Dark/Light</a>
|
|
||||||
|
|
||||||
<a class="w3-bar-item w3-margin-top <?= Page::active($params->page, 'logout', 'w3-bar-item-selected') ?>" href="/logout"><i class="fa fa-sign-out"></i> Logout</a>
|
|
||||||
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<!-- Overlay effect when opening sidebar on small screens -->
|
|
||||||
<div class="w3-overlay w3-hide-large" onclick="w3_close()" style="cursor:pointer" title="close side menu" id="myOverlay"></div>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Main content: shift it to the right by 250 pixels when the sidebar is visible -->
|
|
||||||
<div class="w3-main w3-animate-right">
|
|
|
@ -1,82 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use App\Utils\Page;
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div class="w3-row soshot-main w3-margin-bottom">
|
|
||||||
<div class="w3-container">
|
|
||||||
<h1 class="w3-text"><?= $this->title; ?></h1>
|
|
||||||
<form class="w3-container" method="post" data-theme="dark">
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<label>Accept only request from 127.0.0.1</label>
|
|
||||||
<input class="w3-check" type="checkbox" name="onlyLocalServer" value="1" <?= Page::checked($this->conf->onlyLocalServer, true); ?>>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<label>Use web GUI</label>
|
|
||||||
<input class="w3-check" type="checkbox" name="webPage" value="1" <?= Page::checked($this->conf->webPage, true); ?>>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<label>Use log</label>
|
|
||||||
<input class="w3-check" type="checkbox" name="log" value="1" <?= Page::checked($this->conf->log, true); ?>>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<label>Always make PDF</label>
|
|
||||||
<input class="w3-check" type="checkbox" name="alwaysMakePdf" value="1" <?= Page::checked($this->conf->alwaysMakePdf, true); ?>>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<label>File format (png, jpeg)</label>
|
|
||||||
<select class="w3-select w3-border" name="fileFormat" size="2">
|
|
||||||
<option value="png" <?= Page::selected('png', $this->conf->fileFormat); ?>>png</option>
|
|
||||||
<option value="jpeg" <?= Page::selected('jpeg', $this->conf->fileFormat); ?>>jpeg</option>
|
|
||||||
</select>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<label>Favicon size</label>
|
|
||||||
<input class="w3-input w3-border" type="number" name="icoSize" value="<?= $this->conf->icoSize; ?>">
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<label>Permit type of webshot</label>
|
|
||||||
<select class="w3-select w3-border" name="permitType[]" multiple size="7">
|
|
||||||
<option value="fav" <?= Page::selected('fav', $this->conf->permitType); ?>>Favicon (<?= $this->conf->icoSize; ?>x<?= $this->conf->icoSize; ?>)</option>
|
|
||||||
<option value="og" <?= Page::selected('og', $this->conf->permitType); ?>>Og image</option>
|
|
||||||
<option value="pdf" <?= Page::selected('pdf', $this->conf->permitType); ?>>PDF</option>
|
|
||||||
<option value="thumb" <?= Page::selected('thumb', $this->conf->permitType); ?>>ThumbShot (160x90)</option>
|
|
||||||
<option value="nhd" <?= Page::selected('nhd', $this->conf->permitType); ?>>nHD (640x360)</option>
|
|
||||||
<option value="hd" <?= Page::selected('hd', $this->conf->permitType); ?>>HD (1080x720)</option>
|
|
||||||
<option value="full" <?= Page::selected('full', $this->conf->permitType); ?>>Full HD (1920x1080)</option>
|
|
||||||
<option value="complete" <?= Page::selected('complete', $this->conf->permitType); ?>>Complete (1920x height of page)</option>
|
|
||||||
</select>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<label>Cache expiration (for web GUI) in hour</label>
|
|
||||||
<input class="w3-input w3-border" type="number" name="expireCache" value="<?= $this->conf->expireCache; ?>">
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<label>Maximum work per batch</label>
|
|
||||||
<input class="w3-input w3-border" type="number" name="maxGenPerBatch" value="<?= $this->conf->maxGenPerBatch; ?>">
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<label>Api key (<span class="w3-red">change key will be invalid all previous generation</span>)</label>
|
|
||||||
<input class="w3-input w3-border" type="text" name="key" value="<?= $this->conf->key; ?>">
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<label>Password</label>
|
|
||||||
<input class="w3-input w3-border" type="password" name="password" value="" <?= $this->passwordRequired; ?>>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<label>Chrome path (if empty, SoShot use default value "chrome or chromium")</label>
|
|
||||||
<input class="w3-input w3-border" type="text" name="chromePath" value="<?= $this->conf->chromePath; ?>">
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<input type="hidden" name="page" value="settings">
|
|
||||||
<input type="hidden" name="token" value="<?= $token; ?>">
|
|
||||||
<button type="submit" class="w3-btn w3-padding w3" style="width:120px">Save</button>
|
|
||||||
</p>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|