
qdgal - a quick & dirty PHP photo gallery

I created qdgal for my own personal use, because I needed a dead simple PHP
gallery to show a few photos to family. There is plenty of such gallery
softwares on the internet, but every one that I checked was too complicated,
while I needed something *very* basic. No mandatory authentication, no user
options, no sql database, no crazy php dependencies, and a very simple user
interface that could be used by older people that are not so comfortable with
a computer.
Then I wrote a short php script during a summer afternoon, and qdgal was born.
As time passed, I added a handful of features to qdgal: basic (optional)
authentication, support for video files, custom styles, and more.

How to use it: simply copy the index.php, qdconf.php, qdlang.php and qdgal.css
files to your web server, into a directory where your photos are stored.
That's all. You can optionally edit qdconf.php and/or qdgal.css if you'd like
to customize qdgal to your liking, but that's up to you.
If you use password protection ($AUTH_PASS), copy htaccess.example to
.htaccess as well (disables directory indexes on Apache).

If you'd like to add a static caption to a photo, create a text file with the
same base name as the photo (for example 'photo.txt' if the image is named
'photo.jpg'). Its content is shown as the photo's description.

Photo location: when $PHOTO_LOCATION is enabled (the default), the photo page
shows a short place name from the JPEG's GPS EXIF (for example "GPS: La Courtine,
France"), looked up once via OpenStreetMap Nominatim and cached in
.qdgal-cache. If no name can be resolved, the raw coordinates are shown
instead. You can override this with a photo.loc sidecar (same base name as
the photo). The server needs outbound HTTPS (allow_url_fopen). AUTOROTATE
strips EXIF after GPS has been copied to the cache; photos that were already
rewritten by AUTOROTATE before this feature cannot be located unless you
restore the originals or add a .loc file.

Optional comment threads: set $COMMENTS_ENABLED = 1 in qdconf.php. Visitors can
post a comment with their email (remembered in a cookie) and a message. Threads
are stored next to each photo as photo.jpg.comments.json. Existing photo.txt
captions appear as the first message in the thread (author label "comment").
Previous commenters are notified by PHP mail() in the language recorded with
their comment, and so is every address listed in $COMMENTS_NOTIFY (optionally
with a per-address language, e.g. 'you@example.com' => 'ru'). Each address gets
at most one message; English is used if the language is missing or unknown.
Authors may edit or delete their own comment for
$COMMENTS_EDIT_HOURS hours (default 4), using a secret key kept in a cookie.
New comments are rate-limited per IP and photo (default: 2 per minute;
$COMMENTS_RATE_MAX / $COMMENTS_RATE_WINDOW). The commenter's IP is stored in
the JSON file for this check but is never shown on the page.
Set $COMMENTS_NOTIFY_ONLY = 1 to allow posting only from addresses listed in
$COMMENTS_NOTIFY (comparison is case-insensitive).
Your server must be able to send mail via PHP's mail() function.

Custom footer: to display a custom footer, create a html file named
"footer.html". qdgal will use it automatically.

Dependencies:
 - PHP 5.6+ (7.4+ or 8.x recommended)
 - php-gd (required only if thumbnail support is to be used)
 - exif (optional but highly recommended for correct thumbnails orientation
   and for photo location from GPS)
 - outbound HTTPS / allow_url_fopen (only if photo location is enabled)

homepage: https://mateusz.fr/qdgal

qdgal is published under the MIT license. It's free for anyone to use, modify,
and share.

=== Localization support =====================================================

qdgal supports a variety of languages out of the box. There's nothing you need
to do to, qdgal will auto-negotiate the browser's preferred language.
Currently, qdgal supports the following list of languages:
 * English
 * French
 * German
 * Polish
 * Russian

If your language is missing and you'd like to add it, simply add it to the
qdlang.php file. Let me know about your translation, I'd be happy to add it
into the official qdgal release.

=== License content ==========================================================

MIT License

Copyright (c) 2016-2026 Mateusz Viste

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

==============================================================================
