]> PatchyGit - patchyircd.git/commitdiff
job: templateize job_password_check
authorEgor <egor@patchysicp.xyz>
Thu, 22 Jan 2026 13:22:47 +0000 (15:22 +0200)
committerEgor <egor@patchysicp.xyz>
Thu, 22 Jan 2026 13:22:47 +0000 (15:22 +0200)
src/irc.cpp
src/job.cpp
src/job.hpp

index c51dff1..97dd0a0 100644 (file)
@@ -386,7 +386,7 @@ int irc_process_line(Client *client, char *source, std::string_view command, int
                                        char *password = strchr(p, '\0')+1;
                                        if (password > client->saslbuf + client->saslbufLen)
                                                goto saslerr;
-                                       job_password_check(client, username, password, "users", [client](int res) {
+                                       job_password_check<"users">(client, username, password, [client](int res) {
                                                if (client->saslusername) {
                                                        if (res == 0) {
                                                                rpl_saslsuccess(), sendbuf(client);
@@ -485,7 +485,7 @@ saslcleanup:
                                memcpy(client->webirchostname, args[2], len);
                                memcpy(client->webirchostname+len, ".xmpp", sizeof(".xmpp"));
                        }
-                       job_password_check(client, args[1], args[0], "webirc", [client](int res) {
+                       job_password_check<"webirc">(client, args[1], args[0], [client](int res) {
                                if (!(client->umode & UMODE_SECURE) || res != 0) {
                                        delete[] client->webircpeername;
                                        client->webircpeername = 0;
@@ -515,7 +515,7 @@ saslcleanup:
                if (argc < 2)
                        return err_needmoreparams(client, command), sendbuf(client), 0;
                stringlower(args[0]);
-               job_password_check(client, args[0], args[1], "ops", [client](int res) {
+               job_password_check<"ops">(client, args[0], args[1], [client](int res) {
                        if (!(client->umode & UMODE_SECURE) || res != 0) {
                                err_passwdmismatch(client), sendbuf(client);
                        } else {
@@ -1226,7 +1226,7 @@ void newUser(Client *client) {
                }
        }
        if (client->username[0] == '~' && client->pass_reg) {
-               job_password_check(client, client->username+1, client->pass_reg, "users", [client](int res) {
+               job_password_check<"users">(client, client->username+1, client->pass_reg, [client](int res) {
                        if (client->passwait) {
                                client->passwait = 0;
                                if (!(client->umode & UMODE_SECURE) || res != 0) {
index 37a45c4..f8730b6 100644 (file)
@@ -118,27 +118,11 @@ struct SecureStringWrapper {
                }
        }
 };
-void job_password_check(Client *client, const char *key, const char *pw, const char *fn, contproc_t&& then)
+static void job_password_check_internal(Client *client, const char *salt, const char *pw, contproc_t&& then)
 {
-       db::Statement stmt;
-       std::string_view salt;
-       if (fn == "ops"sv)
-               stmt = db::disk("SELECT hash FROM ops WHERE account = ?;");
-       else if (fn == "users"sv)
-               stmt = db::disk("SELECT hash FROM users WHERE account = ?;");
-       else if (fn == "webirc"sv)
-               stmt = db::disk("SELECT hash FROM webirc WHERE account = ?;");
-       else
-               goto no_table;
-
-       stmt.bind(1, key);
-       if (stmt.step())
-               salt = stmt.text(0);
-
-no_table:
        // FIXME: make_shared only really needed here cuz std::function wants a copyable object
        // C++23 adds a std::move_only_function
-       job_add(client, [pw=std::make_shared<SecureStringWrapper>(pw), salt=std::make_shared<SecureStringWrapper>(salt.data())]() -> int {
+       job_add(client, [pw=std::make_shared<SecureStringWrapper>(pw), salt=std::make_shared<SecureStringWrapper>(salt)]() -> int {
                if (!*salt)
                        return 1;
                char *hash = password_crypt(*pw, *salt);
@@ -148,3 +132,25 @@ no_table:
                return rv;
        }, std::move(then));
 }
+template<size_t A, size_t B, size_t C>
+consteval static std::array<char, A+B+C-2> concat(const char (&a)[A], const char (&b)[B], const char (&c)[C]) {
+       std::array<char, A+B+C-2> arr;
+       std::copy_n(a, A-1, &arr[0]);
+       std::copy_n(b, B-1, &arr[A-1]);
+       std::copy_n(c, C, &arr[A+B-2]);
+       return arr;
+}
+template<Literal table>
+void job_password_check(Client *client, const char *key, const char *pw, contproc_t&& then)
+{
+       constexpr auto query = concat("SELECT hash FROM ", table.value, " WHERE account = ?;");
+       auto stmt = db::disk(std::string_view(query.data(), query.size()));
+       stmt.bind(1, key);
+       std::string_view salt;
+       if (stmt.step())
+               salt = stmt.text(0);
+       job_password_check_internal(client, salt.data(), pw, std::move(then));
+}
+template void job_password_check<"ops">(Client *client, const char *key, const char *pw, contproc_t&& then);
+template void job_password_check<"users">(Client *client, const char *key, const char *pw, contproc_t&& then);
+template void job_password_check<"webirc">(Client *client, const char *key, const char *pw, contproc_t&& then);
index 490e018..1d27887 100644 (file)
@@ -10,5 +10,14 @@ void job_fini(void);
 void job_process(void);
 void job_add(Client *client, jobproc_t&& job, contproc_t&& then);
 void job_kill(Client *client);
-void job_password_check(Client *client, const char *key, const char *pw, const char *fn, contproc_t&& then);
+template<size_t N>
+struct Literal {
+       char value[N];
+       consteval Literal(const char (&s)[N]) { std::copy_n(s, N, value); }
+};
+template<Literal table>
+void job_password_check(Client *client, const char *key, const char *pw, contproc_t&& then);
+extern template void job_password_check<"ops">(Client *client, const char *key, const char *pw, contproc_t&& then);
+extern template void job_password_check<"users">(Client *client, const char *key, const char *pw, contproc_t&& then);
+extern template void job_password_check<"webirc">(Client *client, const char *key, const char *pw, contproc_t&& then);
 #endif