diff --git a/z.ai/notes-noshare/index.php b/z.ai/notes-noshare/index.php new file mode 100644 index 0000000..fe0e081 --- /dev/null +++ b/z.ai/notes-noshare/index.php @@ -0,0 +1,2367 @@ +exec(' + CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT UNIQUE NOT NULL, + password TEXT NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP + ) + '); + + // 创建笔记表(加密存储) + $db->exec(' + CREATE TABLE IF NOT EXISTS notes ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + title_enc TEXT NOT NULL, + content_enc TEXT NOT NULL, + tags TEXT, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP + ) + '); + + // 创建附件表 + $db->exec(' + CREATE TABLE IF NOT EXISTS attachments ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + note_id INTEGER NOT NULL, + filename TEXT NOT NULL, + original_name TEXT NOT NULL, + file_size INTEGER NOT NULL, + file_type TEXT NOT NULL, + upload_time DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (note_id) REFERENCES notes (id) ON DELETE CASCADE + ) + '); + + // 创建索引 + $db->exec('CREATE INDEX IF NOT EXISTS idx_notes_tags ON notes(tags)'); + $db->exec('CREATE INDEX IF NOT EXISTS idx_notes_created ON notes(created_at)'); + $db->exec('CREATE INDEX IF NOT EXISTS idx_attachments_note_id ON attachments(note_id)'); + + return $db; + } catch (Exception $e) { + die('数据库初始化失败: ' . $e->getMessage()); + } +} + +// 获取数据库连接 +function getDB() { + static $db = null; + if ($db === null) { + $db = initDatabase(); + } + return $db; +} + +// 检查是否已初始化 +function isInitialized() { + $db = getDB(); + $result = $db->querySingle('SELECT COUNT(*) FROM users'); + return $result > 0; +} + +// 验证用户登录 +function verifyUser($username, $password) { + $db = getDB(); + $stmt = $db->prepare('SELECT password FROM users WHERE username = ?'); + $stmt->bindValue(1, $username, SQLITE3_TEXT); + $result = $stmt->execute(); + $user = $result->fetchArray(SQLITE3_ASSOC); + + if ($user && password_verify($password, $user['password'])) { + return true; + } + return false; +} + +// 创建用户 +function createUser($username, $password) { + $db = getDB(); + $hashedPassword = password_hash($password, PASSWORD_DEFAULT); + $stmt = $db->prepare('INSERT INTO users (username, password) VALUES (?, ?)'); + $stmt->bindValue(1, $username, SQLITE3_TEXT); + $stmt->bindValue(2, $hashedPassword, SQLITE3_TEXT); + return $stmt->execute(); +} + +// 更新用户密码 +function updatePassword($newPassword) { + $db = getDB(); + $hashedPassword = password_hash($newPassword, PASSWORD_DEFAULT); + $stmt = $db->prepare('UPDATE users SET password = ? WHERE id = 1'); + $stmt->bindValue(1, $hashedPassword, SQLITE3_TEXT); + return $stmt->execute(); +} + +// 获取笔记总数 +function getNotesCount($search = '', $tag = '') { + $db = getDB(); + $sql = 'SELECT COUNT(*) FROM notes WHERE 1=1'; + $params = []; + + if ($search) { + // 搜索需要解密,这里简化处理,只搜索标签 + $sql .= ' AND tags LIKE ?'; + $searchParam = '%' . $search . '%'; + $params[] = $searchParam; + } + + if ($tag) { + $sql .= ' AND tags LIKE ?'; + $params[] = '%' . $tag . '%'; + } + + $stmt = $db->prepare($sql); + foreach ($params as $i => $param) { + $stmt->bindValue($i + 1, $param, SQLITE3_TEXT); + } + + return $stmt->execute()->fetchArray()[0]; +} + +// 获取笔记列表(分页) +function getNotes($page = 1, $search = '', $tag = '') { + $db = getDB(); + $offset = ($page - 1) * NOTES_PER_PAGE; + + $sql = 'SELECT * FROM notes WHERE 1=1'; + $params = []; + + if ($search) { + $sql .= ' AND tags LIKE ?'; + $params[] = '%' . $search . '%'; + } + + if ($tag) { + $sql .= ' AND tags LIKE ?'; + $params[] = '%' . $tag . '%'; + } + + $sql .= ' ORDER BY updated_at DESC LIMIT ? OFFSET ?'; + $params[] = NOTES_PER_PAGE; + $params[] = $offset; + + $stmt = $db->prepare($sql); + foreach ($params as $i => $param) { + $stmt->bindValue($i + 1, $param, SQLITE3_TEXT); + } + + $result = $stmt->execute(); + $notes = []; + + while ($row = $result->fetchArray(SQLITE3_ASSOC)) { + // 解密数据 + $row['title'] = Encryption::decrypt($row['title_enc']); + $row['content'] = Encryption::decrypt($row['content_enc']); + unset($row['title_enc'], $row['content_enc']); + $notes[] = $row; + } + + return $notes; +} + +// 获取单条笔记 +function getNote($id) { + $db = getDB(); + $stmt = $db->prepare('SELECT * FROM notes WHERE id = ?'); + $stmt->bindValue(1, $id, SQLITE3_INTEGER); + $result = $stmt->execute(); + $note = $result->fetchArray(SQLITE3_ASSOC); + + if ($note) { + // 解密数据 + $note['title'] = Encryption::decrypt($note['title_enc']); + $note['content'] = Encryption::decrypt($note['content_enc']); + unset($note['title_enc'], $note['content_enc']); + } + + return $note; +} + +// 创建笔记 +function createNote($title, $content, $tags) { + $db = getDB(); + $stmt = $db->prepare('INSERT INTO notes (title_enc, content_enc, tags) VALUES (?, ?, ?)'); + $stmt->bindValue(1, Encryption::encrypt($title), SQLITE3_TEXT); + $stmt->bindValue(2, Encryption::encrypt($content), SQLITE3_TEXT); + $stmt->bindValue(3, $tags, SQLITE3_TEXT); + $stmt->execute(); + return $db->lastInsertRowID(); +} + +// 更新笔记 +function updateNote($id, $title, $content, $tags) { + $db = getDB(); + $stmt = $db->prepare('UPDATE notes SET title_enc = ?, content_enc = ?, tags = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?'); + $stmt->bindValue(1, Encryption::encrypt($title), SQLITE3_TEXT); + $stmt->bindValue(2, Encryption::encrypt($content), SQLITE3_TEXT); + $stmt->bindValue(3, $tags, SQLITE3_TEXT); + $stmt->bindValue(4, $id, SQLITE3_INTEGER); + return $stmt->execute(); +} + +// 删除笔记 +function deleteNote($id) { + $db = getDB(); + $stmt = $db->prepare('DELETE FROM notes WHERE id = ?'); + $stmt->bindValue(1, $id, SQLITE3_INTEGER); + return $stmt->execute(); +} + +// 获取笔记附件 +function getNoteAttachments($noteId) { + $db = getDB(); + $stmt = $db->prepare('SELECT * FROM attachments WHERE note_id = ? ORDER BY upload_time DESC'); + $stmt->bindValue(1, $noteId, SQLITE3_INTEGER); + $result = $stmt->execute(); + $attachments = []; + + while ($row = $result->fetchArray(SQLITE3_ASSOC)) { + $attachments[] = $row; + } + + return $attachments; +} + +// 添加附件 +function addAttachment($noteId, $filename, $originalName, $fileSize, $fileType) { + $db = getDB(); + $stmt = $db->prepare('INSERT INTO attachments (note_id, filename, original_name, file_size, file_type) VALUES (?, ?, ?, ?, ?)'); + $stmt->bindValue(1, $noteId, SQLITE3_INTEGER); + $stmt->bindValue(2, $filename, SQLITE3_TEXT); + $stmt->bindValue(3, $originalName, SQLITE3_TEXT); + $stmt->bindValue(4, $fileSize, SQLITE3_INTEGER); + $stmt->bindValue(5, $fileType, SQLITE3_TEXT); + return $stmt->execute(); +} + +// 删除附件 +function deleteAttachment($id) { + $db = getDB(); + $stmt = $db->prepare('SELECT filename FROM attachments WHERE id = ?'); + $stmt->bindValue(1, $id, SQLITE3_INTEGER); + $result = $stmt->execute(); + $attachment = $result->fetchArray(SQLITE3_ASSOC); + + if ($attachment && file_exists(UPLOAD_DIR . '/' . $attachment['filename'])) { + unlink(UPLOAD_DIR . '/' . $attachment['filename']); + } + + $stmt = $db->prepare('DELETE FROM attachments WHERE id = ?'); + $stmt->bindValue(1, $id, SQLITE3_INTEGER); + return $stmt->execute(); +} + +// 获取所有标签 +function getAllTags() { + $db = getDB(); + $result = $db->query('SELECT tags FROM notes WHERE tags IS NOT NULL AND tags != ""'); + $tags = []; + + while ($row = $result->fetchArray(SQLITE3_ASSOC)) { + $noteTags = explode(',', $row['tags']); + foreach ($noteTags as $tag) { + $tag = trim($tag); + if ($tag && !in_array($tag, $tags)) { + $tags[] = $tag; + } + } + } + + sort($tags); + return $tags; +} + +// 处理文件上传 +function handleFileUpload($file, $noteId) { + if ($file['error'] !== UPLOAD_ERR_OK) { + return false; + } + + $allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'application/pdf', 'text/plain', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document']; + $maxSize = 10 * 1024 * 1024; // 10MB + + if (!in_array($file['type'], $allowedTypes) || $file['size'] > $maxSize) { + return false; + } + + $extension = pathinfo($file['name'], PATHINFO_EXTENSION); + $filename = uniqid() . '.' . $extension; + $uploadPath = UPLOAD_DIR . '/' . $filename; + + if (move_uploaded_file($file['tmp_name'], $uploadPath)) { + addAttachment($noteId, $filename, $file['name'], $file['size'], $file['type']); + return $filename; + } + + return false; +} + +// Markdown转HTML(增强版) +function markdownToHtml($markdown) { + // 简单的Markdown解析 + $html = $markdown; + + // 图片(支持本地上传的图片) + $html = preg_replace('/!\[(.*?)\]\((.*?)\)/', '$1', $html); + + // 标题 + $html = preg_replace('/^### (.*$)/m', '

