From 0fc43780f5b5a7d747006550c3c4dc1a3f89218c Mon Sep 17 00:00:00 2001
From: Kubat <mael.martin31@gmail.com>
Date: Mon, 4 May 2020 13:41:40 +0200
Subject: [PATCH] Use the sql search functions for stickers (factorisation)

---
 inc/lektor/database.h | 21 ++++++++++++++++-----
 src/database/find.c   | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+), 5 deletions(-)

diff --git a/inc/lektor/database.h b/inc/lektor/database.h
index 501251d4..58e91d60 100644
--- a/inc/lektor/database.h
+++ b/inc/lektor/database.h
@@ -83,22 +83,33 @@ struct lkt_search {
         lkt_search_database,
         lkt_search_playlist,
         lkt_search_queue,
+        lkt_search_sticker,
+
         lkt_add_queue,
     } type;
+
     bool (*init)(volatile sqlite3 *);   /* Called at the end of the init phase          */
     void (*call)(void);                 /* Called during the iter phase, casted         */
+
     struct lkt_state *srv;
     size_t c;
+
     long continuation;                  /* The continuation state of the client         */
     int msg_count;                      /* How much messages we can send                */
-    int priority;                       /* Can be used... where the priority is needed! */
+    const char *name;                   /* Stickers and playlists                       */
+    union {
+        int qu_priority;                /* Can be used... where the priority is needed! */
+        int st_value;                   /* The value of a sticker                       */
+    };
+    int st_uri;                         /* URI of a sticker                             */
 };
 
-typedef bool (*lkt_search_database_func)(struct lkt_state *srv, size_t c, int id, int id_len,
-        const char *row);
+typedef bool (*lkt_search_database_func)(struct lkt_state *srv, size_t c, int id, int id_len, const char *row);
+typedef bool (*lkt_search_sticker_func) (struct lkt_state *srv, size_t c, const char *sticker, const char *type, int uri, int value);
 
-bool database_search_database_init(volatile sqlite3 *db, char *col_name, char *rgx, struct lkt_search *ret);
-bool database_search_queue_init   (volatile sqlite3 *db, char *col_name, char *rgx, struct lkt_search *ret);
+bool database_search_database_init(volatile sqlite3 *db, char *col_name, char *rgx,  struct lkt_search *ret);
+bool database_search_queue_init   (volatile sqlite3 *db, char *col_name, char *rgx,  struct lkt_search *ret);
+bool database_search_sticker_init (volatile sqlite3 *db, char *type,     char *name, struct lkt_search *ret);
 bool database_search_iter(struct lkt_search *item);
 
 /* Next and prev operation on the queue. */
diff --git a/src/database/find.c b/src/database/find.c
index e868700f..5807a541 100644
--- a/src/database/find.c
+++ b/src/database/find.c
@@ -3,6 +3,7 @@
 #include <common/common.h>
 #include <lektor/database.h>
 
+#include <strings.h>
 #include <limits.h>
 #include <stdio.h>
 #include <string.h>
@@ -53,6 +54,39 @@ error:
     return false;
 }
 
+bool
+database_search_sticker_init(volatile sqlite3 *db, char *type, char *name, struct lkt_search *ret)
+{
+    /* No bound checks in strcats, should be fine. Possible SQL injection, depend on the `type`. */
+    static const char *SQL_all_types =
+        "SELECT name, sts.id, value FROM 'stickers' LEFT OUTER JOIN "
+        "( SELECT id, sticker, value FROM 'stickers.song'"
+        "  UNION"
+        "  SELECT id, sticker, value FROM 'stickers.plt'"
+        ") AS sts"
+        "ON sts.sticker = 'stickers'.id";
+    static const char *SQL_one_type =
+            "SELECT name, 'stickers.%s'.id, value "
+            "FROM 'stickers' "
+            "LEFT OUTER JOIN 'stickers' "
+            "ON 'stickers'.id = 'stickers.%s'.sticker";
+    static const char *SQL_check_name = " AND name = ?;";
+    char SQL[LKT_MAX_SQLITE_STATEMENT];
+
+    if (type == NULL)
+        memcpy(SQL, SQL_all_types, strlen(SQL_all_types) + 1);
+    else
+        sprintf(SQL, SQL_one_type, type, type);
+    strcat(SQL, name ? SQL_check_name : ";");
+
+    SQLITE_PREPARE(db, ret->stmt, SQL, error);
+    if (name)
+        SQLITE_BIND_TEXT(db, ret->stmt, 1, name, error)
+        return true;
+error:
+    sqlite3_finalize(ret->stmt);
+    return false;
+}
 
 bool
 database_search_queue_init(volatile sqlite3 *db, char *col_name, char *rgx, struct lkt_search *ret)
-- 
GitLab