@(do (defstruct (alias address memo creation-time) nil address memo creation-time (selected nil) (:postinit (alias) (ifa (stringp alias.creation-time) (set it (int-str it))) (ifa (eq alias.address :random) (set it (format nil `~,03s-~,03s-~,04s` (rand 1000) (rand 1000) (rand 10000))))) (:method equal (alias) alias.address) (:method alt-addresses (alias) (list (regsub #/-/ "." alias.address) (regsub #/-/ "_" alias.address))) (:method get-decoded-memo (alias) (url-decode alias.memo)) (:method get-html-memo (alias) (let* ((mem alias.(get-decoded-memo))) (html-encode-with-http mem))) (:method match (alias regex) (or [regex alias.(get-decoded-memo)] [regex alias.address] [regex (time-string-local alias.creation-time date-format)])))) @; @(bind selected-alias-keys nil) @(bind search-query "") @(bind search-regex nil) @; @(define mark-aliases (aliases selected)) @ (do (each ((key selected)) (iflet ((a (find key aliases))) (set a.selected t)))) @(end) @; @(define load-aliases (user aliases)) @ (local time memo) @ (bind lock @(acquire-lock aliases-file)) @ (try) @ (next aliases-file) @ (maybe) @ (skip) # aliases for @user @ (collect :vars (aliases)) # memo @memo # created @time @address: @user @ (bind aliases @(new (alias address memo time))) @ (until) # end @ (end) @ (or) @ (bind aliases nil) @ (end) @ (finally) @ (do (release-lock lock)) @ (end) @ (mark-aliases aliases selected-alias-keys) @(end) @; @(define store-aliases (user aliases)) @ (local before oldaliases after) @ (bind lock @(acquire-lock aliases-file)) @ (try) @ (next aliases-file) @ (collect) @before @ (last) # aliases for @user @ (end) @ (collect) @oldaliases @ (until) # aliases for @(skip) @ (end) @ (collect) @after @ (end) @ (output `@{aliases-file}.tmp` :named out) @ (repeat) @before @ (end) # aliases for @user @ (repeat :vars (aliases)) # memo @{aliases.memo} # created @{aliases.creation-time} @{aliases.address}: @user @ (repeat :vars ((alt-ali aliases.(alt-addresses)))) @{alt-ali}: @user @ (end) @ (end) # end @ (repeat) @after @ (end) @ (end) @ (do (let ((backup-stamp (time-string-local (time) "%Y%m%d-%H%M"))) (each* ((j (range 30 0)) (i (rest j))) (if (path-file-p `@{aliases-file}.@i`) (rename-path `@{aliases-file}.@i` `@{aliases-file}.@j`))) (rename-path aliases-file `@{aliases-file}.0`) (rename-path `@{aliases-file}.tmp` aliases-file))) @ (finally) @ (do (release-lock lock)) @ (end) @(end) @; @(define update-aliases (userid postdata)) @ (local memo aliases selected) @ (bind url-args @(split-str postdata "&")) @ (next :list url-args) @ (collect :vars (selected)) chkbox-@selected=on @ (end) @ (set selected-alias-keys selected) @ (load-aliases userid aliases) @ (next :list url-args) @ (gather) memo=@memo query=@query @ (end) @ (set search-query @(url-decode query)) @ (set search-regex @(if (equal search-query "") nil (ignerr (regex-compile search-query)))) @ (next :list url-args) @ (cases) @ (skip) create=@(skip) @ (do (push (new (alias :random memo (time))) aliases)) @ (store-aliases userid aliases) @ (or) @ (skip) move-up=@(skip) @ (store-aliases userid @[move-up aliases selected]) @ (or) @ (skip) move-down=@(skip) @ (store-aliases userid @[move-down aliases selected]) @ (or) @ (skip) move-top=@(skip) @ (store-aliases userid @[move-front aliases selected]) @ (or) @ (skip) move-bot=@(skip) @ (store-aliases userid @[move-tail aliases selected]) @ (or) @ (skip) delete=@(skip) @ (store-aliases userid @[set-diff aliases selected equal]) @ (or) @ (accept) @ (end) @(end) @; @(define update-memo (userid edit-alias new-memo)) @ (local aliases) @ (load-aliases userid aliases) @ (bind existing-alias @(find edit-alias aliases)) @ (if existing-alias) @ (do (set existing-alias.memo new-memo)) @ (store-aliases userid aliases) @ (alias-list-form userid) @ (else) @ (error-form "Not Found" `Alias @{edit-alias} doesn't seem to exist!`) @ (end) @(end)