$1

', $html); + $html = preg_replace('/^## (.*$)/m', '

$1

', $html); + $html = preg_replace('/^# (.*$)/m', '

$1

', $html); + + // 粗体和斜体 + $html = preg_replace('/\*\*(.*?)\*\*/', '$1', $html); + $html = preg_replace('/\*(.*?)\*/', '$1', $html); + + // 代码块 + $html = preg_replace('/```(.*?)```/s', '
$1
', $html); + $html = preg_replace('/`(.*?)`/', '$1', $html); + + // 链接 + $html = preg_replace('/\[(.*?)\]\((.*?)\)/', '$1', $html); + + // 无序列表 + $html = preg_replace('/^\* (.+)$/m', '
  • $1
  • ', $html); + $html = preg_replace('/(
  • .*<\/li>)/s', '', $html); + + // 有序列表 + $html = preg_replace('/^\d+\. (.+)$/m', '
  • $1
  • ', $html); + + // 引用 + $html = preg_replace('/^> (.+)$/m', '
    $1
    ', $html); + + // 换行 + $html = preg_replace('/\n\n/', '

    ', $html); + $html = preg_replace('/\n/', '
    ', $html); + + // 段落 + $html = '

    ' . $html . '

    '; + + // 清理多余的段落标签 + $html = preg_replace('/

    <\/p>/', '', $html); + $html = preg_replace('/

    ()/', '$1', $html); + $html = preg_replace('/(<\/h[1-6]>)<\/p>/', '$1', $html); + $html = preg_replace('/

    (

    )/', '$1', $html);
    +    $html = preg_replace('/(<\/pre>)<\/p>/', '$1', $html);
    +    $html = preg_replace('/

    (