-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathiicl.lisp
190 lines (170 loc) · 5.8 KB
/
iicl.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
(ql:quickload :split-sequence)
(ql:quickload :hunchentoot)
(ql:quickload :cl-base64)
(ql:quickload :flexi-streams)
(ql:quickload :cl-ppcre)
(load "lib/txtbase.lisp")
(load "lib/filters.lisp")
(defpackage :iicl
(:use :common-lisp
:split-sequence
:hunchentoot
:cl-base64
:flexi-streams
:cl-ppcre
:txt-base
:ii-filters)
(:export :load-config
:sublist))
(in-package :iicl)
(defvar *nodename* "")
(defvar *echoareas* ())
(defun load-config ()
"Load data from the configuration file."
(setf *echoareas* nil)
(with-open-file (in "iicl.cfg")
(loop for line = (read-line in nil)
while line do
(let ((param (split-sequence #\space line)))
(if (>= (length param) 2)
(cond
((equal (first param) "nodename")
(setf *nodename* (second param)))
((equal (first param) "echo")
(push `(,(second param) ,(format nil "~{~a~^ ~}" (cdr (cdr param)))) *echoareas*)))))))
(setf *echoareas* (reverse *echoareas*)))
(setf *dispatch-table*
`(,(create-prefix-dispatcher "/" 'index)))
(defun echolist ()
"/list.txt"
(setf (content-type*) "text/plain")
(format nil "~{~{~a:~a~}~%~}" *echoareas*))
(defun caesium ()
"/x/caesium for caesium client"
(setf (content-type*) "text/plain")
(format nil "~{echo ~{~a ~a~}~%~}" *echoareas*))
(defun small-list ()
"/x/small-echolist"
(setf (content-type*) "text/plain")
(format nil "~{~{~a ~*~}~%~}" *echoareas*))
(defun blacklist ()
"/blacklist.txt"
(setf (content-type*) "text/plain")
(let (lines)
(with-open-file (in "blacklist.txt")
(loop for line = (read-line in nil)
while line do
(push line lines)))
(format nil "~{~a~%~}" (reverse lines))))
(defun echoareas (echoarea)
"/e/"
(setf (content-type*) "text/plain")
(format nil "~{~a~%~}" (get-echoarea echoarea)))
(defun message (msgid)
"/m/"
(setf (content-type*) "text/plain")
(if (msg-filter msgid)
(let ((msg (get-message msgid)))
(if msg
(format nil "~{~a~%~}" msg)
(format nil "~a" "")))))
;;;
;;; Магия подсписков
;;;
(defun sublist (s e l)
(let (ret)
(if (or (not s) (not e))
;; Если не задан один из параметров
(progn
(when (and s (not e))
;; Задан только начальный параметр
(setf e s)
(setf s 1))
(when (and e (not s))
;; Задан только конечный параметр
(setf s (+ (- (length l) e) 1))))
(progn
;; Если начальный параметр меньше нуля
(if (< s 0)
(setf s (+ (length l) s 1)))
;; Если сумма параметров больше длины списка
(if (> (- (+ s e) 2) (length l))
(setf e (+ (- (length l) s) 1)))))
;; Если начальный параметр указывает за пределы списка
(if (or (< s 0) (> s (length l)))
(setf s 1))
;; Если конечный параметр указывает за пределы списка
(if (or (< e 0) (> e (length l)))
(setf e (length l)))
(loop for i from (- s 1) to (- (+ s e) 2) do
(push (nth i l) ret))
(reverse ret)))
(defun u-echoareas (echoareas)
"/u/e/"
(setf (content-type*) "text/plain")
(let (ret lines limits)
(when (find #\: (car (last echoareas)) :test 'equal)
(setf limits (split-sequence #\: (car (last echoareas))))
(setf echoareas (reverse (cdr (reverse echoareas)))))
(dolist (echoarea echoareas)
(setf ret (append ret (list echoarea)))
(setf lines (get-echoarea echoarea))
(if limits
(let (s e)
(setf s (parse-integer (first limits) :junk-allowed t))
(setf e (parse-integer (second limits) :junk-allowed t))
(setf lines (sublist s e lines))))
(setf ret (append ret lines)))
(format nil "~{~a~%~}" ret)))
(defun bundle (msgids)
"/u/m/"
(setf (content-type*) "text/plain")
(let (lines msg)
(dolist (msgid msgids)
(when (and
(msg-filter msgid)
(probe-file (make-pathname :name (concatenate 'string "msg/" msgid))))
(setf msg (format nil "~{~a~%~}" (get-message msgid)))
(push (concatenate 'string msgid ":"
(usb8-array-to-base64-string
(string-to-octets msg :external-format :utf8)))
lines)))
(format nil "~{~a~%~}" (reverse lines))))
(defun echoareas-count (echoareas)
(setf (content-type*) "text/plain")
(let (counts)
(dolist (echoarea echoareas)
(push (concatenate 'string echoarea ":" (write-to-string (length (get-echoarea echoarea)))) counts))
(format nil "~{~a~%~}" (reverse counts))))
(defun features ()
(setf (content-type*) "text/plain")
(format nil "~{~a~%~}" '("u/e" "list.txt" "blacklist.txt" "x/c" "x/file" "x/small-echolist" "x/caesium")))
(defun index()
"Dispatcher for using beautyfull URLs."
(let ((request (split-sequence #\/ (request-uri *request*))))
(cond
((equal (second request) "list.txt")
(echolist))
((and (equal (second request) "x") (equal (third request) "caesium"))
(caesium))
((and (equal (second request) "x") (equal (third request) "small-echolist"))
(small-list))
((equal (second request) "blacklist.txt")
(blacklist))
((equal (second request) "e")
(echoareas (third request)))
((equal (second request) "m")
(message (third request)))
((and (equal (second request) "u") (equal (third request) "e"))
(u-echoareas (cdddr request)))
((and (equal (second request) "u") (equal (third request) "m"))
(bundle (cdddr request)))
((and (equal (second request) "x") (equal (third request) "c"))
(echoareas-count (cdddr request)))
((and (equal (second request) "x") (equal (third request) "features"))
(features)))))
(defvar *acceptor*
(make-instance 'easy-acceptor :port 4242))
(load-config)
(start *acceptor*)
(format t "iicl started at address http://127.0.0.1:4242")