cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

ls.c (4002B)


      1/*
      2 * Licensed to the Apache Software Foundation (ASF) under one
      3 * or more contributor license agreements.  See the NOTICE file
      4 * distributed with this work for additional information
      5 * regarding copyright ownership.  The ASF licenses this file
      6 * to you under the Apache License, Version 2.0 (the
      7 * "License"); you may not use this file except in compliance
      8 * with the License.  You may obtain a copy of the License at
      9 *
     10 *   http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing,
     13 * software distributed under the License is distributed on an
     14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     15 * KIND, either express or implied.  See the License for the
     16 * specific language governing permissions and limitations
     17 * under the License.
     18 */
     19
     20#include "fs.h"
     21#include "ls.h"
     22
     23#include <guacamole/client.h>
     24#include <guacamole/mem.h>
     25#include <guacamole/protocol.h>
     26#include <guacamole/socket.h>
     27#include <guacamole/stream.h>
     28#include <guacamole/user.h>
     29#include <winpr/file.h>
     30#include <winpr/nt.h>
     31#include <winpr/shell.h>
     32
     33#include <stdlib.h>
     34#include <string.h>
     35
     36int guac_rdp_ls_ack_handler(guac_user* user, guac_stream* stream,
     37        char* message, guac_protocol_status status) {
     38
     39    int blob_written = 0;
     40    const char* filename;
     41
     42    guac_rdp_ls_status* ls_status = (guac_rdp_ls_status*) stream->data;
     43
     44    /* If unsuccessful, free stream and abort */
     45    if (status != GUAC_PROTOCOL_STATUS_SUCCESS) {
     46        guac_rdp_fs_close(ls_status->fs, ls_status->file_id);
     47        guac_user_free_stream(user, stream);
     48        guac_mem_free(ls_status);
     49        return 0;
     50    }
     51
     52    /* While directory entries remain */
     53    while ((filename = guac_rdp_fs_read_dir(ls_status->fs,
     54                    ls_status->file_id)) != NULL
     55            && !blob_written) {
     56
     57        char absolute_path[GUAC_RDP_FS_MAX_PATH];
     58
     59        /* Skip current and parent directory entries */
     60        if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0)
     61            continue;
     62
     63        /* Concatenate into absolute path - skip if invalid */
     64        if (!guac_rdp_fs_append_filename(absolute_path,
     65                    ls_status->directory_name, filename)) {
     66
     67            guac_user_log(user, GUAC_LOG_DEBUG,
     68                    "Skipping filename \"%s\" - filename is invalid or "
     69                    "resulting path is too long", filename);
     70
     71            continue;
     72        }
     73
     74        /* Attempt to open file to determine type */
     75        int file_id = guac_rdp_fs_open(ls_status->fs, absolute_path,
     76                GENERIC_READ, 0, FILE_OPEN, 0);
     77        if (file_id < 0)
     78            continue;
     79
     80        /* Get opened file */
     81        guac_rdp_fs_file* file = guac_rdp_fs_get_file(ls_status->fs, file_id);
     82        if (file == NULL) {
     83            guac_user_log(user, GUAC_LOG_DEBUG, "%s: Successful open produced "
     84                    "bad file_id: %i", __func__, file_id);
     85            return 0;
     86        }
     87
     88        /* Determine mimetype */
     89        const char* mimetype;
     90        if (file->attributes & FILE_ATTRIBUTE_DIRECTORY)
     91            mimetype = GUAC_USER_STREAM_INDEX_MIMETYPE;
     92        else
     93            mimetype = "application/octet-stream";
     94
     95        /* Write entry */
     96        blob_written |= guac_common_json_write_property(user, stream,
     97                &ls_status->json_state, absolute_path, mimetype);
     98
     99        guac_rdp_fs_close(ls_status->fs, file_id);
    100
    101    }
    102
    103    /* Complete JSON and cleanup at end of directory */
    104    if (filename == NULL) {
    105
    106        /* Complete JSON object */
    107        guac_common_json_end_object(user, stream, &ls_status->json_state);
    108        guac_common_json_flush(user, stream, &ls_status->json_state);
    109
    110        /* Clean up resources */
    111        guac_rdp_fs_close(ls_status->fs, ls_status->file_id);
    112        guac_mem_free(ls_status);
    113
    114        /* Signal of stream */
    115        guac_protocol_send_end(user->socket, stream);
    116        guac_user_free_stream(user, stream);
    117
    118    }
    119
    120    guac_socket_flush(user->socket);
    121    return 0;
    122
    123}
    124