summaryrefslogtreecommitdiff
path: root/src/guestbook.cpp
blob: 0b58ddf16c7ad78dc9e8759cc0b059ab0456e085 (plain)
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
#include "guestbook.hpp"
#include "json.hpp"

#include <filesystem>
#include <fstream>
#include <iostream>

using json = nlohmann::json;

namespace {
    const std::filesystem::path guestbookFilePath = "data/guestbook.json";
}

std::vector<GuestbookEntry> loadGuestbook()
{
    std::ifstream file(guestbookFilePath);

    if (!file.is_open())
    {
        return {};
    }

    if (file.peek() == std::ifstream::traits_type::eof())
    {
        return {};
    }

    // An existing but empty file is not valid JSON. Treat it like a new
    // guestbook so a partially initialized data directory cannot crash the
    // server during startup.
    json data = json::parse(file, nullptr, false);

    if (data.is_discarded() || !data.is_array())
    {
        std::cerr << "Warning: ignoring invalid guestbook data in "
                  << guestbookFilePath << '\n';
        return {};
    }

    std::vector<GuestbookEntry> entries;

    for (const auto& item : data)
    {
        GuestbookEntry entry;
        entry.name = item.at("name").get<std::string>();
        entry.message = item.at("message").get<std::string>();

        entries.push_back(entry);
    }

    return entries;
}

bool saveGuestbook(const std::vector<GuestbookEntry>& entries)
{
    std::filesystem::create_directories(guestbookFilePath.parent_path());

    json data = json::array();

    for (const GuestbookEntry& entry : entries)
    {
        data.push_back({
            {"name", entry.name},
            {"message", entry.message}
        });
    }

    std::ofstream file(guestbookFilePath);

    if (!file.is_open())
    {
        return false;
    }

    file << data.dump(4);

    return true;
}