-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapi.php
More file actions
83 lines (68 loc) · 2.86 KB
/
Copy pathapi.php
File metadata and controls
83 lines (68 loc) · 2.86 KB
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
<?php
// api.php
/** @var PDO $db */
require 'db.php';
header('Content-Type: application/json');
$input = json_decode(file_get_contents('php://input'), true);
$action = $input['action'] ?? '';
switch ($action) {
case 'start':
// FIX 1: Prevent multiple timers.
// If a timer is already running, stop it first.
$now = time();
$check = $db->query("SELECT id FROM time_entries WHERE end_time IS NULL LIMIT 1");
if ($check->fetch()) {
$stopStmt = $db->prepare("UPDATE time_entries SET end_time = :end WHERE end_time IS NULL");
$stopStmt->execute([':end' => $now]);
}
// Start the new timer
$stmt = $db->prepare("INSERT INTO time_entries (start_time) VALUES (:start)");
$stmt->execute([':start' => $now]);
echo json_encode(['status' => 'success']);
break;
case 'stop':
$now = time();
$stmt = $db->prepare("UPDATE time_entries SET end_time = :end WHERE end_time IS NULL");
$stmt->execute([':end' => $now]);
echo json_encode(['status' => 'success']);
break;
case 'update':
$id = $input['id'];
$allowedFields = ['project', 'start_time', 'end_time'];
$updates = [];
$params = [':id' => $id];
foreach ($allowedFields as $field) {
if (array_key_exists($field, $input)) {
$updates[] = "$field = :$field";
$value = $input[$field];
// FIX 2: SERVER-SIDE XSS PROTECTION
// Sanitize text fields before saving to the DB.
// This neutralizes <script> tags into <script>
if ($field === 'project' && is_string($value)) {
$value = htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
$params[":$field"] = $value;
}
}
if (!empty($updates)) {
$sql = "UPDATE time_entries SET " . implode(', ', $updates) . " WHERE id = :id";
$stmt = $db->prepare($sql);
$stmt->execute($params);
}
echo json_encode(['status' => 'success']);
break;
case 'list':
// UPDATED LOGIC:
// If inputs are null (cleared by user), default to the full range of time.
// 2147483647 is the max 32-bit integer (Year 2038), effectively "forever" for this MVP.
$to = $input['to'] ?? 2147483647;
$from = $input['from'] ?? 0; // Jan 1, 1970
$stmt = $db->prepare("SELECT * FROM time_entries WHERE start_time BETWEEN :from AND :to ORDER BY start_time DESC");
$stmt->execute([':from' => $from, ':to' => $to]);
$entries = $stmt->fetchAll();
echo json_encode(['status' => 'success', 'data' => $entries]);
break;
default:
echo json_encode(['status' => 'error', 'message' => 'Invalid action']);
break;
}