/* whoopsie
 * 
 * Copyright © 2011-2013 Canonical Ltd.
 * Author: Evan Dandrea <evan.dandrea@canonical.com>
 * 
 * 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; version 3 of the License.
 *
 * 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 <http://www.gnu.org/licenses/>.
 */

#include <string.h>
#include <glib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>

#include "whoopsie.h"
#include "utils.h"

char*
change_file_extension (const char* path, const char* extension)
{
    /* Ex. (/var/crash/foo.crash, .upload) -> /var/crash/foo.upload */
    GString *string;
    char *ret;
    const char* current_extension = NULL;
    size_t prefix_len;

    if (!extension || !path)
        return NULL;

    current_extension = g_strrstr (path, ".");

    if (current_extension == NULL)
        return NULL;

    prefix_len = current_extension - path;

    string = g_string_new_len (path, prefix_len);
    g_string_append (string, extension);

    ret = g_string_free (string, FALSE);

    return ret;
}

gboolean
already_handled_report (const char* crash_file)
{
    /* If the .uploaded path exists and .uploaded is newer than .upload */
    char* upload_file = NULL;
    char* uploaded_file = NULL;
    struct stat uploaded_stat;
    struct stat upload_stat;
    struct stat crash_stat;

    g_return_val_if_fail (crash_file, FALSE);

    if (stat (crash_file, &crash_stat) < 0)
        /* .crash doesn't exist; don't process. */
        return TRUE;

    upload_file = change_file_extension (crash_file, ".upload");
    if (!upload_file)
        /* Bogus crash file; don't process. */
        return TRUE;

    if (stat (upload_file, &upload_stat) < 0) {
        /* .upload doesn't exist; don't process. */
        g_free (upload_file);
        return TRUE;
    }

    g_free (upload_file);
    
    uploaded_file = change_file_extension (crash_file, ".uploaded");
    if (!uploaded_file)
        /* Bogus crash file; don't process. */
        return TRUE;

    if (stat (uploaded_file, &uploaded_stat) < 0) {
        /* .uploaded doesn't exist. */
        g_free (uploaded_file);
        return FALSE;
    }

    g_free (uploaded_file);

    /* If .uploaded is newer than .upload, then we've already handled this
     * report */
    return (uploaded_stat.st_mtime > upload_stat.st_mtime);
}

gboolean
mark_handled (const char* crash_file, const char* oops_id)
{
    char* uploaded_file = NULL;
    int fd;
    FILE* fp = NULL;

    g_return_val_if_fail (crash_file, FALSE);

    uploaded_file = change_file_extension (crash_file, ".uploaded");
    if (!uploaded_file)
        return FALSE;

    fd = creat (uploaded_file, 0600);

    if (fd < 0)
        return FALSE;
    else {
        fp = fopen (uploaded_file, "w");
        if (oops_id) {
            fprintf (fp, "%s\n", oops_id);
        } else {
            fprintf (fp, "NULL\n");
        }
        fclose (fp);
        g_free (uploaded_file);
        close (fd);
        return TRUE;
    }
}
