function tftpd_authorize_config($s, $sock, $path, $file, &$db)
{
    /* Sanitize path and filename */
    $path = preg_replace('/^\\$(.*)\\$$/', '$1', $path);
    $pass = mysql_real_escape_string($path);
    $file = mysql_real_escape_string($file);
    /* Authorize access access 
     * Note that the $db object will keep the query result for use later in
     * the script. In particular we will retrieve 'device' later.
     */
    /* Check for filename first */
    $sql = "SELECT id,filename,password FROM devices WHERE filename='{$file}'";
    tftpd_log('25', 'sql query string: "' . $sql . '"');
    if ($db->query($sql) != 1) {
        tftpd_send_nak($s, $sock, TFTP_ENOTFOUND, 'config not found');
        return false;
    }
    /* Check for filename password match next */
    $sql = "SELECT id,filename,password FROM devices WHERE filename='{$file}' AND password='******'";
    tftpd_log('25', 'sql query string: "' . $sql . '"');
    if ($db->query($sql) != 1) {
        tftpd_send_nak($s, $sock, TFTP_EACCESS, 'config not found');
        return false;
    }
    return true;
}
function tftpd_connect($sock, $r_buf)
{
    /* Create child socket to communicate with peer */
    $c_sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
    if (!$c_sock) {
        tftpd_log('0', 'could not create child socket');
        return;
    }
    $r = socket_bind($c_sock, $sock['c_addr']);
    if (!$r) {
        tftpd_log('0', 'could not bind child socket');
        return;
    }
    socket_getsockname($c_sock, $sock['c_addr'], $sock['c_port']);
    tftpd_log('11', 'listen: ' . $sock['c_addr'] . ':' . $sock['c_port']);
    /* Parse the request */
    if (!tftpd_recv_request($r_buf, $opcode, $request, $mode)) {
        tftpd_log('1', 'disconnect: invalid request');
        socket_close($c_sock);
        return;
    }
    tftpd_log('11', 'request: "' . $request . '", mode: "' . $mode . '"');
    /* Check mode */
    if (strcasecmp($mode, 'netascii') != 0 && strcasecmp($mode, 'binary') != 0 && strcasecmp($mode, 'octet') != 0) {
        tftpd_send_nak($c_sock, $sock, TFTP_EBADOP, 'unknown mode');
        socket_close($c_sock);
        return;
    }
    /* Sanitize request */
    tftpd_sanitize_request($request, $path, $file);
    /* Handle config requests as indicated by a path delimited with $.
     * Example: $password$
     */
    if (preg_match('/^\\$.+\\$$/', $path)) {
        tftpd_handle_config($c_sock, $sock, $opcode, $mode, $path, $file);
    } else {
        tftpd_handle_file($c_sock, $sock, $opcode, $mode, $path, $file);
    }
    socket_close($c_sock);
}
function tftpd_recv_file($s, $sock, $fp)
{
    $block = 0;
    $xfer_byte = 0;
    $xfer_time = tftpd_microtime();
    do {
        if (!tftpd_receive_data($s, $sock, $block, $data)) {
            return false;
        }
        $r = fwrite($fp, $data);
        if ($r != strlen($data)) {
            tftpd_send_nak($c_sock, $sock, TFTP_ENOSPACE, 'disk full?');
            return false;
        }
        $block++;
        if ($block > 65535) {
            $block = 0;
        }
        $xfer_byte += strlen($data);
    } while (strlen($data) == 512);
    /* Be a good citizen and churn out one last ACK */
    $s_buf = pack('nn', TFTP_ACK, $block);
    tftpd_send_packet($s, $sock, $s_buf);
    /* Log our success */
    $xfer_time = round(tftpd_microtime() - $xfer_time, 3);
    tftpd_log('1', 'received ' . $xfer_byte . ' bytes in ' . $xfer_time . ' seconds');
}