summaryrefslogtreecommitdiffstats
path: root/app/df.php
blob: 348daa2f7ffa2a47a8d7595006337e6c8a6027f4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<?php

/*
 * SCROTT 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 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.
 *
 * For more information, please refer to UNLICENSE
 */

require_once "class/user.class.php";
require_once "class/group.class.php";
require_once "class/mesg.class.php";

/*
 * This file is a proxy script for fetching resources from the /dynmic
 * directory.  This script enforces access-control on HTTP objects such
 * as images and flat files which are supplied by users.
 *
 * Example request:
 * https://yourdomain.com/scrott/df.php?d=heads&f=a4bf903a
 *
 * In cases of error or lack of access privilege, this script will
 * produce no output and fail silently.
 */

/*
 * Serve the resource at the given URI in response to the current
 * request.  When finished, this function will exit PHP and terminate
 * this script.
 */
function serveResource(string $uri, ?string $filename = NULL) : void
{
    $f = fopen($uri, "rb");

    /* no file */
    if (!$f)
        exit;

    /* enable client caching */
    header("Cache-Control: max-age=0");
    header("Pragma: cache");

    $hash = hash_file("sha256", $uri);

    /* validate client cache */
    if (isset($_SERVER['HTTP_IF_NONE_MATCH']) &&
            $_SERVER['HTTP_IF_NONE_MATCH'] == $hash)
    {
        header("HTTP/1.1 304 Not Modified");
        exit;
    }

    /* resource metadata */
    header("Content-Type: " . mime_content_type($uri));
    header("Content-Length: " . filesize($uri));
    header("ETag: " . $hash);

    if ($filename)
        header("Content-Disposition: attachment; filename=\"" . $filename . "\"");

    fpassthru($f);
    fclose($f);

    exit;
}

/*
 * Check the current user's permissions.  User must have access
 * rights for the file's object, unless that object is a user
 * object and $allowHeadUser is set to true.
 */
function checkPermissions(string $guid, bool $allowHeadUser = false) : bool
{
    if (!($user = user::getCurrent()))
        return false;

    $obj = new obj($guid);

    if ($allowHeadUser && $obj->objtype == "user")
        return true;

    return $user->canAccess($obj);
}

/*
 * Respond to users' requests for dynamic files
 */
function main(string $dir, string $guid) : void
{
    try
    {
        if (basename($guid) != $guid || $guid == "")
            return;

        if (!checkPermissions($guid, $dir == "heads"))
            return;

        switch ($dir)
        {
            case "heads":
                if (file_exists("dynmic/heads/" . $guid))
                    serveResource("dynmic/heads/" . $guid);
                else
                    serveResource("static/img/null.jpg");
                break;

            case "bgs":
                serveResource("dynmic/bgs/" . $guid);
                break;

            case "thumbs":
                serveResource("dynmic/thumbs/" . $guid);
                break;

            case "attach":
                $mesg = new mesg($guid);
                serveResource("dynmic/attach/" . $guid, $mesg->attachment);
                break;
        }
    }
    catch (Exception $e)
    {
        /* fail silently */
    }
}

main($_REQUEST['d'], $_REQUEST['f']);

?>