summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/kike.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/kike.c b/src/kike.c
index 7c151e4..d5a777c 100644
--- a/src/kike.c
+++ b/src/kike.c
@@ -89,6 +89,93 @@ setup_signal_handlers (void)
}
}
+// --- IRC token validation ----------------------------------------------------
+
+enum validation_result
+{
+ VALIDATION_OK,
+ VALIDATION_ERROR_EMPTY,
+ VALIDATION_ERROR_TOO_LONG,
+ VALIDATION_ERROR_INVALID
+};
+
+// Everything as per RFC 2812
+#define IRC_NICKNAME_MAX 9
+#define IRC_HOSTNAME_MAX 63
+
+// Anything to keep it as short as possible
+#define SN "[0-9A-Za-z][-0-9A-Za-z]*[0-9A-Za-z]*"
+#define N4 "[0-9]{1,3}"
+#define N6 "[0-9ABCDEFabcdef]{1,}"
+
+#define LE "A-Za-z"
+#define SP "\\[\\]\\\\`_^{|}"
+
+static const char *
+irc_validate_to_str (enum validation_result result)
+{
+ switch (result)
+ {
+ case VALIDATION_OK: return "success";
+ case VALIDATION_ERROR_EMPTY: return "the value is empty";
+ case VALIDATION_ERROR_INVALID: return "invalid format";
+ case VALIDATION_ERROR_TOO_LONG: return "the value is too long";
+ default: abort ();
+ }
+}
+
+// TODO: at least cache the resulting `regex_t' in a `struct str_map'
+
+static enum validation_result
+irc_validate_hostname (const char *hostname)
+{
+ if (!*hostname)
+ return VALIDATION_ERROR_EMPTY;
+ if (!regex_match ("^" SN "(\\." SN ")*$", hostname, NULL))
+ return VALIDATION_ERROR_INVALID;
+ if (strlen (hostname) > IRC_HOSTNAME_MAX)
+ return VALIDATION_ERROR_TOO_LONG;
+ return VALIDATION_OK;
+}
+
+static bool
+irc_is_valid_hostaddr (const char *hostaddr)
+{
+ if (regex_match ("^" N4 "\\." N4 "\\." N4 "\\." N4 "$", hostaddr, NULL)
+ || regex_match ("^" N6 ":" N6 ":" N6 ":" N6 ":"
+ N6 ":" N6 ":" N6 ":" N6 "$", hostaddr, NULL)
+ || regex_match ("^0:0:0:0:0:(0|[Ff]{4}):"
+ N4 "\\." N4 "\\." N4 "\\." N4 "$", hostaddr, NULL))
+ return true;
+ return false;
+}
+
+static bool
+irc_is_valid_host (const char *host)
+{
+ return irc_validate_hostname (host) == VALIDATION_OK
+ || irc_is_valid_hostaddr (host);
+}
+
+static bool
+irc_validate_nickname (const char *nickname)
+{
+ if (!*nickname)
+ return VALIDATION_ERROR_EMPTY;
+ if (!regex_match ("^[" LE SP "][-0-9" LE SP "]*$", nickname, NULL))
+ return VALIDATION_ERROR_INVALID;
+ if (strlen (nickname) > IRC_NICKNAME_MAX)
+ return VALIDATION_ERROR_TOO_LONG;
+ return VALIDATION_OK;
+}
+
+#undef SN
+#undef N4
+#undef N6
+
+#undef LE
+#undef SP
+
// --- Application data --------------------------------------------------------
enum