#lang racket

(define memory (make-vector 1024 #\nul))

(define (write-to-memory! str memory-start-index)
  (define str-length (string-length str))
  (define (loop str-index)
    (when (< str-index str-length)
        (vector-set! memory (+ memory-start-index str-index) (string-ref str str-index))
        (loop (+ str-index 1))))
  (loop 0))

(define (init-memory!)
  (write-to-memory! "admin\0" 8)
  (write-to-memory! "<PASSWORD>\0" 14))

(init-memory!)

(define (read-from-memory memory-start-index)
  (define (loop str curr-index)
    (if (equal? (vector-ref memory curr-index) #\nul)
      str
      (loop (string-append str (string (vector-ref memory curr-index))) (+ curr-index 1))))
  (loop "" memory-start-index))

(define (find-in-memory value)
  (define (loop memory-index value-index)

    (cond
      ((>= memory-index (vector-length memory))
       #f)
      ((>= value-index (string-length value))
       (if (equal? (vector-ref memory memory-index) #\nul)
         (- memory-index (string-length value))
         (loop (+ memory-index 1) 0)))
      ((equal? (vector-ref memory memory-index) (string-ref value value-index))
       (loop (+ memory-index 1) (+ value-index 1)))
      (else
        (loop (+ memory-index 1) 0))))
  (loop 8 0))

(define (find-next-value-in-memory-after start-memory-index-previous)
  (define (loop memory-index)
    (if (equal? (vector-ref memory memory-index) #\nul)
      (+ memory-index 1)
      (loop (+ memory-index 1))))
  (loop start-memory-index-previous))

(define (get-password-for username)
  (define username-in-memory (find-in-memory username))
  (if username-in-memory
    (read-from-memory (find-next-value-in-memory-after username-in-memory))
    #f))

(define (receive-login-attempt-username username)
  (write-to-memory! username 0))

(define (passwords-match? received-password)
  (define login-username (read-from-memory 0))
  (define password-in-memory (get-password-for login-username))
  (equal? received-password password-in-memory))

(define (accept-null-termination str)
  (string-replace str "\\0" "\0"))

; Using \0 in your username or password string will be interpreted as the null character. Surely this is very safe and secure and will certainly not cause potential leaks

(define (main)
  (display "username: ")
  (receive-login-attempt-username (accept-null-termination (read-line (current-input-port) 'any)))
  (display "password: ")
  (if (passwords-match? (read-line (current-input-port) 'any))
    (flag-or-something-idk)
    (display "Incorrect password!!!1!! >:(")))

(main)
