';
57 | $seqs = DB::query("SELECT *,
58 | (SELECT COUNT(*) FROM libseq WHERE libseq.seqid=libseqname.SeqId) cnt
59 | FROM libseqname $filter4 ORDER BY seqname");
60 |
61 | while ($s = $seqs->fetch_object()) {
62 | if ($s->cnt > 0) {
63 | echo "
";
64 |
65 | echo "SeqId'\">";
66 |
67 | echo "$s->SeqName ";
68 |
69 |
70 |
71 | echo "$s->cnt ";
72 |
73 | echo " ";
74 |
75 | echo "
";
76 | }
77 | }
78 | */
79 | ?>
80 |
--------------------------------------------------------------------------------
/application/opds/search_book.php:
--------------------------------------------------------------------------------
1 | ';
4 | echo <<< _XML
5 |
tag:root:authors
6 | Поиск по книгам
7 | $cdt
8 | /favicon.ico
9 |
10 |
11 |
12 | _XML;
13 |
14 | $q = $_GET['q'];
15 | $get = "?q=$q";
16 |
17 | if ($q == '') {
18 | die(':(');
19 | }
20 |
21 | //$filter2 = "AND libbook.Title LIKE " . DB::es('%' . $q . '%');
22 |
23 | $books = $dbh->prepare("SELECT DISTINCT BookId, libbook.Title as BookTitle,
24 | (SELECT Body FROM libbannotations WHERE BookId=libbook.BookId LIMIT 1) as Body
25 | FROM libbook
26 | JOIN libgenre USING(BookId)
27 | WHERE deleted='0' AND libbook.Title LIKE :q
28 | GROUP BY BookId, BookTitle, Body
29 | LIMIT 100");
30 | $param = '%'.$q.'%';
31 | $books->bindParam(":q", $param);
32 | $books->execute();
33 |
34 | while ($b = $books->fetchObject()) {
35 | echo " $cdt ";
36 | echo " tag:book:$b->bookid ";
37 | echo " " . htmlspecialchars($b->booktitle) . " ";
38 |
39 | $as = '';
40 | $authors = $dbh->query("SELECT lastname, firstname, middlename FROM libavtorname, libavtor WHERE libavtor.BookId=$b->bookid AND libavtor.AvtorId=libavtorname.AvtorId ORDER BY LastName");
41 | while ($a = $authors->fetchObject()) {
42 | $as .= $a->lastname . " " . $a->firstname . " " . $a->middlename . ", ";
43 | }
44 | $authors = null;
45 |
46 | echo " $as ";
47 | echo " /a/id ";
48 | echo " ";
49 | echo " " . htmlspecialchars($b->body ?? '') . " ";
50 |
51 | echo " ";
52 | echo " ";
53 | echo " ";
54 |
55 | echo " \n";
56 | }
57 | $books = null;
58 | ?>
59 |
--------------------------------------------------------------------------------
/application/opds/sequencesindex.php:
--------------------------------------------------------------------------------
1 | ';
13 | echo <<< _XML
14 |
tag:root:authors
15 | Книги по сериям
16 | $cdt
17 | /favicon.ico
18 |
19 |
20 | \n
21 | _XML;
22 |
23 | $query="
24 | SELECT UPPER(SUBSTR(SeqName, 1, ".($length_letters + 1).")) as alpha, COUNT(*) as cnt
25 | FROM libseqname
26 | WHERE UPPER(SUBSTR(SeqName, 1, ".($length_letters + 1).")) SIMILAR TO :pattern
27 | GROUP BY UPPER(SUBSTR(SeqName, 1, ".($length_letters + 1)."))
28 | ORDER BY alpha";
29 | $ai = $dbh->prepare($query);
30 | $bindparam1 = $letters."_";
31 | $ai->bindParam(":pattern",$bindparam1);
32 | $ai->execute();
33 | while ($ach = $ai->fetchObject()) {
34 | if ($ach->cnt>30) {
35 | echo "\n\n $cdt ";
36 | echo "tag:sequences:".urlencode($ach->alpha)." \n";
37 | echo "".htmlspecialchars($ach->alpha)." \n";
38 | echo "$ach->cnt книжных серий на ".htmlspecialchars($ach->alpha)." \n";
39 | echo " \n";
40 | echo " ";
41 | } else {
42 | // list individual serie
43 | $sq = $dbh->prepare("SELECT SeqName, SeqId
44 | from libseqname
45 | where UPPER(SUBSTR(SeqName, 1, ".($length_letters + 1).")) = :pattern
46 | ORDER BY UPPER(SeqName)");
47 | $sq->bindParam(":pattern",$ach->alpha);
48 | $sq->execute();
49 | while($s = $sq->fetchObject()){
50 | echo "\n\n $cdt ";
51 | echo "tag:sequence:$s->seqid \n";
52 | echo "". htmlspecialchars($s->seqname)." \n";
53 | echo " ";
54 | echo " ";
55 | echo " ";
56 | }
57 | $sq = null;
58 | }
59 | }
60 | echo ' ';
61 | ?>
--------------------------------------------------------------------------------
/application/public/bootstrap/css/bootstrap-reboot.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Reboot v5.1.3 (https://getbootstrap.com/)
3 | * Copyright 2011-2021 The Bootstrap Authors
4 | * Copyright 2011-2021 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
7 | */
8 | :root {
9 | --bs-blue: #0d6efd;
10 | --bs-indigo: #6610f2;
11 | --bs-purple: #6f42c1;
12 | --bs-pink: #d63384;
13 | --bs-red: #dc3545;
14 | --bs-orange: #fd7e14;
15 | --bs-yellow: #ffc107;
16 | --bs-green: #198754;
17 | --bs-teal: #20c997;
18 | --bs-cyan: #0dcaf0;
19 | --bs-white: #fff;
20 | --bs-gray: #6c757d;
21 | --bs-gray-dark: #343a40;
22 | --bs-gray-100: #f8f9fa;
23 | --bs-gray-200: #e9ecef;
24 | --bs-gray-300: #dee2e6;
25 | --bs-gray-400: #ced4da;
26 | --bs-gray-500: #adb5bd;
27 | --bs-gray-600: #6c757d;
28 | --bs-gray-700: #495057;
29 | --bs-gray-800: #343a40;
30 | --bs-gray-900: #212529;
31 | --bs-primary: #0d6efd;
32 | --bs-secondary: #6c757d;
33 | --bs-success: #198754;
34 | --bs-info: #0dcaf0;
35 | --bs-warning: #ffc107;
36 | --bs-danger: #dc3545;
37 | --bs-light: #f8f9fa;
38 | --bs-dark: #212529;
39 | --bs-primary-rgb: 13, 110, 253;
40 | --bs-secondary-rgb: 108, 117, 125;
41 | --bs-success-rgb: 25, 135, 84;
42 | --bs-info-rgb: 13, 202, 240;
43 | --bs-warning-rgb: 255, 193, 7;
44 | --bs-danger-rgb: 220, 53, 69;
45 | --bs-light-rgb: 248, 249, 250;
46 | --bs-dark-rgb: 33, 37, 41;
47 | --bs-white-rgb: 255, 255, 255;
48 | --bs-black-rgb: 0, 0, 0;
49 | --bs-body-color-rgb: 33, 37, 41;
50 | --bs-body-bg-rgb: 255, 255, 255;
51 | --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
52 | --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
53 | --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
54 | --bs-body-font-family: var(--bs-font-sans-serif);
55 | --bs-body-font-size: 1rem;
56 | --bs-body-font-weight: 400;
57 | --bs-body-line-height: 1.5;
58 | --bs-body-color: #212529;
59 | --bs-body-bg: #fff;
60 | }
61 |
62 | *,
63 | *::before,
64 | *::after {
65 | box-sizing: border-box;
66 | }
67 |
68 | @media (prefers-reduced-motion: no-preference) {
69 | :root {
70 | scroll-behavior: smooth;
71 | }
72 | }
73 |
74 | body {
75 | margin: 0;
76 | font-family: var(--bs-body-font-family);
77 | font-size: var(--bs-body-font-size);
78 | font-weight: var(--bs-body-font-weight);
79 | line-height: var(--bs-body-line-height);
80 | color: var(--bs-body-color);
81 | text-align: var(--bs-body-text-align);
82 | background-color: var(--bs-body-bg);
83 | -webkit-text-size-adjust: 100%;
84 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
85 | }
86 |
87 | hr {
88 | margin: 1rem 0;
89 | color: inherit;
90 | background-color: currentColor;
91 | border: 0;
92 | opacity: 0.25;
93 | }
94 |
95 | hr:not([size]) {
96 | height: 1px;
97 | }
98 |
99 | h6, h5, h4, h3, h2, h1 {
100 | margin-top: 0;
101 | margin-bottom: 0.5rem;
102 | font-weight: 500;
103 | line-height: 1.2;
104 | }
105 |
106 | h1 {
107 | font-size: calc(1.375rem + 1.5vw);
108 | }
109 | @media (min-width: 1200px) {
110 | h1 {
111 | font-size: 2.5rem;
112 | }
113 | }
114 |
115 | h2 {
116 | font-size: calc(1.325rem + 0.9vw);
117 | }
118 | @media (min-width: 1200px) {
119 | h2 {
120 | font-size: 2rem;
121 | }
122 | }
123 |
124 | h3 {
125 | font-size: calc(1.3rem + 0.6vw);
126 | }
127 | @media (min-width: 1200px) {
128 | h3 {
129 | font-size: 1.75rem;
130 | }
131 | }
132 |
133 | h4 {
134 | font-size: calc(1.275rem + 0.3vw);
135 | }
136 | @media (min-width: 1200px) {
137 | h4 {
138 | font-size: 1.5rem;
139 | }
140 | }
141 |
142 | h5 {
143 | font-size: 1.25rem;
144 | }
145 |
146 | h6 {
147 | font-size: 1rem;
148 | }
149 |
150 | p {
151 | margin-top: 0;
152 | margin-bottom: 1rem;
153 | }
154 |
155 | abbr[title],
156 | abbr[data-bs-original-title] {
157 | -webkit-text-decoration: underline dotted;
158 | text-decoration: underline dotted;
159 | cursor: help;
160 | -webkit-text-decoration-skip-ink: none;
161 | text-decoration-skip-ink: none;
162 | }
163 |
164 | address {
165 | margin-bottom: 1rem;
166 | font-style: normal;
167 | line-height: inherit;
168 | }
169 |
170 | ol,
171 | ul {
172 | padding-left: 2rem;
173 | }
174 |
175 | ol,
176 | ul,
177 | dl {
178 | margin-top: 0;
179 | margin-bottom: 1rem;
180 | }
181 |
182 | ol ol,
183 | ul ul,
184 | ol ul,
185 | ul ol {
186 | margin-bottom: 0;
187 | }
188 |
189 | dt {
190 | font-weight: 700;
191 | }
192 |
193 | dd {
194 | margin-bottom: 0.5rem;
195 | margin-left: 0;
196 | }
197 |
198 | blockquote {
199 | margin: 0 0 1rem;
200 | }
201 |
202 | b,
203 | strong {
204 | font-weight: bolder;
205 | }
206 |
207 | small {
208 | font-size: 0.875em;
209 | }
210 |
211 | mark {
212 | padding: 0.2em;
213 | background-color: #fcf8e3;
214 | }
215 |
216 | sub,
217 | sup {
218 | position: relative;
219 | font-size: 0.75em;
220 | line-height: 0;
221 | vertical-align: baseline;
222 | }
223 |
224 | sub {
225 | bottom: -0.25em;
226 | }
227 |
228 | sup {
229 | top: -0.5em;
230 | }
231 |
232 | a {
233 | color: #0d6efd;
234 | text-decoration: underline;
235 | }
236 | a:hover {
237 | color: #0a58ca;
238 | }
239 |
240 | a:not([href]):not([class]), a:not([href]):not([class]):hover {
241 | color: inherit;
242 | text-decoration: none;
243 | }
244 |
245 | pre,
246 | code,
247 | kbd,
248 | samp {
249 | font-family: var(--bs-font-monospace);
250 | font-size: 1em;
251 | direction: ltr /* rtl:ignore */;
252 | unicode-bidi: bidi-override;
253 | }
254 |
255 | pre {
256 | display: block;
257 | margin-top: 0;
258 | margin-bottom: 1rem;
259 | overflow: auto;
260 | font-size: 0.875em;
261 | }
262 | pre code {
263 | font-size: inherit;
264 | color: inherit;
265 | word-break: normal;
266 | }
267 |
268 | code {
269 | font-size: 0.875em;
270 | color: #d63384;
271 | word-wrap: break-word;
272 | }
273 | a > code {
274 | color: inherit;
275 | }
276 |
277 | kbd {
278 | padding: 0.2rem 0.4rem;
279 | font-size: 0.875em;
280 | color: #fff;
281 | background-color: #212529;
282 | border-radius: 0.2rem;
283 | }
284 | kbd kbd {
285 | padding: 0;
286 | font-size: 1em;
287 | font-weight: 700;
288 | }
289 |
290 | figure {
291 | margin: 0 0 1rem;
292 | }
293 |
294 | img,
295 | svg {
296 | vertical-align: middle;
297 | }
298 |
299 | table {
300 | caption-side: bottom;
301 | border-collapse: collapse;
302 | }
303 |
304 | caption {
305 | padding-top: 0.5rem;
306 | padding-bottom: 0.5rem;
307 | color: #6c757d;
308 | text-align: left;
309 | }
310 |
311 | th {
312 | text-align: inherit;
313 | text-align: -webkit-match-parent;
314 | }
315 |
316 | thead,
317 | tbody,
318 | tfoot,
319 | tr,
320 | td,
321 | th {
322 | border-color: inherit;
323 | border-style: solid;
324 | border-width: 0;
325 | }
326 |
327 | label {
328 | display: inline-block;
329 | }
330 |
331 | button {
332 | border-radius: 0;
333 | }
334 |
335 | button:focus:not(:focus-visible) {
336 | outline: 0;
337 | }
338 |
339 | input,
340 | button,
341 | select,
342 | optgroup,
343 | textarea {
344 | margin: 0;
345 | font-family: inherit;
346 | font-size: inherit;
347 | line-height: inherit;
348 | }
349 |
350 | button,
351 | select {
352 | text-transform: none;
353 | }
354 |
355 | [role=button] {
356 | cursor: pointer;
357 | }
358 |
359 | select {
360 | word-wrap: normal;
361 | }
362 | select:disabled {
363 | opacity: 1;
364 | }
365 |
366 | [list]::-webkit-calendar-picker-indicator {
367 | display: none;
368 | }
369 |
370 | button,
371 | [type=button],
372 | [type=reset],
373 | [type=submit] {
374 | -webkit-appearance: button;
375 | }
376 | button:not(:disabled),
377 | [type=button]:not(:disabled),
378 | [type=reset]:not(:disabled),
379 | [type=submit]:not(:disabled) {
380 | cursor: pointer;
381 | }
382 |
383 | ::-moz-focus-inner {
384 | padding: 0;
385 | border-style: none;
386 | }
387 |
388 | textarea {
389 | resize: vertical;
390 | }
391 |
392 | fieldset {
393 | min-width: 0;
394 | padding: 0;
395 | margin: 0;
396 | border: 0;
397 | }
398 |
399 | legend {
400 | float: left;
401 | width: 100%;
402 | padding: 0;
403 | margin-bottom: 0.5rem;
404 | font-size: calc(1.275rem + 0.3vw);
405 | line-height: inherit;
406 | }
407 | @media (min-width: 1200px) {
408 | legend {
409 | font-size: 1.5rem;
410 | }
411 | }
412 | legend + * {
413 | clear: left;
414 | }
415 |
416 | ::-webkit-datetime-edit-fields-wrapper,
417 | ::-webkit-datetime-edit-text,
418 | ::-webkit-datetime-edit-minute,
419 | ::-webkit-datetime-edit-hour-field,
420 | ::-webkit-datetime-edit-day-field,
421 | ::-webkit-datetime-edit-month-field,
422 | ::-webkit-datetime-edit-year-field {
423 | padding: 0;
424 | }
425 |
426 | ::-webkit-inner-spin-button {
427 | height: auto;
428 | }
429 |
430 | [type=search] {
431 | outline-offset: -2px;
432 | -webkit-appearance: textfield;
433 | }
434 |
435 | /* rtl:raw:
436 | [type="tel"],
437 | [type="url"],
438 | [type="email"],
439 | [type="number"] {
440 | direction: ltr;
441 | }
442 | */
443 | ::-webkit-search-decoration {
444 | -webkit-appearance: none;
445 | }
446 |
447 | ::-webkit-color-swatch-wrapper {
448 | padding: 0;
449 | }
450 |
451 | ::-webkit-file-upload-button {
452 | font: inherit;
453 | }
454 |
455 | ::file-selector-button {
456 | font: inherit;
457 | }
458 |
459 | ::-webkit-file-upload-button {
460 | font: inherit;
461 | -webkit-appearance: button;
462 | }
463 |
464 | output {
465 | display: inline-block;
466 | }
467 |
468 | iframe {
469 | border: 0;
470 | }
471 |
472 | summary {
473 | display: list-item;
474 | cursor: pointer;
475 | }
476 |
477 | progress {
478 | vertical-align: baseline;
479 | }
480 |
481 | [hidden] {
482 | display: none !important;
483 | }
484 |
485 | /*# sourceMappingURL=bootstrap-reboot.css.map */
--------------------------------------------------------------------------------
/application/public/bootstrap/css/bootstrap-reboot.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Reboot v5.1.3 (https://getbootstrap.com/)
3 | * Copyright 2011-2021 The Bootstrap Authors
4 | * Copyright 2011-2021 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
7 | */:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-primary-rgb:13,110,253;--bs-secondary-rgb:108,117,125;--bs-success-rgb:25,135,84;--bs-info-rgb:13,202,240;--bs-warning-rgb:255,193,7;--bs-danger-rgb:220,53,69;--bs-light-rgb:248,249,250;--bs-dark-rgb:33,37,41;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-body-color-rgb:33,37,41;--bs-body-bg-rgb:255,255,255;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#212529;--bs-body-bg:#fff}*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:var(--bs-font-monospace);font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::-webkit-file-upload-button{font:inherit}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}
8 | /*# sourceMappingURL=bootstrap-reboot.min.css.map */
--------------------------------------------------------------------------------
/application/public/bootstrap/css/bootstrap-reboot.rtl.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Reboot v5.1.3 (https://getbootstrap.com/)
3 | * Copyright 2011-2021 The Bootstrap Authors
4 | * Copyright 2011-2021 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
7 | */
8 | :root {
9 | --bs-blue: #0d6efd;
10 | --bs-indigo: #6610f2;
11 | --bs-purple: #6f42c1;
12 | --bs-pink: #d63384;
13 | --bs-red: #dc3545;
14 | --bs-orange: #fd7e14;
15 | --bs-yellow: #ffc107;
16 | --bs-green: #198754;
17 | --bs-teal: #20c997;
18 | --bs-cyan: #0dcaf0;
19 | --bs-white: #fff;
20 | --bs-gray: #6c757d;
21 | --bs-gray-dark: #343a40;
22 | --bs-gray-100: #f8f9fa;
23 | --bs-gray-200: #e9ecef;
24 | --bs-gray-300: #dee2e6;
25 | --bs-gray-400: #ced4da;
26 | --bs-gray-500: #adb5bd;
27 | --bs-gray-600: #6c757d;
28 | --bs-gray-700: #495057;
29 | --bs-gray-800: #343a40;
30 | --bs-gray-900: #212529;
31 | --bs-primary: #0d6efd;
32 | --bs-secondary: #6c757d;
33 | --bs-success: #198754;
34 | --bs-info: #0dcaf0;
35 | --bs-warning: #ffc107;
36 | --bs-danger: #dc3545;
37 | --bs-light: #f8f9fa;
38 | --bs-dark: #212529;
39 | --bs-primary-rgb: 13, 110, 253;
40 | --bs-secondary-rgb: 108, 117, 125;
41 | --bs-success-rgb: 25, 135, 84;
42 | --bs-info-rgb: 13, 202, 240;
43 | --bs-warning-rgb: 255, 193, 7;
44 | --bs-danger-rgb: 220, 53, 69;
45 | --bs-light-rgb: 248, 249, 250;
46 | --bs-dark-rgb: 33, 37, 41;
47 | --bs-white-rgb: 255, 255, 255;
48 | --bs-black-rgb: 0, 0, 0;
49 | --bs-body-color-rgb: 33, 37, 41;
50 | --bs-body-bg-rgb: 255, 255, 255;
51 | --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
52 | --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
53 | --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
54 | --bs-body-font-family: var(--bs-font-sans-serif);
55 | --bs-body-font-size: 1rem;
56 | --bs-body-font-weight: 400;
57 | --bs-body-line-height: 1.5;
58 | --bs-body-color: #212529;
59 | --bs-body-bg: #fff;
60 | }
61 |
62 | *,
63 | *::before,
64 | *::after {
65 | box-sizing: border-box;
66 | }
67 |
68 | @media (prefers-reduced-motion: no-preference) {
69 | :root {
70 | scroll-behavior: smooth;
71 | }
72 | }
73 |
74 | body {
75 | margin: 0;
76 | font-family: var(--bs-body-font-family);
77 | font-size: var(--bs-body-font-size);
78 | font-weight: var(--bs-body-font-weight);
79 | line-height: var(--bs-body-line-height);
80 | color: var(--bs-body-color);
81 | text-align: var(--bs-body-text-align);
82 | background-color: var(--bs-body-bg);
83 | -webkit-text-size-adjust: 100%;
84 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
85 | }
86 |
87 | hr {
88 | margin: 1rem 0;
89 | color: inherit;
90 | background-color: currentColor;
91 | border: 0;
92 | opacity: 0.25;
93 | }
94 |
95 | hr:not([size]) {
96 | height: 1px;
97 | }
98 |
99 | h6, h5, h4, h3, h2, h1 {
100 | margin-top: 0;
101 | margin-bottom: 0.5rem;
102 | font-weight: 500;
103 | line-height: 1.2;
104 | }
105 |
106 | h1 {
107 | font-size: calc(1.375rem + 1.5vw);
108 | }
109 | @media (min-width: 1200px) {
110 | h1 {
111 | font-size: 2.5rem;
112 | }
113 | }
114 |
115 | h2 {
116 | font-size: calc(1.325rem + 0.9vw);
117 | }
118 | @media (min-width: 1200px) {
119 | h2 {
120 | font-size: 2rem;
121 | }
122 | }
123 |
124 | h3 {
125 | font-size: calc(1.3rem + 0.6vw);
126 | }
127 | @media (min-width: 1200px) {
128 | h3 {
129 | font-size: 1.75rem;
130 | }
131 | }
132 |
133 | h4 {
134 | font-size: calc(1.275rem + 0.3vw);
135 | }
136 | @media (min-width: 1200px) {
137 | h4 {
138 | font-size: 1.5rem;
139 | }
140 | }
141 |
142 | h5 {
143 | font-size: 1.25rem;
144 | }
145 |
146 | h6 {
147 | font-size: 1rem;
148 | }
149 |
150 | p {
151 | margin-top: 0;
152 | margin-bottom: 1rem;
153 | }
154 |
155 | abbr[title],
156 | abbr[data-bs-original-title] {
157 | -webkit-text-decoration: underline dotted;
158 | text-decoration: underline dotted;
159 | cursor: help;
160 | -webkit-text-decoration-skip-ink: none;
161 | text-decoration-skip-ink: none;
162 | }
163 |
164 | address {
165 | margin-bottom: 1rem;
166 | font-style: normal;
167 | line-height: inherit;
168 | }
169 |
170 | ol,
171 | ul {
172 | padding-right: 2rem;
173 | }
174 |
175 | ol,
176 | ul,
177 | dl {
178 | margin-top: 0;
179 | margin-bottom: 1rem;
180 | }
181 |
182 | ol ol,
183 | ul ul,
184 | ol ul,
185 | ul ol {
186 | margin-bottom: 0;
187 | }
188 |
189 | dt {
190 | font-weight: 700;
191 | }
192 |
193 | dd {
194 | margin-bottom: 0.5rem;
195 | margin-right: 0;
196 | }
197 |
198 | blockquote {
199 | margin: 0 0 1rem;
200 | }
201 |
202 | b,
203 | strong {
204 | font-weight: bolder;
205 | }
206 |
207 | small {
208 | font-size: 0.875em;
209 | }
210 |
211 | mark {
212 | padding: 0.2em;
213 | background-color: #fcf8e3;
214 | }
215 |
216 | sub,
217 | sup {
218 | position: relative;
219 | font-size: 0.75em;
220 | line-height: 0;
221 | vertical-align: baseline;
222 | }
223 |
224 | sub {
225 | bottom: -0.25em;
226 | }
227 |
228 | sup {
229 | top: -0.5em;
230 | }
231 |
232 | a {
233 | color: #0d6efd;
234 | text-decoration: underline;
235 | }
236 | a:hover {
237 | color: #0a58ca;
238 | }
239 |
240 | a:not([href]):not([class]), a:not([href]):not([class]):hover {
241 | color: inherit;
242 | text-decoration: none;
243 | }
244 |
245 | pre,
246 | code,
247 | kbd,
248 | samp {
249 | font-family: var(--bs-font-monospace);
250 | font-size: 1em;
251 | direction: ltr ;
252 | unicode-bidi: bidi-override;
253 | }
254 |
255 | pre {
256 | display: block;
257 | margin-top: 0;
258 | margin-bottom: 1rem;
259 | overflow: auto;
260 | font-size: 0.875em;
261 | }
262 | pre code {
263 | font-size: inherit;
264 | color: inherit;
265 | word-break: normal;
266 | }
267 |
268 | code {
269 | font-size: 0.875em;
270 | color: #d63384;
271 | word-wrap: break-word;
272 | }
273 | a > code {
274 | color: inherit;
275 | }
276 |
277 | kbd {
278 | padding: 0.2rem 0.4rem;
279 | font-size: 0.875em;
280 | color: #fff;
281 | background-color: #212529;
282 | border-radius: 0.2rem;
283 | }
284 | kbd kbd {
285 | padding: 0;
286 | font-size: 1em;
287 | font-weight: 700;
288 | }
289 |
290 | figure {
291 | margin: 0 0 1rem;
292 | }
293 |
294 | img,
295 | svg {
296 | vertical-align: middle;
297 | }
298 |
299 | table {
300 | caption-side: bottom;
301 | border-collapse: collapse;
302 | }
303 |
304 | caption {
305 | padding-top: 0.5rem;
306 | padding-bottom: 0.5rem;
307 | color: #6c757d;
308 | text-align: right;
309 | }
310 |
311 | th {
312 | text-align: inherit;
313 | text-align: -webkit-match-parent;
314 | }
315 |
316 | thead,
317 | tbody,
318 | tfoot,
319 | tr,
320 | td,
321 | th {
322 | border-color: inherit;
323 | border-style: solid;
324 | border-width: 0;
325 | }
326 |
327 | label {
328 | display: inline-block;
329 | }
330 |
331 | button {
332 | border-radius: 0;
333 | }
334 |
335 | button:focus:not(:focus-visible) {
336 | outline: 0;
337 | }
338 |
339 | input,
340 | button,
341 | select,
342 | optgroup,
343 | textarea {
344 | margin: 0;
345 | font-family: inherit;
346 | font-size: inherit;
347 | line-height: inherit;
348 | }
349 |
350 | button,
351 | select {
352 | text-transform: none;
353 | }
354 |
355 | [role=button] {
356 | cursor: pointer;
357 | }
358 |
359 | select {
360 | word-wrap: normal;
361 | }
362 | select:disabled {
363 | opacity: 1;
364 | }
365 |
366 | [list]::-webkit-calendar-picker-indicator {
367 | display: none;
368 | }
369 |
370 | button,
371 | [type=button],
372 | [type=reset],
373 | [type=submit] {
374 | -webkit-appearance: button;
375 | }
376 | button:not(:disabled),
377 | [type=button]:not(:disabled),
378 | [type=reset]:not(:disabled),
379 | [type=submit]:not(:disabled) {
380 | cursor: pointer;
381 | }
382 |
383 | ::-moz-focus-inner {
384 | padding: 0;
385 | border-style: none;
386 | }
387 |
388 | textarea {
389 | resize: vertical;
390 | }
391 |
392 | fieldset {
393 | min-width: 0;
394 | padding: 0;
395 | margin: 0;
396 | border: 0;
397 | }
398 |
399 | legend {
400 | float: right;
401 | width: 100%;
402 | padding: 0;
403 | margin-bottom: 0.5rem;
404 | font-size: calc(1.275rem + 0.3vw);
405 | line-height: inherit;
406 | }
407 | @media (min-width: 1200px) {
408 | legend {
409 | font-size: 1.5rem;
410 | }
411 | }
412 | legend + * {
413 | clear: right;
414 | }
415 |
416 | ::-webkit-datetime-edit-fields-wrapper,
417 | ::-webkit-datetime-edit-text,
418 | ::-webkit-datetime-edit-minute,
419 | ::-webkit-datetime-edit-hour-field,
420 | ::-webkit-datetime-edit-day-field,
421 | ::-webkit-datetime-edit-month-field,
422 | ::-webkit-datetime-edit-year-field {
423 | padding: 0;
424 | }
425 |
426 | ::-webkit-inner-spin-button {
427 | height: auto;
428 | }
429 |
430 | [type=search] {
431 | outline-offset: -2px;
432 | -webkit-appearance: textfield;
433 | }
434 |
435 | [type="tel"],
436 | [type="url"],
437 | [type="email"],
438 | [type="number"] {
439 | direction: ltr;
440 | }
441 | ::-webkit-search-decoration {
442 | -webkit-appearance: none;
443 | }
444 |
445 | ::-webkit-color-swatch-wrapper {
446 | padding: 0;
447 | }
448 |
449 | ::-webkit-file-upload-button {
450 | font: inherit;
451 | }
452 |
453 | ::file-selector-button {
454 | font: inherit;
455 | }
456 |
457 | ::-webkit-file-upload-button {
458 | font: inherit;
459 | -webkit-appearance: button;
460 | }
461 |
462 | output {
463 | display: inline-block;
464 | }
465 |
466 | iframe {
467 | border: 0;
468 | }
469 |
470 | summary {
471 | display: list-item;
472 | cursor: pointer;
473 | }
474 |
475 | progress {
476 | vertical-align: baseline;
477 | }
478 |
479 | [hidden] {
480 | display: none !important;
481 | }
482 | /*# sourceMappingURL=bootstrap-reboot.rtl.css.map */
--------------------------------------------------------------------------------
/application/public/bootstrap/css/bootstrap-reboot.rtl.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Reboot v5.1.3 (https://getbootstrap.com/)
3 | * Copyright 2011-2021 The Bootstrap Authors
4 | * Copyright 2011-2021 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
7 | */:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-primary-rgb:13,110,253;--bs-secondary-rgb:108,117,125;--bs-success-rgb:25,135,84;--bs-info-rgb:13,202,240;--bs-warning-rgb:255,193,7;--bs-danger-rgb:220,53,69;--bs-light-rgb:248,249,250;--bs-dark-rgb:33,37,41;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-body-color-rgb:33,37,41;--bs-body-bg-rgb:255,255,255;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#212529;--bs-body-bg:#fff}*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-right:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-right:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:var(--bs-font-monospace);font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:right}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:right;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:right}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}[type=email],[type=number],[type=tel],[type=url]{direction:ltr}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::-webkit-file-upload-button{font:inherit}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}
8 | /*# sourceMappingURL=bootstrap-reboot.rtl.min.css.map */
--------------------------------------------------------------------------------
/application/public/css/css.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/css/css.css
--------------------------------------------------------------------------------
/application/public/css/style.css:
--------------------------------------------------------------------------------
1 | .whb {
2 | background-color: #fff;
3 | }
4 |
5 | section title {
6 | display: block;
7 |
8 | }
9 |
10 | .block {
11 | width: 100%;
12 | background: #faf4ea;
13 | padding: 0.3rem 0.3rem;
14 | border: 1px solid #e4dcd8;
15 | position: relative;
16 | }
17 |
18 | .block h3 {
19 | margin: 0 0 10px;
20 | }
21 |
22 |
23 | .authors-list {
24 | margin-bottom: 10px;
25 | }
26 |
27 | .block .info {
28 | color: #542a00;
29 | margin-bottom: 5px;
30 | font-size: 14px;
31 | line-height: 20px;
32 | }
33 |
34 |
35 | .info dt {
36 | float: left;
37 | clear: left;
38 | color: #000;
39 | margin: 0 3px 0 0;
40 | }
41 |
42 | .bottom-line {
43 | border-top: 1px dashed #e4dcd8;
44 | margin-top: 5px;
45 | margin-bottom: 5px;
46 | }
47 |
48 | .author {
49 | line-height: 1.3em;
50 | padding-right: 4px;
51 | padding-left: 4px;
52 | border-radius: 2px;
53 | text-decoration: none;
54 | margin: 2px 4px 2px 0;
55 | color: #542a00;
56 | padding: 2px;
57 | }
58 |
59 | section {
60 | text-align: justify;
61 | }
62 |
63 | section p {
64 | text-indent: 2em;
65 | }
66 |
67 | section title {
68 | text-align: center;
69 | font-weight: bold;
70 | font-size: 1.5 em;
71 | }
72 |
73 | a:hover, a:visited, a:link, a:active {
74 | text-decoration: none;
75 | }
76 | h3 {
77 | color: #334455;
78 | text-decoration: none;
79 | }
80 |
81 | .book-link {
82 | color: #542a00;
83 | }
84 | .card-body {
85 | padding: 0.3rem 0.3rem;
86 | }
87 |
88 | h4 {
89 | margin-bottom: .1rem;
90 | }
91 |
92 | .cover {
93 | box-shadow: 0 .125rem .25rem rgba(0,0,0,.9)!important;
94 | max-height: 400px;
95 | }
96 |
97 | .book {
98 | text-align: justify;
99 | }
100 |
101 |
102 | canvas {
103 | width: 100%;
104 | }
105 |
106 | .epub-view {
107 | width: 100% !important;
108 | }
109 |
110 | .epub-view iframe {
111 | width: 100% !important;
112 |
113 | }
114 |
115 | .divider {
116 | position: relative;
117 | margin-top: 1em;
118 | margin-bottom: 1em;
119 | height: 1px;
120 | }
121 |
122 | .div-transparent:before {
123 | content: "";
124 | position: absolute;
125 | top: 0;
126 | left: 5%;
127 | right: 5%;
128 | width: 90%;
129 | height: 1px;
130 | background-image: linear-gradient(to right, transparent, rgb(48,49,51), transparent);
131 | }
132 |
133 | .div-arrow-down:after {
134 | content: "";
135 | position: absolute;
136 | z-index: 1;
137 | top: -7px;
138 | left: calc(50% - 7px);
139 | width: 14px;
140 | height: 14px;
141 | transform: rotate(45deg);
142 | background-color: white;
143 | border-bottom: 1px solid rgb(48,49,51);
144 | border-right: 1px solid rgb(48,49,51);
145 | }
146 |
147 | .div-tab-down:after {
148 | content: "";
149 | position: absolute;
150 | z-index: 1;
151 | top: 0;
152 | left: calc(50% - 10px);
153 | width: 20px;
154 | height: 14px;
155 | background-color: white;
156 | border-bottom: 1px solid rgb(48,49,51);
157 | border-left: 1px solid rgb(48,49,51);
158 | border-right: 1px solid rgb(48,49,51);
159 | border-radius: 0 0 8px 8px;
160 | }
161 |
162 | .div-stopper:after {
163 | content: "";
164 | position: absolute;
165 | z-index: 1;
166 | top: -6px;
167 | left: calc(50% - 7px);
168 | width: 14px;
169 | height: 12px;
170 | background-color: white;
171 | border-left: 1px solid rgb(48,49,51);
172 | border-right: 1px solid rgb(48,49,51);
173 | }
174 |
175 | .div-dot:after {
176 | content: "";
177 | position: absolute;
178 | z-index: 1;
179 | top: -9px;
180 | left: calc(50% - 9px);
181 | width: 18px;
182 | height: 18px;
183 | background-color: #aaa ;
184 | border: 1px solid rgb(48,49,51);
185 | border-radius: 50%;
186 | box-shadow: inset 0 0 0 2px white,
187 | 0 0 0 4px white;
188 | }
189 |
190 | title {
191 | text-shadow: 0 2px white, 0 3px #777;
192 | margin: 1em 0 0.5em 0;
193 | color: #343434;
194 | font-family: 'Open Sans Condensed', sans-serif;
195 | font-size: 1.5em;
196 | line-height: 1.8em;
197 | text-align: center;
198 | text-transform: uppercase;
199 | }
200 |
201 | section section title {
202 | font-size: 18px;
203 | line-height: 20px;
204 | margin: 0;
205 | text-shadow: none;
206 | text-transform: none;
207 | text-align: left;
208 | border-top-left-radius: .25rem!important;
209 | border-top-right-radius: .25rem!important;
210 | background: #ddd;
211 | display: inline-block;
212 | padding: 0.25em;
213 | border-top: 1px solid #ddd;
214 | border-right: 1px solid #ddd;
215 | border-left: 1px solid #ddd;
216 | }
217 |
218 | section1 section p {
219 | padding: 0.5em;
220 | border: 1px solid #ddd;
221 | border-bottom-left-radius: .25rem!important;
222 | border-bottom-right-radius: .25rem!important;
223 | border-top-right-radius: .25rem!important;
224 | background: #eee;
225 | }
226 |
227 | .reader p {
228 | font-family: Sentinel SSm A,Sentinel SSm B,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;
229 | font-size: 1.2rem;
230 | font-weight: 400;
231 | line-height: 1.7;
232 | color: #333;
233 | font-family: sans-serif;
234 | margin-bottom: 15px;
235 | }
236 |
237 | .fx {
238 | display: block;
239 | margin-bottom: 0.5em;
240 |
241 | }
242 |
243 | .epub-container {
244 | min-width: 320px;
245 | margin: 0 auto;
246 | position: relative;
247 | }
248 |
249 | .epub-container .epub-view > iframe {
250 | background: white;
251 | box-shadow: 0 0 4px #ccc;
252 | /*margin: 10px;
253 | padding: 20px;*/
254 | }
255 |
256 |
--------------------------------------------------------------------------------
/application/public/extract_author.php:
--------------------------------------------------------------------------------
1 | prepare("SELECT file FROM libapics WHERE AvtorId=$id");
34 | $stmt->execute();
35 | $f = $stmt->fetch();
36 |
37 | if (isset($f->file)) {
38 | $zip = new ZipArchive();
39 | if ($zip->open(ROOT_PATH . "cache/lib.a.attached.zip")) {
40 | $f = $zip->getFromName($f->file);
41 | if (strlen($f) > 0) {
42 | file_put_contents(ROOT_PATH . "cache/authors/$id.jpg", $f);
43 | echo $f;
44 | die();
45 | }
46 | }
47 | $zip->close();
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/application/public/extract_cover.php:
--------------------------------------------------------------------------------
1 | $height && $newheight < $height){
12 | $newheight = (int)round($height / ($width / $newwidth));
13 | } else if ($width < $height && $newwidth < $width) {
14 | $newwidth = (int)round($width / ($height / $newheight));
15 | } else {
16 | $newwidth = (int)round($width);
17 | $newheight = (int)round($height);
18 | }
19 | $thumb = imagecreatetruecolor($newwidth, $newheight);
20 | imagecopyresized($thumb, $i, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
21 | return $thumb;
22 | }
23 |
24 | function lastm($path) {
25 | $fmtimestamp = filemtime($path);
26 | if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $fmtimestamp <= strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
27 | header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified');
28 | die();
29 | } else {
30 | header("Expires: " . gmdate("D, d M Y H:i:s", filemtime($path) + 60*60*24) . " GMT");
31 | header("Last-Modified: " . gmdate("D, d M Y H:i:s", filemtime($path)) . " GMT");
32 |
33 | echo file_get_contents($path);
34 | }
35 | }
36 |
37 | $small = isset($_GET['small']);
38 |
39 | if (isset($_GET['id'])) {
40 | $id = $_GET['id'];
41 | } else {
42 | if (isset($_GET['sid'])) {
43 | $id = $_GET['sid'];
44 | $small = true;
45 | }
46 | }
47 | $iid = $id;
48 |
49 | header("Content-type: image/jpeg");
50 |
51 | if ($small) {
52 | if (file_exists(ROOT_PATH . "cache/covers/$id-small.jpg")) {
53 | lastm(ROOT_PATH . "cache/covers/$id-small.jpg");
54 | die();
55 | }
56 | } else {
57 | if (file_exists(ROOT_PATH . "cache/covers/$id.jpg")) {
58 | lastm(ROOT_PATH . "cache/covers/$id.jpg");
59 | die();
60 | }
61 | }
62 |
63 | $stmt = $dbh->prepare("SELECT file FROM libbpics WHERE BookId=$id");
64 | $stmt->execute();
65 | $f = $stmt->fetch();
66 |
67 | if (isset($f->file)) {
68 | $zip = new ZipArchive();
69 | if ($zip->open(ROOT_PATH . "cache/lib.b.attached.zip")) {
70 | $f = $zip->getFromName($f->file);
71 | if (strlen($f) > 0) {
72 | file_put_contents(ROOT_PATH . "cache/covers/$id.jpg", $f);
73 | $thm = resizeCover($f, 300, 400);
74 | imagejpeg($thm, ROOT_PATH . "cache/covers/$id-small.jpg", 75);
75 | imagedestroy($thm);
76 | if ($small) {
77 | if (file_exists(ROOT_PATH . "cache/covers/$id-small.jpg")) {
78 | lastm(ROOT_PATH . "cache/covers/$id-small.jpg");
79 | die();
80 | }
81 | } else {
82 | echo $f;
83 | die();
84 | }
85 | }
86 | }
87 | $zip->close();
88 | }
89 |
90 |
91 | $stmt = $dbh->prepare("SELECT filetype FROM libbook WHERE bookid=$id LIMIT 1");
92 | $stmt->execute();
93 | $type = trim($stmt->fetch()->filetype);
94 | if ($type == 'fb2') {
95 | $u = '0';
96 | } else {
97 | $u = '1';
98 | }
99 |
100 | $stmt = $dbh->prepare("SELECT * FROM book_zip WHERE $id BETWEEN start_id AND end_id AND usr=$u");
101 | $stmt->execute();
102 | $zip_name = $stmt->fetch()->filename;
103 | $zip = new ZipArchive();
104 |
105 | $result = $dbh->query("SELECT filename FROM libfilename where BookId=$id")->fetch();
106 |
107 | if ($result) {
108 | $filename = $result->filename;
109 | } else {
110 | $filename = null;
111 | }
112 | if ($filename == '') {
113 | $filename = trim("$id.$type");
114 | }
115 |
116 | if ($zip->open(ROOT_PATH . "flibusta/" . $zip_name)) {
117 | $f = $zip->getFromName("$filename");
118 | }
119 |
120 |
121 | if ($type == 'fb2') {
122 | $fb2 = simplexml_load_string($f);
123 | $images = array();
124 | if (isset($fb2->binary)) {
125 | foreach ($fb2->binary as $binary) {
126 | $id = $binary->attributes()['id'];
127 | if (
128 | (strpos($id, "cover") !== false) ||
129 | (strpos($id, "jpg") !== false) ||
130 | (strpos($id, "obloj") !== false)
131 | ) {
132 | $cover = base64_decode($binary);
133 | }
134 | $images["$id"] = $binary;
135 | }
136 | }
137 | $zip->close();
138 | }
139 |
140 | if ($type == 'epub') {
141 | file_put_contents(ROOT_PATH . "cache/tmp/$iid.tmp", $f);
142 | include('/application/epub.php');
143 | $d = new EPub(ROOT_PATH . "cache/tmp/$iid.tmp");
144 | $im = $d->Cover();
145 | if ($im['found'] != '') {
146 | $cover = $im['data'];
147 | unlink(ROOT_PATH . "cache/tmp/$iid.tmp");
148 | } else {
149 | echo file_get_contents('/application/none.jpg');
150 | }
151 | }
152 |
153 | if (strlen($cover) < 100) {
154 | $cover = file_get_contents('/application/none.jpg');
155 | echo $cover;
156 | die();
157 | } else {
158 | file_put_contents(ROOT_PATH . "cache/covers/$iid.jpg", $cover);
159 | $thm = resizeCover($cover, 300, 400);
160 | imagejpeg($thm, ROOT_PATH . "cache/covers/$iid-small.jpg", 75);
161 | imagedestroy($thm);
162 | }
163 |
164 | if ($small) {
165 | if (file_exists(ROOT_PATH . "cache/covers/$iid-small.jpg")) {
166 | lastm(ROOT_PATH . "cache/covers/$iid-small.jpg");
167 | die();
168 | }
169 | } else {
170 | echo $cover;
171 | }
172 |
173 |
--------------------------------------------------------------------------------
/application/public/extract_usr.php:
--------------------------------------------------------------------------------
1 | fetchObject();
17 |
18 | $usr_filename = DBO::query("SELECT * FROM libfilename where BookId=$id")->fetchObject();
19 |
20 |
21 | if ($usr_filename == '') {
22 | $usr_filename = trim("$id.$book->filetype");
23 | }
24 |
25 | $zip_name = DBO::query("SELECT * FROM book_zip WHERE ($id BETWEEN start_id AND end_id) AND usr=1")->fetchObject()->filename;
26 | $zip = new ZipArchive();
27 |
28 | if ($zip->open("/work/fb/Flibusta.Net/" . $zip_name)) {
29 | $filename = $book->author_name . " - " . $book->booktitle . " " . $book->filename . "." . trim($book->filetype);
30 |
31 | header('Content-Description: File Transfer');
32 | header('Content-Type: application/octet-stream');
33 | header('Content-Transfer-Encoding: binary');
34 | header('Expires: 0');
35 | header('Cache-Control: must-revalidate');
36 | header('Pragma: public');
37 | header('Content-Disposition: attachment; filename=' . basename(rawurlencode($filename)));
38 |
39 | $data = $zip->getFromName($usr_filename);
40 | if ($data == '') {
41 | $data = $zip->getFromName($usr_filename . ".zip");
42 | }
43 |
44 | echo $data;
45 | $zip->close();
46 | } else {
47 | echo "NO ZIP";
48 | }
49 |
50 |
51 |
--------------------------------------------------------------------------------
/application/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/favicon.ico
--------------------------------------------------------------------------------
/application/public/favicon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 10
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/application/public/fb2.php:
--------------------------------------------------------------------------------
1 | prepare("SELECT libbook.Title BookTitle,
11 | CONCAT(libavtorname.LastName, ' ', libavtorname.FirstName) author_name
12 | FROM libbook
13 | LEFT JOIN libbannotations USING(BookId)
14 | LEFT JOIN libgenre USING(BookId)
15 | LEFT JOIN libgenrelist USING(GenreId)
16 | LEFT JOIN libseq USING(BookId)
17 | LEFT JOIN libavtor USING(BookId)
18 | LEFT JOIN libavtorname USING(AvtorId)
19 | LEFT JOIN libseqname USING(SeqId) WHERE libbook.BookId=:id");
20 | $stmt->bindParam(":id", $id);
21 | $stmt->execute();
22 | $book = $stmt->fetch();
23 |
24 |
25 | $stmt = $dbh->prepare("SELECT * FROM book_zip WHERE $id BETWEEN start_id AND end_id AND usr=0");
26 | $stmt->execute();
27 | $zip_name = $stmt->fetch()->filename;
28 | $zip = new ZipArchive();
29 |
30 | if ($zip->open(ROOT_PATH . "flibusta/" . $zip_name)) {
31 | $filename = $book->author_name . " - " . $book->booktitle . " " . $id . ".fb2";
32 | header('Content-Description: File Transfer');
33 | header('Content-Type: application/octet-stream');
34 | header('Content-Disposition: attachment; filename=' . basename(rawurlencode($filename)));
35 | header('Content-Transfer-Encoding: binary');
36 | header('Expires: 0');
37 | header('Cache-Control: must-revalidate');
38 | header('Pragma: public');
39 | echo $zip->getFromName("$id.fb2");
40 | $zip->close();
41 | } else {
42 | echo "NO ZIP";
43 | }
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/application/public/font/weathericons-regular-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/font/weathericons-regular-webfont.eot
--------------------------------------------------------------------------------
/application/public/font/weathericons-regular-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/font/weathericons-regular-webfont.ttf
--------------------------------------------------------------------------------
/application/public/font/weathericons-regular-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/font/weathericons-regular-webfont.woff
--------------------------------------------------------------------------------
/application/public/font/weathericons-regular-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/font/weathericons-regular-webfont.woff2
--------------------------------------------------------------------------------
/application/public/fonts/KFOlCnqEu92Fr1MmWUlfABc4EsA.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/KFOlCnqEu92Fr1MmWUlfABc4EsA.woff2
--------------------------------------------------------------------------------
/application/public/fonts/KFOlCnqEu92Fr1MmWUlfBBc4.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/KFOlCnqEu92Fr1MmWUlfBBc4.woff2
--------------------------------------------------------------------------------
/application/public/fonts/Roboto-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/Roboto-Bold.woff2
--------------------------------------------------------------------------------
/application/public/fonts/Roboto-Medium.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/Roboto-Medium.woff2
--------------------------------------------------------------------------------
/application/public/fonts/Roboto-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/Roboto-Regular.woff2
--------------------------------------------------------------------------------
/application/public/fonts/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2
--------------------------------------------------------------------------------
/application/public/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/application/public/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/application/public/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/application/public/fonts/materialicons.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/materialicons.woff2
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Bold.eot
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Bold.ttf
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Bold.woff
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Bold.woff2
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Light.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Light.eot
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Light.ttf
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Light.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Light.woff
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Light.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Light.woff2
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Medium.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Medium.eot
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Medium.ttf
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Medium.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Medium.woff
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Medium.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Medium.woff2
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Regular.eot
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Regular.woff
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Regular.woff2
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Thin.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Thin.eot
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Thin.ttf
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Thin.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Thin.woff
--------------------------------------------------------------------------------
/application/public/fonts/roboto/Roboto-Thin.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/fonts/roboto/Roboto-Thin.woff2
--------------------------------------------------------------------------------
/application/public/i/default_avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/i/default_avatar.png
--------------------------------------------------------------------------------
/application/public/i/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/i/ic_launcher.png
--------------------------------------------------------------------------------
/application/public/index.php:
--------------------------------------------------------------------------------
1 | prepare("DELETE FROM fav_users WHERE user_uuid=:uuid");
16 | $stmt->bindParam(":uuid", $uu);
17 | $stmt->execute();
18 | $st = $dbh->prepare("DELETE FROM fav WHERE user_uuid=:uuid");
19 | $st->bindParam(":uuid", $uu);
20 | $st->execute();
21 | }
22 |
23 | if (isset($_GET['new_uuid'])) {
24 | $nname = trim($_GET['new_uuid']);
25 | if ($nname !== '') {
26 | $stmt = $dbh->prepare("INSERT INTO fav_users (user_uuid, name) VALUES (uuid_generate_v1(), :name)");
27 | $stmt->bindParam(":name", $nname);
28 | $stmt->execute();
29 |
30 | $stmt = $dbh->prepare("SELECT user_uuid FROM fav_users WHERE name=:name LIMIT 1");
31 | $stmt->bindParam(":name", $nname);
32 | $stmt->execute();
33 | $r = $stmt->fetch();
34 | $user_uuid = $r->user_uuid;
35 | $user_name = $nname;
36 | $_SESSION['user_uuid'] = $user_uuid;
37 | }
38 | }
39 |
40 | if (isset($_SESSION['user_uuid'])) {
41 | $user_uuid = $_SESSION['user_uuid'];
42 | $stmt = $dbh->prepare("SELECT * FROM fav_users WHERE user_uuid=:uuid");
43 | $stmt->bindParam(":uuid", $user_uuid);
44 | try {
45 | $stmt->execute();
46 | $user = $stmt->fetch();
47 | } catch (PDOException $e) {
48 | //
49 | }
50 |
51 | if (isset($user->name)) {
52 | $user_name = $user->name;
53 |
54 | if (isset($_GET['fav_book'])) {
55 | $id = intval($_GET['fav_book']);
56 | $st = $dbh->prepare("INSERT INTO fav (user_uuid, bookid) VALUES(:uuid, :id) ON CONFLICT DO NOTHING");
57 | $st->bindParam(":uuid", $user_uuid);
58 | $st->bindParam(":id", $id);
59 | $st->execute();
60 | }
61 | if (isset($_GET['fav_author'])) {
62 | $id = intval($_GET['fav_author']);
63 | $st = $dbh->prepare("INSERT INTO fav (user_uuid, avtorid) VALUES(:uuid, :id) ON CONFLICT DO NOTHING");
64 | $st->bindParam(":uuid", $user_uuid);
65 | $st->bindParam(":id", $id);
66 | $st->execute();
67 | }
68 | if (isset($_GET['fav_seq'])) {
69 | $id = intval($_GET['fav_seq']);
70 | $st = $dbh->prepare("DELETE FROM fav WHERE user_uuid=:uuid AND seqid=:id");
71 | $st->bindParam(":uuid", $user_uuid);
72 | $st->bindParam(":id", $id);
73 | $st->execute();
74 | $st = $dbh->prepare("INSERT INTO fav (user_uuid, seqid) VALUES(:uuid, :id) ON CONFLICT DO NOTHING");
75 | $st->bindParam(":uuid", $user_uuid);
76 | $st->bindParam(":id", $id);
77 | $st->execute();
78 | }
79 |
80 | if (isset($_GET['unfav_book'])) {
81 | $id = intval($_GET['unfav_book']);
82 | $st = $dbh->prepare("DELETE FROM fav WHERE user_uuid=:uuid AND bookid=:id");
83 | $st->bindParam(":uuid", $user_uuid);
84 | $st->bindParam(":id", $id);
85 | $st->execute();
86 | }
87 | if (isset($_GET['unfav_author'])) {
88 | $id = intval($_GET['unfav_author']);
89 | $st = $dbh->prepare("DELETE FROM fav WHERE user_uuid=:uuid AND avtorid=:id");
90 | $st->bindParam(":uuid", $user_uuid);
91 | $st->bindParam(":id", $id);
92 | $st->execute();
93 | }
94 | if (isset($_GET['unfav_seq'])) {
95 | $id = intval($_GET['unfav_seq']);
96 | $st = $dbh->prepare("DELETE FROM fav WHERE user_uuid=:uuid AND seqid=:id");
97 | $st->bindParam(":uuid", $user_uuid);
98 | $st->bindParam(":id", $id);
99 | $st->execute();
100 | }
101 | } else {
102 | unset($_SESSION['user_uuid']);
103 | $user_name = 'Книжные полки';
104 | }
105 | } else {
106 | $user_uuid = '';
107 | }
108 |
109 | if (isset($_GET['sort'])) {
110 | $sort_mode = $_GET['sort'];
111 | } else {
112 | $sort_mode = 'abc';
113 | if ($url->action == '') {
114 | $sort_mode = 'date';
115 | }
116 | }
117 |
118 | if (isset($_GET['page'])) {
119 | $page = intval($_GET['page']);
120 | } else {
121 | $page = 0;
122 | }
123 |
124 | $start = $page * RECORDS_PAGE;
125 | $lang = 'ru';
126 | $filter = "";
127 |
128 | switch ($sort_mode) {
129 | case 'abc':
130 | $order = 'b.Title';
131 | break;
132 |
133 | case 'author':
134 | $order = 'b.Title';
135 | break;
136 |
137 | case 'date':
138 | $order = 'b.Time DESC';
139 | break;
140 |
141 | case 'rating':
142 | $order = 'b.Title';
143 | break;
144 | }
145 |
146 | if ($url->mod == 'opds') {
147 | include(ROOT_PATH . "/opds/index.php");
148 | } else {
149 | include(ROOT_PATH . "renderer.php");
150 | }
151 |
152 |
--------------------------------------------------------------------------------
/application/public/js/mobi.min.js:
--------------------------------------------------------------------------------
1 | var _0x3d0b=["\x6C\x65\x6E\x67\x74\x68","\x65\x6E\x75\x6D\x65\x72\x61\x62\x6C\x65","\x63\x6F\x6E\x66\x69\x67\x75\x72\x61\x62\x6C\x65","\x76\x61\x6C\x75\x65","\x77\x72\x69\x74\x61\x62\x6C\x65","\x6B\x65\x79","\x64\x65\x66\x69\x6E\x65\x50\x72\x6F\x70\x65\x72\x74\x79","\x70\x72\x6F\x74\x6F\x74\x79\x70\x65","\x43\x61\x6E\x6E\x6F\x74\x20\x63\x61\x6C\x6C\x20\x61\x20\x63\x6C\x61\x73\x73\x20\x61\x73\x20\x61\x20\x66\x75\x6E\x63\x74\x69\x6F\x6E","\x64\x65\x63\x6F\x64\x65","\x75\x74\x66\x2D\x38","\x63\x61\x70\x61\x63\x69\x74\x79","\x66\x72\x61\x67\x6D\x65\x6E\x74\x5F\x6C\x69\x73\x74","\x63\x75\x72\x5F\x66\x72\x61\x67\x6D\x65\x6E\x74","\x70\x75\x73\x68","\x77\x72\x69\x74\x65","\x67\x65\x74","\x73\x69\x7A\x65","\x73\x68\x72\x69\x6E\x6B","\x66\x75\x6C\x6C","\x62\x75\x66\x66\x65\x72","\x73\x65\x74","\x73\x6C\x69\x63\x65","\x76\x69\x65\x77","\x6F\x66\x66\x73\x65\x74","\x68\x65\x61\x64\x65\x72","\x70\x61\x72\x73\x65","\x67\x65\x74\x55\x69\x6E\x74\x38","\x67\x65\x74\x55\x69\x6E\x74\x31\x36","\x67\x65\x74\x55\x69\x6E\x74\x33\x32","\x67\x65\x74\x53\x74\x72","\x73\x6B\x69\x70","\x73\x65\x74\x6F\x66\x66\x73\x65\x74","\x67\x65\x74\x5F\x72\x65\x63\x6F\x72\x64\x5F\x65\x78\x74\x72\x61\x73\x69\x7A\x65","\x62\x75\x66\x66\x65\x72\x5F\x67\x65\x74\x5F\x76\x61\x72\x6C\x65\x6E","\x72\x65\x61\x64\x5F\x74\x65\x78\x74","\x72\x65\x63\x6F\x72\x64\x5F\x63\x6F\x75\x6E\x74","\x70\x61\x6C\x6D\x5F\x68\x65\x61\x64\x65\x72","\x72\x65\x61\x64\x5F\x74\x65\x78\x74\x5F\x72\x65\x63\x6F\x72\x64","\x65\x78\x74\x72\x61\x5F\x66\x6C\x61\x67\x73","\x6D\x6F\x62\x69\x5F\x68\x65\x61\x64\x65\x72","\x72\x65\x63\x6C\x69\x73\x74","\x63\x6F\x6D\x70\x72\x65\x73\x73\x69\x6F\x6E","\x72\x65\x61\x64\x5F\x69\x6D\x61\x67\x65","\x66\x69\x72\x73\x74\x5F\x69\x6D\x61\x67\x65\x5F\x69\x64\x78","\x6C\x6F\x61\x64","\x6C\x6F\x61\x64\x5F\x70\x64\x62\x68\x65\x61\x64\x65\x72","\x6C\x6F\x61\x64\x5F\x72\x65\x63\x6C\x69\x73\x74","\x6C\x6F\x61\x64\x5F\x72\x65\x63\x6F\x72\x64\x30","\x6E\x61\x6D\x65","\x61\x74\x74\x72","\x76\x65\x72\x73\x69\x6F\x6E","\x63\x74\x69\x6D\x65","\x6D\x74\x69\x6D\x65","\x62\x74\x69\x6D\x65","\x6D\x6F\x64\x5F\x6E\x75\x6D","\x61\x70\x70\x69\x6E\x66\x6F\x5F\x6F\x66\x66\x73\x65\x74","\x73\x6F\x72\x74\x69\x6E\x66\x6F\x5F\x6F\x66\x66\x73\x65\x74","\x74\x79\x70\x65","\x63\x72\x65\x61\x74\x6F\x72","\x75\x69\x64","\x6E\x65\x78\x74\x5F\x72\x65\x63","\x72\x65\x63\x6F\x72\x64\x5F\x6E\x75\x6D","\x6C\x6F\x61\x64\x5F\x72\x65\x63\x6F\x72\x64\x30\x5F\x68\x65\x61\x64\x65\x72","\x6C\x6F\x61\x64\x5F\x6D\x6F\x62\x69\x5F\x68\x65\x61\x64\x65\x72","\x74\x65\x78\x74\x5F\x6C\x65\x6E\x67\x74\x68","\x72\x65\x63\x6F\x72\x64\x5F\x73\x69\x7A\x65","\x65\x6E\x63\x72\x79\x70\x74\x69\x6F\x6E\x5F\x74\x79\x70\x65","\x69\x64\x65\x6E\x74\x69\x66\x69\x65\x72","\x68\x65\x61\x64\x65\x72\x5F\x6C\x65\x6E\x67\x74\x68","\x6D\x6F\x62\x69\x5F\x74\x79\x70\x65","\x74\x65\x78\x74\x5F\x65\x6E\x63\x6F\x64\x69\x6E\x67","\x67\x65\x6E\x65\x72\x61\x74\x6F\x72\x5F\x76\x65\x72\x73\x69\x6F\x6E","\x66\x69\x72\x73\x74\x5F\x6E\x6F\x6E\x62\x6F\x6F\x6B\x5F\x69\x6E\x64\x65\x78","\x66\x75\x6C\x6C\x5F\x6E\x61\x6D\x65\x5F\x6F\x66\x66\x73\x65\x74","\x66\x75\x6C\x6C\x5F\x6E\x61\x6D\x65\x5F\x6C\x65\x6E\x67\x74\x68","\x6C\x61\x6E\x67\x75\x61\x67\x65","\x69\x6E\x70\x75\x74\x5F\x6C\x61\x6E\x67\x75\x61\x67\x65","\x6F\x75\x74\x70\x75\x74\x5F\x6C\x61\x6E\x67\x75\x61\x67\x65","\x6D\x69\x6E\x5F\x76\x65\x72\x73\x69\x6F\x6E","\x68\x75\x66\x66\x5F\x72\x65\x63\x5F\x69\x6E\x64\x65\x78","\x68\x75\x66\x66\x5F\x72\x65\x63\x5F\x63\x6F\x75\x6E\x74","\x64\x61\x74\x70\x5F\x72\x65\x63\x5F\x69\x6E\x64\x65\x78","\x64\x61\x74\x70\x5F\x72\x65\x63\x5F\x63\x6F\x75\x6E\x74","\x65\x78\x74\x68\x5F\x66\x6C\x61\x67\x73","\x64\x72\x6D\x5F\x6F\x66\x66\x73\x65\x74","\x64\x72\x6D\x5F\x63\x6F\x75\x6E\x74","\x64\x72\x6D\x5F\x73\x69\x7A\x65","\x64\x72\x6D\x5F\x66\x6C\x61\x67\x73","\x6C\x6F\x61\x64\x5F\x65\x78\x74\x68\x5F\x68\x65\x61\x64\x65\x72","\x72\x65\x6E\x64\x65\x72\x5F\x74\x6F","\x67\x65\x74\x45\x6C\x65\x6D\x65\x6E\x74\x42\x79\x49\x64","\x66\x69\x72\x73\x74\x43\x68\x69\x6C\x64","\x72\x65\x6D\x6F\x76\x65\x43\x68\x69\x6C\x64","\x74\x65\x78\x74\x2F\x68\x74\x6D\x6C","\x70\x61\x72\x73\x65\x46\x72\x6F\x6D\x53\x74\x72\x69\x6E\x67","\x61\x70\x70\x65\x6E\x64\x43\x68\x69\x6C\x64","\x66\x6F\x72\x45\x61\x63\x68","\x63\x68\x69\x6C\x64\x4E\x6F\x64\x65\x73","\x62\x6F\x64\x79","\x69\x6D\x67","\x67\x65\x74\x45\x6C\x65\x6D\x65\x6E\x74\x73\x42\x79\x54\x61\x67\x4E\x61\x6D\x65","\x72\x65\x6E\x64\x65\x72\x5F\x69\x6D\x61\x67\x65","\x72\x65\x63\x69\x6E\x64\x65\x78","\x67\x65\x74\x41\x74\x74\x72\x69\x62\x75\x74\x65","\x6F\x6E\x6C\x6F\x61\x64","\x73\x72\x63","\x72\x65\x73\x75\x6C\x74","\x74\x61\x72\x67\x65\x74","\x72\x65\x61\x64\x41\x73\x44\x61\x74\x61\x55\x52\x4C"];var _createClass=function(){function _0x8e3ex2(_0x8e3ex3,_0x8e3ex4){for(var _0x8e3ex5=0;_0x8e3ex5< _0x8e3ex4[_0x3d0b[0]];_0x8e3ex5++){var _0x8e3ex6=_0x8e3ex4[_0x8e3ex5];_0x8e3ex6[_0x3d0b[1]]= _0x8e3ex6[_0x3d0b[1]]|| false;_0x8e3ex6[_0x3d0b[2]]= true;if(_0x3d0b[3] in _0x8e3ex6){_0x8e3ex6[_0x3d0b[4]]= true};Object[_0x3d0b[6]](_0x8e3ex3,_0x8e3ex6[_0x3d0b[5]],_0x8e3ex6)}}return function(_0x8e3ex7,_0x8e3ex8,_0x8e3ex9){if(_0x8e3ex8){_0x8e3ex2(_0x8e3ex7[_0x3d0b[7]],_0x8e3ex8)};if(_0x8e3ex9){_0x8e3ex2(_0x8e3ex7,_0x8e3ex9)};return _0x8e3ex7}}();function _classCallCheck(_0x8e3exb,_0x8e3ex7){if(!(_0x8e3exb instanceof _0x8e3ex7)){throw new TypeError(_0x3d0b[8])}}function ab2str(_0x8e3exd){if(_0x8e3exd instanceof ArrayBuffer){_0x8e3exd= new Uint8Array(_0x8e3exd)};return new TextDecoder(_0x3d0b[10])[_0x3d0b[9]](_0x8e3exd)}var domParser= new DOMParser();var Buffer=function(){function Buffer(_0x8e3ex10){_classCallCheck(this,Buffer);this[_0x3d0b[11]]= _0x8e3ex10;this[_0x3d0b[12]]= [];this[_0x3d0b[13]]= new Fragment(_0x8e3ex10);this[_0x3d0b[12]][_0x3d0b[14]](this[_0x3d0b[13]])}_createClass(Buffer,[{key:_0x3d0b[15],value:function _0x8e3ex11(_0x8e3ex12){var _0x8e3ex13=this[_0x3d0b[13]][_0x3d0b[15]](_0x8e3ex12);if(!_0x8e3ex13){this[_0x3d0b[13]]= new Fragment(this[_0x3d0b[11]]);this[_0x3d0b[12]][_0x3d0b[14]](this[_0x3d0b[13]]);this[_0x3d0b[13]][_0x3d0b[15]](_0x8e3ex12)}}},{key:_0x3d0b[16],value:function _0x8e3ex14(_0x8e3ex15){var _0x8e3ex16=0;while(_0x8e3ex16< this[_0x3d0b[12]][_0x3d0b[0]]){var _0x8e3ex17=this[_0x3d0b[12]][_0x8e3ex16];if(_0x8e3ex15< _0x8e3ex17[_0x3d0b[17]]){return _0x8e3ex17[_0x3d0b[16]](_0x8e3ex15)};_0x8e3ex15-= _0x8e3ex17[_0x3d0b[17]];_0x8e3ex16+= 1};return null}},{key:_0x3d0b[17],value:function _0x8e3ex18(){var _0x8e3ex19=0;for(var _0x8e3ex5=0;_0x8e3ex5< this[_0x3d0b[12]][_0x3d0b[0]];_0x8e3ex5++){_0x8e3ex19+= this[_0x3d0b[12]][_0x8e3ex5][_0x3d0b[17]]};return _0x8e3ex19}},{key:_0x3d0b[18],value:function _0x8e3ex1a(){var _0x8e3ex1b= new Uint8Array(this[_0x3d0b[17]]());var _0x8e3ex1c=0;for(var _0x8e3ex5=0;_0x8e3ex5< this[_0x3d0b[12]][_0x3d0b[0]];_0x8e3ex5++){var _0x8e3ex17=this[_0x3d0b[12]][_0x8e3ex5];if(_0x8e3ex17[_0x3d0b[19]]()){_0x8e3ex1b[_0x3d0b[21]](_0x8e3ex17[_0x3d0b[20]],_0x8e3ex1c)}else {_0x8e3ex1b[_0x3d0b[21]](_0x8e3ex17[_0x3d0b[20]][_0x3d0b[22]](0,_0x8e3ex17[_0x3d0b[17]]),_0x8e3ex1c)};_0x8e3ex1c+= _0x8e3ex17[_0x3d0b[17]]};return _0x8e3ex1b}}]);return Buffer}();var combine_uint8array=function combine_uint8array(_0x8e3ex1e){var _0x8e3ex1f=0;for(var _0x8e3ex5=0;_0x8e3ex5< _0x8e3ex1e[_0x3d0b[0]];_0x8e3ex5++){var _0x8e3ex20=_0x8e3ex1e[_0x8e3ex5];_0x8e3ex1f+= _0x8e3ex20[_0x3d0b[0]]};var _0x8e3ex1b= new Uint8Array(_0x8e3ex1f);var _0x8e3ex1c=0;for(var _0x8e3ex5=0;_0x8e3ex5< _0x8e3ex1e[_0x3d0b[0]];_0x8e3ex5++){var _0x8e3ex20=_0x8e3ex1e[_0x8e3ex5];_0x8e3ex1b[_0x3d0b[21]](_0x8e3ex20,_0x8e3ex1c);_0x8e3ex1c+= _0x8e3ex20[_0x3d0b[0]]};return _0x8e3ex1b};var Fragment=function(){function Fragment(_0x8e3ex10){_classCallCheck(this,Fragment);this[_0x3d0b[20]]= new Uint8Array(_0x8e3ex10);this[_0x3d0b[11]]= _0x8e3ex10;this[_0x3d0b[17]]= 0}_createClass(Fragment,[{key:_0x3d0b[15],value:function _0x8e3ex11(_0x8e3ex12){if(this[_0x3d0b[17]]>= this[_0x3d0b[11]]){return false};this[_0x3d0b[20]][this[_0x3d0b[17]]]= _0x8e3ex12;this[_0x3d0b[17]]+= 1;return true}},{key:_0x3d0b[19],value:function _0x8e3ex22(){return this[_0x3d0b[17]]=== this[_0x3d0b[11]]}},{key:_0x3d0b[16],value:function _0x8e3ex14(_0x8e3ex15){return this[_0x3d0b[20]][_0x8e3ex15]}}]);return Fragment}();var uncompression_lz77=function uncompression_lz77(_0x8e3ex24){var _0x8e3ex25=_0x8e3ex24[_0x3d0b[0]];var _0x8e3ex1c=0;var _0x8e3ex20= new Buffer(_0x8e3ex24[_0x3d0b[0]]);while(_0x8e3ex1c< _0x8e3ex25){var _0x8e3ex26=_0x8e3ex24[_0x8e3ex1c];_0x8e3ex1c+= 1;if(_0x8e3ex26== 0){_0x8e3ex20[_0x3d0b[15]](_0x8e3ex26)}else {if(_0x8e3ex26<= 8){for(var _0x8e3ex5=_0x8e3ex1c;_0x8e3ex5< _0x8e3ex1c+ _0x8e3ex26;_0x8e3ex5++){_0x8e3ex20[_0x3d0b[15]](_0x8e3ex24[_0x8e3ex5])};_0x8e3ex1c+= _0x8e3ex26}else {if(_0x8e3ex26<= 0x7f){_0x8e3ex20[_0x3d0b[15]](_0x8e3ex26)}else {if(_0x8e3ex26<= 0xbf){var _0x8e3ex27=_0x8e3ex24[_0x8e3ex1c];_0x8e3ex1c+= 1;var _0x8e3ex28=(_0x8e3ex26<< 8| _0x8e3ex27)>> 3& 0x7ff;var _0x8e3ex29=(_0x8e3ex27& 0x7)+ 3;var _0x8e3ex2a=_0x8e3ex20[_0x3d0b[17]]();for(var _0x8e3ex5=0;_0x8e3ex5< _0x8e3ex29;_0x8e3ex5++){_0x8e3ex20[_0x3d0b[15]](_0x8e3ex20[_0x3d0b[16]](_0x8e3ex2a- _0x8e3ex28));_0x8e3ex2a+= 1}}else {_0x8e3ex20[_0x3d0b[15]](32);_0x8e3ex20[_0x3d0b[15]](_0x8e3ex26^ 0x80)}}}}};return _0x8e3ex20};var MobiFile=function(){function MobiFile(_0x8e3ex24){_classCallCheck(this,MobiFile);this[_0x3d0b[23]]= new DataView(_0x8e3ex24);this[_0x3d0b[20]]= this[_0x3d0b[23]][_0x3d0b[20]];this[_0x3d0b[24]]= 0;this[_0x3d0b[25]]= null}_createClass(MobiFile,[{key:_0x3d0b[26],value:function _0x8e3ex2c(){}},{key:_0x3d0b[27],value:function _0x8e3ex2d(){var _0x8e3ex2e=this[_0x3d0b[23]][_0x3d0b[27]](this[_0x3d0b[24]]);this[_0x3d0b[24]]+= 1;return _0x8e3ex2e}},{key:_0x3d0b[28],value:function _0x8e3ex2f(){var _0x8e3ex2e=this[_0x3d0b[23]][_0x3d0b[28]](this[_0x3d0b[24]]);this[_0x3d0b[24]]+= 2;return _0x8e3ex2e}},{key:_0x3d0b[29],value:function _0x8e3ex30(){var _0x8e3ex2e=this[_0x3d0b[23]][_0x3d0b[29]](this[_0x3d0b[24]]);this[_0x3d0b[24]]+= 4;return _0x8e3ex2e}},{key:_0x3d0b[30],value:function _0x8e3ex31(_0x8e3ex18){var _0x8e3ex2e=ab2str(this[_0x3d0b[20]][_0x3d0b[22]](this[_0x3d0b[24]],this[_0x3d0b[24]]+ _0x8e3ex18));this[_0x3d0b[24]]+= _0x8e3ex18;return _0x8e3ex2e}},{key:_0x3d0b[31],value:function _0x8e3ex32(_0x8e3ex18){this[_0x3d0b[24]]+= _0x8e3ex18}},{key:_0x3d0b[32],value:function _0x8e3ex33(_0x8e3ex34){this[_0x3d0b[24]]= _0x8e3ex34}},{key:_0x3d0b[33],value:function _0x8e3ex35(_0x8e3ex24,_0x8e3ex36){var _0x8e3ex37=_0x8e3ex24[_0x3d0b[0]]- 1;var _0x8e3ex38=0;for(var _0x8e3ex5=15;_0x8e3ex5> 0;_0x8e3ex5--){if(_0x8e3ex36& 1<< _0x8e3ex5){var _0x8e3ex39=this[_0x3d0b[34]](_0x8e3ex24,_0x8e3ex37);var _0x8e3ex18=_0x8e3ex39[0];var _0x8e3ex3a=_0x8e3ex39[1];_0x8e3ex37= _0x8e3ex39[2];_0x8e3ex37-= _0x8e3ex18- _0x8e3ex3a;_0x8e3ex38+= _0x8e3ex18}};if(_0x8e3ex36& 1){var _0x8e3ex3b=_0x8e3ex24[_0x8e3ex37];_0x8e3ex38+= (_0x8e3ex3b& 0x3)+ 1};return _0x8e3ex38}},{key:_0x3d0b[34],value:function _0x8e3ex3c(_0x8e3ex24,_0x8e3ex37){var _0x8e3ex3a=0;var _0x8e3ex18=0;var _0x8e3ex3d=0;var _0x8e3ex3e=0x7f;var _0x8e3ex3f=0x80;var _0x8e3ex40=0;for(var _0x8e3ex5=0;;_0x8e3ex5++){var _0x8e3ex12=_0x8e3ex24[_0x8e3ex37];_0x8e3ex18|= (_0x8e3ex12& _0x8e3ex3e)<< _0x8e3ex40;_0x8e3ex40+= 7;_0x8e3ex3a+= 1;_0x8e3ex3d+= 1;_0x8e3ex37-= 1;var _0x8e3ex41=_0x8e3ex12& _0x8e3ex3f;if(_0x8e3ex3d>= 4|| _0x8e3ex41> 0){break}};return [_0x8e3ex18,_0x8e3ex3a,_0x8e3ex37]}},{key:_0x3d0b[35],value:function _0x8e3ex42(){var _0x8e3ex43=this[_0x3d0b[37]][_0x3d0b[36]];var _0x8e3ex1e=[];for(var _0x8e3ex5=1;_0x8e3ex5<= _0x8e3ex43;_0x8e3ex5++){_0x8e3ex1e[_0x3d0b[14]](this[_0x3d0b[38]](_0x8e3ex5))};var _0x8e3ex44=combine_uint8array(_0x8e3ex1e);return ab2str(_0x8e3ex44)}},{key:_0x3d0b[38],value:function _0x8e3ex45(_0x8e3ex5){var _0x8e3ex36=this[_0x3d0b[40]][_0x3d0b[39]];var _0x8e3ex46=this[_0x3d0b[41]][_0x8e3ex5][_0x3d0b[24]];var _0x8e3ex47=this[_0x3d0b[41]][_0x8e3ex5+ 1][_0x3d0b[24]];var _0x8e3ex24= new Uint8Array(this[_0x3d0b[20]][_0x3d0b[22]](_0x8e3ex46,_0x8e3ex47));var _0x8e3ex48=this[_0x3d0b[33]](_0x8e3ex24,_0x8e3ex36);_0x8e3ex24= new Uint8Array(this[_0x3d0b[20]][_0x3d0b[22]](_0x8e3ex46,_0x8e3ex47- _0x8e3ex48));if(this[_0x3d0b[37]][_0x3d0b[42]]=== 2){var _0x8e3ex20=uncompression_lz77(_0x8e3ex24);return _0x8e3ex20[_0x3d0b[18]]()}else {return _0x8e3ex24}}},{key:_0x3d0b[43],value:function _0x8e3ex49(_0x8e3ex15){var _0x8e3ex4a=this[_0x3d0b[40]][_0x3d0b[44]];var _0x8e3ex46=this[_0x3d0b[41]][_0x8e3ex4a+ _0x8e3ex15][_0x3d0b[24]];var _0x8e3ex47=this[_0x3d0b[41]][_0x8e3ex4a+ _0x8e3ex15+ 1][_0x3d0b[24]];var _0x8e3ex24= new Uint8Array(this[_0x3d0b[20]][_0x3d0b[22]](_0x8e3ex46,_0x8e3ex47));return new Blob([_0x8e3ex24[_0x3d0b[20]]])}},{key:_0x3d0b[45],value:function _0x8e3ex4b(){this[_0x3d0b[25]]= this[_0x3d0b[46]]();this[_0x3d0b[41]]= this[_0x3d0b[47]]();this[_0x3d0b[48]]()}},{key:_0x3d0b[46],value:function _0x8e3ex4c(){var _0x8e3ex4d={};_0x8e3ex4d[_0x3d0b[49]]= this[_0x3d0b[30]](32);_0x8e3ex4d[_0x3d0b[50]]= this[_0x3d0b[28]]();_0x8e3ex4d[_0x3d0b[51]]= this[_0x3d0b[28]]();_0x8e3ex4d[_0x3d0b[52]]= this[_0x3d0b[29]]();_0x8e3ex4d[_0x3d0b[53]]= this[_0x3d0b[29]]();_0x8e3ex4d[_0x3d0b[54]]= this[_0x3d0b[29]]();_0x8e3ex4d[_0x3d0b[55]]= this[_0x3d0b[29]]();_0x8e3ex4d[_0x3d0b[56]]= this[_0x3d0b[29]]();_0x8e3ex4d[_0x3d0b[57]]= this[_0x3d0b[29]]();_0x8e3ex4d[_0x3d0b[58]]= this[_0x3d0b[30]](4);_0x8e3ex4d[_0x3d0b[59]]= this[_0x3d0b[30]](4);_0x8e3ex4d[_0x3d0b[60]]= this[_0x3d0b[29]]();_0x8e3ex4d[_0x3d0b[61]]= this[_0x3d0b[29]]();_0x8e3ex4d[_0x3d0b[62]]= this[_0x3d0b[28]]();return _0x8e3ex4d}},{key:_0x3d0b[47],value:function _0x8e3ex4e(){var _0x8e3ex4f=[];for(var _0x8e3ex5=0;_0x8e3ex5< this[_0x3d0b[25]][_0x3d0b[62]];_0x8e3ex5++){var _0x8e3ex50={};_0x8e3ex50[_0x3d0b[24]]= this[_0x3d0b[29]]();_0x8e3ex50[_0x3d0b[50]]= this[_0x3d0b[29]]();_0x8e3ex4f[_0x3d0b[14]](_0x8e3ex50)};return _0x8e3ex4f}},{key:_0x3d0b[48],value:function _0x8e3ex51(){this[_0x3d0b[37]]= this[_0x3d0b[63]]();this[_0x3d0b[40]]= this[_0x3d0b[64]]()}},{key:_0x3d0b[63],value:function _0x8e3ex52(){var _0x8e3ex53={};var _0x8e3ex54=this[_0x3d0b[41]][0];this[_0x3d0b[32]](_0x8e3ex54[_0x3d0b[24]]);_0x8e3ex53[_0x3d0b[42]]= this[_0x3d0b[28]]();this[_0x3d0b[31]](2);_0x8e3ex53[_0x3d0b[65]]= this[_0x3d0b[29]]();_0x8e3ex53[_0x3d0b[36]]= this[_0x3d0b[28]]();_0x8e3ex53[_0x3d0b[66]]= this[_0x3d0b[28]]();_0x8e3ex53[_0x3d0b[67]]= this[_0x3d0b[28]]();this[_0x3d0b[31]](2);return _0x8e3ex53}},{key:_0x3d0b[64],value:function _0x8e3ex55(){var _0x8e3ex56={};var _0x8e3ex57=this[_0x3d0b[24]];_0x8e3ex56[_0x3d0b[68]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[69]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[70]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[71]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[60]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[72]]= this[_0x3d0b[29]]();this[_0x3d0b[31]](40);_0x8e3ex56[_0x3d0b[73]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[74]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[75]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[76]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[77]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[78]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[79]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[44]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[80]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[81]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[82]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[83]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[84]]= this[_0x3d0b[29]]();this[_0x3d0b[31]](36);_0x8e3ex56[_0x3d0b[85]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[86]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[87]]= this[_0x3d0b[29]]();_0x8e3ex56[_0x3d0b[88]]= this[_0x3d0b[29]]();this[_0x3d0b[31]](8);this[_0x3d0b[31]](4);this[_0x3d0b[31]](46);_0x8e3ex56[_0x3d0b[39]]= this[_0x3d0b[28]]();this[_0x3d0b[32]](_0x8e3ex57+ _0x8e3ex56[_0x3d0b[69]]);return _0x8e3ex56}},{key:_0x3d0b[89],value:function _0x8e3ex58(){return {}}},{key:_0x3d0b[90],value:function _0x8e3ex59(_0x8e3ex5a){this[_0x3d0b[45]]();var _0x8e3ex5b=this[_0x3d0b[35]]();var _0x8e3ex5c=document[_0x3d0b[91]](_0x8e3ex5a);while(_0x8e3ex5c[_0x3d0b[92]]){_0x8e3ex5c[_0x3d0b[93]](_0x8e3ex5c[_0x3d0b[92]])};var _0x8e3ex5d=domParser[_0x3d0b[95]](_0x8e3ex5b,_0x3d0b[94]);_0x8e3ex5d[_0x3d0b[99]][_0x3d0b[98]][_0x3d0b[97]](function(_0x8e3ex5e){if(_0x8e3ex5e instanceof Element){_0x8e3ex5c[_0x3d0b[96]](_0x8e3ex5e)}});var _0x8e3ex5f=_0x8e3ex5c[_0x3d0b[101]](_0x3d0b[100]);for(var _0x8e3ex5=0;_0x8e3ex5< _0x8e3ex5f[_0x3d0b[0]];_0x8e3ex5++){this[_0x3d0b[102]](_0x8e3ex5f,_0x8e3ex5)}}},{key:_0x3d0b[102],value:function _0x8e3ex60(_0x8e3ex5f,_0x8e3ex5){var _0x8e3ex61=_0x8e3ex5f[_0x8e3ex5];var _0x8e3ex15=+_0x8e3ex61[_0x3d0b[104]](_0x3d0b[103]);var _0x8e3ex62=this[_0x3d0b[43]](_0x8e3ex15- 1);var _0x8e3ex63= new FileReader();_0x8e3ex63[_0x3d0b[105]]= function(_0x8e3ex64){_0x8e3ex61[_0x3d0b[106]]= _0x8e3ex64[_0x3d0b[108]][_0x3d0b[107]]};_0x8e3ex63[_0x3d0b[109]](_0x8e3ex62)}}]);return MobiFile}()
--------------------------------------------------------------------------------
/application/public/opds-opensearch.xml:
--------------------------------------------------------------------------------
1 |
2 | Библиотека
3 | Библиотека
4 |
5 |
6 |
7 | /opds/search
8 | Библиотека
9 | /favicon.ico
10 |
11 |
12 | open
13 | false
14 | *
15 | UTF-8
16 | UTF-8
17 |
18 |
--------------------------------------------------------------------------------
/application/public/opds-opensearch.xml.php:
--------------------------------------------------------------------------------
1 |
5 |
Библиотека
6 |
Библиотека
7 |
8 |
9 |
10 |
$webroot/opds/search
11 |
Библиотека
12 |
/favicon.ico
13 |
14 |
15 |
open
16 |
false
17 |
*
18 |
UTF-8
19 |
UTF-8
20 |
21 | __HTML
22 | ?>
--------------------------------------------------------------------------------
/application/public/save_position.php:
--------------------------------------------------------------------------------
1 | prepare("DELETE FROM progress WHERE user_uuid=:uuid AND bookid=:id");
18 | $stmt->bindParam(":uuid", $user_uuid);
19 | $stmt->bindParam(":id", $bookid);
20 | $stmt->execute();
21 | die();
22 | }
23 |
24 | $stmt = $dbh->prepare("INSERT INTO progress (user_uuid, bookid, pos) VALUES (:uuid, :id, :pos) ON CONFLICT(user_uuid, bookid) DO UPDATE set pos=:pos2");
25 | $stmt->bindParam(":uuid", $user_uuid);
26 | $stmt->bindParam(":id", $bookid);
27 | $stmt->bindParam(":pos", $pos);
28 | $stmt->bindParam(":pos2", $pos);
29 | $stmt->execute();
30 |
--------------------------------------------------------------------------------
/application/public/usr.php:
--------------------------------------------------------------------------------
1 | prepare("SELECT libbook.Title BookTitle, libfilename.filename, libbook.filetype,
11 | CONCAT(libavtorname.LastName, ' ', libavtorname.FirstName) author_name
12 | FROM libbook
13 | LEFT JOIN libavtor USING(BookId)
14 | LEFT JOIN libfilename USING(BookId)
15 | LEFT JOIN libavtorname USING(AvtorId)
16 | WHERE libbook.BookId=:id");
17 | $stmt->bindParam(":id", $id);
18 | $stmt->execute();
19 | $book = $stmt->fetch();
20 |
21 |
22 | $stmt = $dbh->prepare("SELECT * FROM book_zip WHERE $id BETWEEN start_id AND end_id AND usr=1");
23 | $stmt->execute();
24 | $zip_name = $stmt->fetch()->filename;
25 | $zip = new ZipArchive();
26 |
27 | if ($zip->open(ROOT_PATH . "flibusta/" . $zip_name)) {
28 | $filename = $book->author_name . " - " . $book->booktitle . " " . $id . "." . $book->filename . "." . trim($book->filetype);
29 | header('Content-Description: File Transfer');
30 | header('Content-Type: application/octet-stream');
31 | header('Content-Disposition: attachment; filename=' . basename(rawurlencode($filename)));
32 | header('Content-Transfer-Encoding: binary');
33 | header('Expires: 0');
34 | header('Cache-Control: must-revalidate');
35 | header('Pragma: public');
36 |
37 | if (isset($book->filename)) {
38 | echo $zip->getFromName($book->filename);
39 | } else {
40 | echo $zip->getFromName("$id." . trim($book->filetype));
41 | }
42 | $zip->close();
43 | } else {
44 | echo "NO ZIP";
45 | }
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/application/public/webfonts/fa-brands-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/webfonts/fa-brands-400.eot
--------------------------------------------------------------------------------
/application/public/webfonts/fa-brands-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/webfonts/fa-brands-400.ttf
--------------------------------------------------------------------------------
/application/public/webfonts/fa-brands-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/webfonts/fa-brands-400.woff
--------------------------------------------------------------------------------
/application/public/webfonts/fa-brands-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/webfonts/fa-brands-400.woff2
--------------------------------------------------------------------------------
/application/public/webfonts/fa-regular-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/webfonts/fa-regular-400.eot
--------------------------------------------------------------------------------
/application/public/webfonts/fa-regular-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/webfonts/fa-regular-400.ttf
--------------------------------------------------------------------------------
/application/public/webfonts/fa-regular-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/webfonts/fa-regular-400.woff
--------------------------------------------------------------------------------
/application/public/webfonts/fa-regular-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/webfonts/fa-regular-400.woff2
--------------------------------------------------------------------------------
/application/public/webfonts/fa-solid-900.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/webfonts/fa-solid-900.eot
--------------------------------------------------------------------------------
/application/public/webfonts/fa-solid-900.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/webfonts/fa-solid-900.ttf
--------------------------------------------------------------------------------
/application/public/webfonts/fa-solid-900.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/webfonts/fa-solid-900.woff
--------------------------------------------------------------------------------
/application/public/webfonts/fa-solid-900.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/application/public/webfonts/fa-solid-900.woff2
--------------------------------------------------------------------------------
/application/renderer.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | description != '') {
11 | echo "
";
12 | }
13 |
14 | if ($url->title != '') {
15 | $title = $url->title;
16 | } else {
17 | $title = 'Библиотека';
18 | }
19 | echo "
$title ";
20 | include_once(ROOT_PATH . 'webroot.php');
21 | echo <<< __HTML
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | __HTML
31 | ?>
32 |
58 |
59 |
60 | mod) {
69 | case '':
70 | $c1 = 'active';
71 | break;
72 | case 'genres':
73 | $c2 = 'active';
74 | break;
75 | case 'genres':
76 | $c3 = 'active';
77 | break;
78 | case 'authors':
79 | $c4 = 'active';
80 | break;
81 | case 'fav':
82 | $c5 = 'active';
83 | break;
84 | case 'service':
85 | $c6 = 'active';
86 | break;
87 | default:
88 | $c1 = 'active';
89 | }
90 |
91 |
92 |
93 | echo <<< __HTML
94 |
95 |
96 |
97 |
122 |
123 |
124 | module)) {
126 | // echo "
$url->title ";
127 | include($url->module);
128 | } else {
129 | echo 'Раздел не найден', 'Вы ввели неверный адрес, либо раздел находится в разработке.';
130 | header("HTTP/1.0 404 Not Found");
131 | }
132 | ?>
133 |
134 |
135 |
136 |
137 |
138 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
--------------------------------------------------------------------------------
/application/tools/app_db_converter.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Fixes a MySQL dump made with the right format so it can be directly
5 | imported to a new PostgreSQL database.
6 |
7 | Dump using:
8 | mysqldump --compatible=postgresql --default-character-set=utf8 -r databasename.mysql -u root databasename
9 | """
10 |
11 | import re
12 | import sys
13 | import os
14 | import time
15 | import subprocess
16 |
17 |
18 | def parse(input_filename, output_filename):
19 | "Feed it a file, and it'll output a fixed one"
20 |
21 | # State storage
22 | if input_filename == "-":
23 | num_lines = -1
24 | else:
25 | num_lines = int(subprocess.check_output(["wc", "-l", input_filename]).strip().split()[0])
26 | tables = {}
27 | current_table = None
28 | creation_lines = []
29 | enum_types = []
30 | foreign_key_lines = []
31 | fulltext_key_lines = []
32 | sequence_lines = []
33 | cast_lines = []
34 | num_inserts = 0
35 | started = time.time()
36 |
37 | # Open output file and write header. Logging file handle will be stdout
38 | # unless we're writing output to stdout, in which case NO PROGRESS FOR YOU.
39 | if output_filename == "-":
40 | output = sys.stdout
41 | logging = open(os.devnull, "w")
42 | else:
43 | output = open(output_filename, "w")
44 | logging = sys.stdout
45 |
46 | if input_filename == "-":
47 | input_fh = sys.stdin
48 | else:
49 | input_fh = open(input_filename)
50 |
51 |
52 | output.write("-- Converted by db_converter\n")
53 | output.write("START TRANSACTION;\n")
54 | output.write("SET standard_conforming_strings=off;\n")
55 | output.write("SET escape_string_warning=off;\n")
56 | output.write("SET CONSTRAINTS ALL DEFERRED;\n\n")
57 |
58 | for i, line in enumerate(input_fh):
59 | time_taken = time.time() - started
60 | percentage_done = (i+1) / float(num_lines)
61 | secs_left = (time_taken / percentage_done) - time_taken
62 | logging.write("\rLine %i (of %s: %.2f%%) [%s tables] [%s inserts] [ETA: %i min %i sec]" % (
63 | i + 1,
64 | num_lines,
65 | ((i+1)/float(num_lines))*100,
66 | len(tables),
67 | num_inserts,
68 | secs_left // 60,
69 | secs_left % 60,
70 | ))
71 | logging.flush()
72 | line = line.strip().replace(r"\\", "WUBWUBREALSLASHWUB").replace(r"\'", "''").replace("WUBWUBREALSLASHWUB", r"\\")
73 | # Ignore comment lines
74 | if line.startswith("--") or line.startswith("/*") or line.startswith("LOCK TABLES") or line.startswith("DROP TABLE") or line.startswith("UNLOCK TABLES") or not line:
75 | continue
76 |
77 | # Outside of anything handling
78 | if current_table is None:
79 | # Start of a table creation statement?
80 | if line.startswith("CREATE TABLE"):
81 | current_table = line.split('"')[1]
82 | tables[current_table] = {"columns": []}
83 | creation_lines = []
84 | # Inserting data into a table?
85 | elif line.startswith("INSERT INTO"):
86 | output.write(line.replace("'0000-00-00 00:00:00'", "NULL") + "\n")
87 | num_inserts += 1
88 | # ???
89 | elif line.startswith("TRUNCATE"):
90 | output.write(line.replace("'0000-00-00 00:00:00'", "NULL") + "\n")
91 | num_inserts += 1
92 | else:
93 | print("\n ! Unknown line in main body: {}".format(line))
94 |
95 | # Inside-create-statement handling
96 | else:
97 | # Is it a column?
98 | if line.startswith('"'):
99 | useless, name, definition = line.strip(",").split('"',2)
100 | try:
101 | type, extra = definition.strip().split(" ", 1)
102 |
103 | # This must be a tricky enum
104 | if ')' in extra:
105 | type, extra = definition.strip().split(")")
106 |
107 | except ValueError:
108 | type = definition.strip()
109 | extra = ""
110 | extra = re.sub(r"CHARACTER SET [\w\d]+\s*", "", extra.replace("unsigned", ""))
111 | extra = re.sub(r"COLLATE [\w\d]+\s*", "", extra.replace("unsigned", ""))
112 |
113 | # See if it needs type conversion
114 | final_type = None
115 | set_sequence = None
116 | if type.startswith("tinyint("):
117 | type = "int4"
118 | set_sequence = True
119 | final_type = "boolean"
120 | elif type.startswith("int("):
121 | type = "integer"
122 | set_sequence = True
123 | elif type.startswith("bigint("):
124 | type = "bigint"
125 | set_sequence = True
126 | elif type == "longtext":
127 | type = "text"
128 | elif type == "mediumtext":
129 | type = "text"
130 | elif type == "tinytext":
131 | type = "text"
132 | elif type.startswith("varchar("):
133 | size = int(type.split("(")[1].rstrip(")"))
134 | type = "varchar(%s)" % (size * 2)
135 | elif type.startswith("smallint("):
136 | type = "int2"
137 | set_sequence = True
138 | elif type == "datetime":
139 | type = "timestamp with time zone"
140 | elif type == "double":
141 | type = "double precision"
142 | elif type.endswith("blob"):
143 | type = "bytea"
144 | elif type.startswith("enum(") or type.startswith("set("):
145 |
146 | types_str = type.split("(")[1].rstrip(")").rstrip('"')
147 | types_arr = [type_str.strip('\'') for type_str in types_str.split(",")]
148 |
149 | # Considered using values to make a name, but its dodgy
150 | # enum_name = '_'.join(types_arr)
151 | enum_name = "{0}_{1}".format(current_table, name)
152 |
153 | if enum_name not in enum_types:
154 | output.write("CREATE TYPE {0} AS ENUM ({1}); \n".format(enum_name, types_str));
155 | enum_types.append(enum_name)
156 |
157 | type = enum_name
158 |
159 | if final_type:
160 | cast_lines.append("ALTER TABLE \"%s\" ALTER COLUMN \"%s\" DROP DEFAULT, ALTER COLUMN \"%s\" TYPE %s USING CAST(\"%s\" as %s)" % (current_table, name, name, final_type, name, final_type))
161 | # ID fields need sequences [if they are integers?]
162 | if name == "id" and set_sequence is True:
163 | sequence_lines.append("CREATE SEQUENCE %s_id_seq" % (current_table))
164 | sequence_lines.append("SELECT setval('%s_id_seq', max(id)) FROM %s" % (current_table, current_table))
165 | sequence_lines.append("ALTER TABLE \"%s\" ALTER COLUMN \"id\" SET DEFAULT nextval('%s_id_seq')" % (current_table, current_table))
166 | # Record it
167 | creation_lines.append('"%s" %s %s' % (name, type, extra))
168 | tables[current_table]['columns'].append((name, type, extra))
169 | # Is it a constraint or something?
170 | elif line.startswith("PRIMARY KEY"):
171 | creation_lines.append(line.rstrip(","))
172 | elif line.startswith("CONSTRAINT"):
173 | foreign_key_lines.append("ALTER TABLE \"%s\" ADD CONSTRAINT %s DEFERRABLE INITIALLY DEFERRED" % (current_table, line.split("CONSTRAINT")[1].strip().rstrip(",")))
174 | foreign_key_lines.append("CREATE INDEX ON \"%s\" %s" % (current_table, line.split("FOREIGN KEY")[1].split("REFERENCES")[0].strip().rstrip(",")))
175 | elif line.startswith("UNIQUE KEY"):
176 | creation_lines.append("UNIQUE (%s)" % line.split("(")[1].split(")")[0])
177 | elif line.startswith("FULLTEXT KEY"):
178 |
179 | fulltext_keys = " || ' ' || ".join( line.split('(')[-1].split(')')[0].replace('"', '').split(',') )
180 | fulltext_key_lines.append("CREATE INDEX ON %s USING gin(to_tsvector('english', %s))" % (current_table, fulltext_keys))
181 |
182 | elif line.startswith("KEY"):
183 | pass
184 | # Is it the end of the table?
185 | elif line == ");":
186 | output.write("CREATE TABLE \"%s\" (\n" % current_table)
187 | for i, line in enumerate(creation_lines):
188 | output.write(" %s%s\n" % (line, "," if i != (len(creation_lines) - 1) else ""))
189 | output.write(');\n\n')
190 | current_table = None
191 | # ???
192 | else:
193 | print("\n ! Unknown line inside table creation: {}".format(line))
194 |
195 |
196 | # Finish file
197 | output.write("\n-- Post-data save --\n")
198 | output.write("COMMIT;\n")
199 | output.write("START TRANSACTION;\n")
200 |
201 | # Write typecasts out
202 | output.write("\n-- Typecasts --\n")
203 | for line in cast_lines:
204 | output.write("%s;\n" % line)
205 |
206 | # Write FK constraints out
207 | output.write("\n-- Foreign keys --\n")
208 | for line in foreign_key_lines:
209 | output.write("%s;\n" % line)
210 |
211 | # Write sequences out
212 | output.write("\n-- Sequences --\n")
213 | for line in sequence_lines:
214 | output.write("%s;\n" % line)
215 |
216 | # Write full-text indexkeyses out
217 | output.write("\n-- Full Text keys --\n")
218 | for line in fulltext_key_lines:
219 | output.write("%s;\n" % line)
220 |
221 | # Finish file
222 | output.write("\n")
223 | output.write("COMMIT;\n")
224 | print("")
225 |
226 |
227 | if __name__ == "__main__":
228 | parse(sys.argv[1], sys.argv[2])
229 |
--------------------------------------------------------------------------------
/application/tools/app_import_sql.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | source /application/tools/dbinit.sh
3 |
4 | mkdir -p /application/sql/psql
5 | mkdir -p /application/cache/authors
6 | mkdir -p /application/cache/covers
7 | mkdir -p /application/cache/tmp
8 |
9 | echo "Распаковка sql.gz">/application/sql/status
10 | gzip -f -d /application/sql/*.gz
11 |
12 | /application/tools/app_topg lib.a.annotations_pics.sql
13 | /application/tools/app_topg lib.b.annotations_pics.sql
14 | /application/tools/app_topg lib.a.annotations.sql
15 | /application/tools/app_topg lib.b.annotations.sql
16 | /application/tools/app_topg lib.libavtorname.sql
17 | /application/tools/app_topg lib.libavtor.sql
18 | /application/tools/app_topg lib.libbook.sql
19 | /application/tools/app_topg lib.libfilename.sql
20 | /application/tools/app_topg lib.libgenrelist.sql
21 | /application/tools/app_topg lib.libgenre.sql
22 | /application/tools/app_topg lib.libjoinedbooks.sql
23 | /application/tools/app_topg lib.librate.sql
24 | /application/tools/app_topg lib.librecs.sql
25 | /application/tools/app_topg lib.libseqname.sql
26 | /application/tools/app_topg lib.libseq.sql
27 | /application/tools/app_topg lib.libtranslator.sql
28 | /application/tools/app_topg lib.reviews.sql
29 |
30 | echo "Подчистка БД. Стираем авторов, серии и жанры у которых нет ни одной книги" >>/application/sql/status
31 | $SQL_CMD -f /application/tools/cleanup_db.sql
32 |
33 | echo "Обновление полнотекстовых индексов">>/application/sql/status
34 | $SQL_CMD -f /application/tools/update_vectors.sql
35 |
36 | echo "Создание индекса zip-файлов">>/application/sql/status
37 | php /application/tools/app_update_zip_list.php
38 |
39 | echo "">/application/sql/status
40 |
41 |
--------------------------------------------------------------------------------
/application/tools/app_reindex.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | echo "Создание индекса zip-файлов">>/application/sql/status
3 | php /application/tools/app_update_zip_list.php
4 |
5 | echo "">/application/sql/status
6 |
7 |
8 |
--------------------------------------------------------------------------------
/application/tools/app_topg:
--------------------------------------------------------------------------------
1 | #/bin/sh
2 | echo "Конвертация $1">>/application/sql/status
3 | if ! grep -q INSERT "/application/sql/$1"; then
4 | echo "Empty table">>/application/sql/status;
5 | exit 1
6 | fi
7 |
8 |
9 |
10 | xtable="cat /application/sql/$1|grep 'CREATE TABLE'|awk '{print \$3}'| sed 's/^.//;s/.$//'"
11 | table=$(eval "$xtable")
12 |
13 | echo $1
14 | echo "TRUNCATE $table;">/application/sql/tmp.sql
15 | echo $table
16 | cat /application/sql/$1|grep INSERT|tr -d \`|sed "s/$table/$table/g">>/application/sql/tmp.sql
17 | /application/tools/app_db_converter.py /application/sql/tmp.sql /application/sql/psql/$1
18 | rm /application/sql/tmp.sql
19 |
20 | echo "Импорт $1">>/application/sql/status
21 | $SQL_CMD -f /application/sql/psql/$1
22 |
23 |
--------------------------------------------------------------------------------
/application/tools/app_update_zip_list.php:
--------------------------------------------------------------------------------
1 | prepare("TRUNCATE book_zip;");
7 | $stmt->execute();
8 |
9 | $dbh->beginTransaction();
10 |
11 | while (false !== ($entry = readdir($handle))) {
12 | if (strpos($entry, "-") !== false && strpos($entry, ".zip") !== false && substr($entry, -9) !== ".zip.part") {
13 | $dt = str_replace(".zip", "", $entry);
14 | $dt = str_replace("f.n.", "f.n-", $dt);
15 | $dt = str_replace("f.fb2.", "f.n-", $dt);
16 | echo "[$dt]";
17 | $fn = explode("-", $dt);
18 | $u = 1;
19 | if (strpos($entry, "fb2") !== false) {
20 | $u = 0;
21 | }
22 | if (strpos($entry, "d.fb2-009") !== false) {
23 | } else {
24 | $stmt = $dbh->prepare("INSERT INTO book_zip (filename, start_id, end_id, usr) VALUES (:fn, :start, :end, :usr)");
25 | $stmt->bindParam(":fn", $entry);
26 | $stmt->bindParam(":start", $fn[1]);
27 | $stmt->bindParam(":end", $fn[2]);
28 | $stmt->bindParam(":usr", $u);
29 | $stmt->execute();
30 | }
31 | }
32 | echo "\n";
33 | }
34 | $dbh->commit();
35 | closedir($handle);
36 | }
37 |
--------------------------------------------------------------------------------
/application/tools/cleanup_db.sql:
--------------------------------------------------------------------------------
1 | delete from libgenrelist where not exists (select 1 from libgenre where libgenrelist.genreid = libgenre.genreid);
2 | delete from libseqname where not exists ( select 1 from libseq where libseqname.seqid = libseq.seqid);
3 | delete from libavtorname where not exists (select 1 from libavtor where libavtorname.avtorid = libavtor.avtorid);
4 |
--------------------------------------------------------------------------------
/application/tools/dbinit.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | if [ -z "$FLIBUSTA_DBNAME" ]; then
4 | export FLIBUSTA_DBNAME=flibusta
5 | fi
6 |
7 | if [ -z "$FLIBUSTA_DBHOST" ]; then
8 | export FLIBUSTA_DBHOST=postgres
9 | fi
10 |
11 | if [ -z "$FLIBUSTA_DBUSER" ]; then
12 | export FLIBUSTA_DBUSER=flibusta
13 | fi
14 |
15 | if [ -z "$FLIBUSTA_DBTYPE" ] || [ "$FLIBUSTA_DBTYPE" == 'postgres' ]; then
16 | export SQL_CMD="psql -h $FLIBUSTA_DBHOST -d $FLIBUSTA_DBNAME -U $FLIBUSTA_DBUSER"
17 | export SQL_PASSWORD_VAR=PGPASSWORD
18 |
19 | if [ ! -z "$FLIBUSTA_DBPASSWORD_FILE" ] && [ -e $FLIBUSTA_DBPASSWORD_FILE ]; then
20 | FPGPASSWORD=`cat $FLIBUSTA_DBPASSWORD_FILE`
21 | fi
22 |
23 | if [ ! -z "$FLIBUSTA_DBPASSWORD" ] && [ -z "$FPGPASSWORD" ]; then
24 | FPGPASSWORD=$FLIBUSTA_DBPASSWORD
25 | fi
26 |
27 | if [ ! -z "$FPGPASSWORD" ]; then
28 | export PGPASSWORD=$FPGPASSWORD
29 | fi
30 |
31 | if [ -z "$PGPASSWORD" ]; then
32 | export PGPASSWORD=flibusta
33 | fi
34 | fi
35 |
--------------------------------------------------------------------------------
/application/tools/external_services_config/README.md:
--------------------------------------------------------------------------------
1 | # Конфигурация docker container для работы с reverse proxy и внешним сервером базы данных
2 |
3 | ## Почему Вы можете предпочесть такую конфигурацию
4 |
5 | Главное преимущество конфигурации с reverse proxy и внешним сервером базы данных- это экономия ресурсов. Как правило ресурсы NAS довольно ограничены, а дополнительные процессы потребляют память и CPU которому вероятно есть более полезное применение.
6 |
7 | "Обычный" docker-compose.yaml определяет 3 сервиса, бекенд на php-fpm , база данных Postgres и nginx в качестве front end. Вместо 2 последних можно использовать существующие сервисы, если они есть. Сервисы не зависят друг от друга, так что можмо "экстернализаровать" оба или только один.
8 |
9 | ## Работа с внешней Postgres базой данных.
10 | Есть 2 главных отличия в конфигурации внешней и "внутренней" базы данных.
11 | 1. При использовании внутренней базы данных для траффика между бекендом о БД используется default netwrok автоматически определяемая Docker engine для каждого docker-compose file. Если БД определена в другом файле, нужно явным образом разрешить коммуникацию межды сервисами. Это делается с помощью explicite network, в [docker-compose.yaml](docker-compose.yaml) из этой директории такой сетью служит postgres_db_net. Сеть с таким же именем дожна быть определана в файле определения сервиса постгресс и эта сеть должна быть прописана в списке сетей для сервиса (конфигурация практически идентична той что есть в примере в этой директории). В таком случае можно создать сеть отдельно, с помощью docker network create (Кроме того во многих GUI/ web interface есть возможность определить такую сеть без command line). Затем можно определить ее как external во всех релевантных docker compose files..
12 | 2. Образ созданный в главном docker-compose, определяет юзера БД, таблицы, индексы и т.д. во время создания image. В случае с внешней базой все необходимое должно быть создано при запуске контейнера бекенда Флибусты. Для этого слижит скрипт flibusta_entrypoint.sh . Скрипт проверяет есть ли postgres account определенный как FLIBUSTA_DBUSER в environment docker_compose.yml (default - account flibusta, password - flibusta). Если удается подключиться с таким юзером к БД, скрипт считает что инитиализация уже состоялась при прошлых запусках. Если такая попытка не успешна, скрипт пытается инитиализировать нужные обьекты : создается счет с именем из переменной окружения FLIBUSTA_DBUSER ( default flibusta) и паролем из /run/secrets/FLIBUSTA_PWD, создается база данных и в ней все нужные таблицы, индексы и т.д. Создание нового счета и базы данных - это привeлигированные опреации, для них используется счет с именем из POSTGRES_ADMIN_USER (default - postgres) и паролем из фаила указанного в POSTGRES_ADMIN_DBPASSWORD_FILE . Проверьте что этот account имеет необходимые grants... Административный account используется толкько в скрипте и только если скрипт решает что инициализация необходима. После успешной инициализации можно заменить пароль в POSTGRES_ADMIN_DBPASSWORD_FILE на неправильный если Вы боитесь компрометации этого счета.
13 |
14 |
15 | ## Работа с reverse proxy
16 |
17 | Существуют 2 наиболее распространненых типа подключения к reverse proxy : subdomain и subdir . При подключении как subdomain, ресурс ( в данном случае библиотека) для адреса https://example.com будет доступна как https://mylib.example.com/ . При подключении как subdir адрес библиотеки https://example.com/mylib. Второй вариант конфигурации ПМСМ сложнее, и поэтому здесь обьясняется именно он.
18 |
19 | В качестве reverse proxy в примере в данной директории используется nginx . Если у Вас другой reverse proxy, вместо nginx конфигурации flibusta.conf Вам нужно будет использовать конфигурационные файлы специфичные для Вашего proxy.
20 | В конфигурации в этой директории используется вариант subdir. Для адреса она будет доступна как https://addres of my server/mylib .
21 |
22 | Для конфигурации используются следующие значения
23 | 1. /mylib - путь до "корня" библиотеки. Определяется переменной FLIBUSTA_WEBROOT в environment сервиса flibusta-fpm в docker_compose.yml
24 | 2. flibusta_net - сеть по которой backend и reverse proxy связываются, и определяется subnet 172.101.0.0/16
25 | 3. 172.101.0.101 адрес бекенда ( должен быть адресом в сети из предыдущего пункта), задается параметром ipv4_address сервиса flibusta-fpm
26 | 4. 192.168.1.0/24 -локальная сеть . Это значение используется для контроля доступа ( см. обсуждение ниже) в директиве
27 | ```
28 | allow 192.168.1.0/24;
29 | ```
30 | в конфигурации flibusta.conf для nginx.
31 | 5. Файлы из application/public доступны в докер контейнере nginx как /srv/mylib
32 |
33 | Шаги для конфигурации работы с reverse proxy
34 | 1. Создайте docker netwrork с именем flibusta_net и subnet 172.101.0.0/16 . Важно чтобы subnet соответствовал адресу flibusta-fpm, который прописан в nginx конфигурационном файле flibusta.conf. Добавьте эту сеть в докер контейнер nginx как external (похоже на то как она определена в docker-compose.yml из этой директории)
35 | 2. Добавьте volume /srv/mylib :
36 |
37 | ```
38 | -
/flibusta/application/public:/srv/mylib:v,ro
39 | ```
40 | 3. Добавьте (предпологается что конфигурация внутри докера находится в /config/nginx, если нет, например часто бывает /etc/etc/config/nginx , соответственно измените mount)
41 |
42 | ```
43 | - /flibusta/application/tools/external_services_config/flibusta.conf:/config/nginx/flibusta.conf:v,ro
44 | ```
45 | и сделайте include конфиг файла flibusta.conf в server блок в конфигурации nginx, скорее всего конфигурация находится в /config/nginx/site-confs/default.conf или /etc/config/nginx/site-conf/default.conf
46 |
47 | ```
48 | # main server block
49 | server {
50 |
51 | listen 443 ssl default_server;
52 | listen [::]:443 ssl default_server;
53 | http2 on;
54 |
55 | .......................
56 |
57 | location {
58 |
59 | }
60 |
61 | location {
62 |
63 | }
64 |
65 | include /config/nginx/flibusta.conf;
66 |
67 | .......
68 |
69 | }
70 | ```
71 |
72 | ## Доступ к Вашему зеркалу Флибусты
73 |
74 | reverse proxy скорее всего дает доступ из интернета к Вашим сервисам ( он скорее всего и нужен чтобы был доступ к докер контейнерам на Вашем NAS). Я думаю , понятно, что предоставлять неконтролируемый доступ всему интернету к Вашему зеркалу Флибусты не очень хорошая идея. Nginx позволяет давать доступ к определенному ресурсу ( например к директории https://my address/mylib) только определенный IP адресам или только авторизированным пользователям. flibusta.conf ограничевает дотуп только локальными адресами ( из сети 192.168.1.0/24). Если subnet вашей домашней сети другой - соответственным образом измените файл. Для доступа к библеотеке из интернета для авторизованных пользователей проще всего воспользоваться механизмом Basic authenitcation ( htpassword) примерно так
75 | ```
76 | location ^~ /mylib {
77 | #...
78 | satisfy any;
79 | allow 192.168.1.0/24;
80 | deny all;
81 |
82 | auth_basic "Flibusta forever";
83 | auth_basic_user_file conf/htpasswd;
84 | ...
85 | }
86 | ```
87 |
88 |
--------------------------------------------------------------------------------
/application/tools/external_services_config/docker-compose.yml:
--------------------------------------------------------------------------------
1 | services:
2 |
3 | flibusta-fpm:
4 | build: phpdocker/php-fpm
5 | working_dir: /application
6 | container_name: flibusta-fpm
7 | environment:
8 | - PUID=${APPUSER_PUID}
9 | - PGID=${APPUSER_PGID}
10 | - TZ=${TIME_ZONE_VALUE}
11 | - FLIBUSTA_WEBROOT=/mylib
12 | - FLIBUSTA_DBUSER=flibusta
13 | - FLIBUSTA_DBNAME=flibusta
14 | - FLIBUSTA_DBTYPE=postgres
15 | - FLIBUSTA_DBHOST=postgresdb
16 | - FLIBUSTA_DBPASSWORD_FILE=/run/secrets/FLIBUSTA_PWD
17 | - POSTGRES_ADMIN_USER=postgres
18 | - POSTGRES_ADMIN_DBPASSWORD_FILE=/run/secrets/POSTGRES_ADMIN_PWD
19 | - DB_HOST_PINGS=3
20 | command: /application/tools/external_services_config/flibusta_entrypoint.sh
21 | networks:
22 | flibusta_net:
23 | ipv4_address: 172.101.0.101
24 | postgres_db_net:
25 | volumes:
26 | - './application:/application'
27 | - './cache:/application/cache'
28 | - './Flibusta.Net:/application/flibusta'
29 | - './FlibustaSQL:/application/sql'
30 | - './phpdocker/php-fpm/php-ini-overrides.ini:/usr/local/etc/php/conf.d/local-custom.ini'
31 | - './phpdocker/php-fpm/php-fpm.conf:/usr/local/etc/php-fpm.d/zz-php-fpm.conf'
32 | - './FlibustaSQL/lib.a.attached.zip:/application/cache/lib.a.attached.zip:ro'
33 | - './FlibustaSQL/lib.b.attached.zip:/application/cache/lib.b.attached.zip:ro'
34 | secrets:
35 | - FLIBUSTA_PWD
36 | - POSTGRES_ADMIN_PWD
37 |
38 | secrets:
39 | FLIBUSTA_PWD:
40 | file: ./secrets/flibusta_pwd.txt
41 | POSTGRES_ADMIN_PWD:
42 | file: ./secrets/postgres_admin_pwd.txt
43 |
44 | networks:
45 | postgres_db_net:
46 | external: true
47 | flibusta_net:
48 | external: true
49 |
--------------------------------------------------------------------------------
/application/tools/external_services_config/flibusta.conf:
--------------------------------------------------------------------------------
1 | location ^~ /mylib {
2 | allow 192.168.1.0/24;
3 | deny all;
4 | root /srv;
5 | index index.php;
6 | try_files $uri /mylib/index.php$is_args$args;
7 | if (!-e $request_filename) {
8 | rewrite ^.*$ /mylib/index.php last;
9 | }
10 | location ~ \.php$ {
11 | add_header 'Content-Security-Policy' 'worker-src * blob:';
12 |
13 | fastcgi_split_path_info ^\/mylib(.+?\.php)(.*)$;
14 | set $path_info $fastcgi_path_info;
15 |
16 | include fastcgi_params;
17 | fastcgi_param SCRIPT_FILENAME /application/public/$fastcgi_script_name;
18 | fastcgi_param PATH_INFO $path_info;
19 | fastcgi_param PATH_TRANSLATED /applicaition/public/$path_info;
20 | fastcgi_intercept_errors on;
21 | fastcgi_param PHP_VALUE "error_log=/var/log/nginx/application_php_errors.log";
22 | fastcgi_buffers 16 16k;
23 | fastcgi_buffer_size 32k;
24 | fastcgi_pass 172.101.0.101:9000;
25 | fastcgi_index index.php;
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/application/tools/external_services_config/flibusta_entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . /application/tools/dbinit.sh
3 |
4 | if [ -z "$DB_HOST_PINGS" ]; then
5 | DB_HOST_PINGS=3
6 | fi
7 |
8 | for i in `seq 1 $DB_HOST_PINGS`
9 | do
10 | ping -q -c 1 $FLIBUSTA_DBHOST
11 | EXITCODE=$?
12 | if [ $EXITCODE -eq 0 ]; then
13 | break
14 | fi
15 | if [ $i -lt $DB_HOST_PINGS ]; then
16 | sleep 1
17 | fi
18 | done
19 |
20 | if [ $EXITCODE -ne 0 ]; then
21 | echo $FLIBUSTA_DBHOST is unreachable, can not access DB, exiting
22 | exit 1
23 | fi
24 |
25 |
26 | if [ `$SQL_CMD -c "select 1 from pg_roles where rolname='flibusta'" | wc -l` -eq 0 ]; then
27 | echo attempt to connect to postgres db has failed. Trying to initialize the DB
28 |
29 | FLIBUSTA_DBPASSWORD=$PGPASSWORD
30 |
31 | if [ -z "$POSTGRES_ADMIN_USER" ]; then
32 | POSTGRES_ADMIN_USER=postgres
33 | fi
34 |
35 | if [ ! -z "$POSTGRES_ADMIN_DBPASSWORD_FILE" ] && [ -e $POSTGRES_ADMIN_DBPASSWORD_FILE ]; then
36 | TPOSTGRES_ADMIN_PASSWD=`cat $POSTGRES_ADMIN_DBPASSWORD_FILE`
37 | fi
38 | if [ ! -z "$TPOSTGRES_ADMIN_PASSWD" ]; then
39 | PGPASSWORD=$TPOSTGRES_ADMIN_PASSWD
40 | fi
41 |
42 | if [ ! -z "$POSTGRES_ADMIN_PASSWD" ]; then
43 | PGPASSWORD=$POSTGRES_ADMIN_PASSWD
44 | fi
45 |
46 | if [ -z "$PGPASSWORD" ]; then
47 | echo Attempt to initialize postgres DB has failed. Cant obtain PG admin password
48 | exit 1
49 | fi
50 |
51 | psql -h $FLIBUSTA_DBHOST -d $POSTGRES_ADMIN_USER -U $POSTGRES_ADMIN_USER -v FLIBUSTA_DBUSER="$FLIBUSTA_DBUSER" -v FLIBUSTA_DBPASSWORD="$FLIBUSTA_DBPASSWORD" -v FLIBUSTA_DBNAME="$FLIBUSTA_DBNAME" -f /application/tools/external_services_config/external_postgres_init.sql
52 | #restore flibusta password
53 | export PGPASSWORD=$FLIBUSTA_DBPASSWORD
54 |
55 | if [ `$SQL_CMD -c "select 1 from pg_roles where rolname='flibusta'" | wc -l` -eq 0 ]; then
56 | echo "Can't connect to the DB after initialization attempt, exiting"
57 | exit 1
58 | fi
59 | fi
60 |
61 | exec php-fpm
--------------------------------------------------------------------------------
/application/tools/update_vectors.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO libavtorname_ts
2 | select avtorid, to_tsvector('russian', concat(lastname, ' ', middlename, ' ', firstname, ' ', nickname)) vector
3 | FROM libavtorname
4 | ON CONFLICT DO NOTHING;
5 |
6 | INSERT INTO libbook_ts
7 | select bookid, to_tsvector('russian',title) vector
8 | FROM libbook
9 | ON CONFLICT DO NOTHING;
10 |
11 | INSERT INTO libseqname_ts
12 | select seqid, to_tsvector('russian', seqname) vector
13 | FROM libseqname
14 | ON CONFLICT DO NOTHING;
15 |
16 |
--------------------------------------------------------------------------------
/application/webroot.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/blob/1:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/blob/x1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/blob/x1.png
--------------------------------------------------------------------------------
/blob/x2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/blob/x2.png
--------------------------------------------------------------------------------
/blob/x3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/blob/x3.png
--------------------------------------------------------------------------------
/blob/x4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/blob/x4.png
--------------------------------------------------------------------------------
/cache/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/cache/.gitkeep
--------------------------------------------------------------------------------
/cache/authors/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/cache/authors/.gitkeep
--------------------------------------------------------------------------------
/cache/covers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/cache/covers/.gitkeep
--------------------------------------------------------------------------------
/cache/tmp/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/cache/tmp/.gitkeep
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.1'
2 | services:
3 | postgres:
4 | build: phpdocker/pg
5 | working_dir: /application
6 | volumes:
7 | - 'db-data:/var/lib/postgresql/data'
8 | - './application:/application'
9 | environment:
10 | - POSTGRES_USER=flibusta
11 | - POSTGRES_PASSWORD=flibusta
12 | - POSTGRES_DB=flibusta
13 | ports:
14 | - '27101:5432'
15 |
16 | webserver:
17 | image: 'nginx:alpine'
18 | working_dir: /application
19 | volumes:
20 | - './application:/application'
21 | - './cache:/application/cache'
22 | - './Flibusta.Net:/application/flibusta'
23 | - './phpdocker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf'
24 | ports:
25 | - '27100:80'
26 |
27 | php-fpm:
28 | build: phpdocker/php-fpm
29 | working_dir: /application
30 | volumes:
31 | - './application:/application'
32 | - './cache:/application/cache'
33 | - './Flibusta.Net:/application/flibusta'
34 | - './FlibustaSQL:/application/sql'
35 | - './phpdocker/php-fpm/php-ini-overrides.ini:/usr/local/etc/php/conf.d/local-custom.ini'
36 | - './phpdocker/php-fpm/php-fpm.conf:/usr/local/etc/php-fpm.d/zz-php-fpm.conf'
37 | environment:
38 | - FLIBUSTA_DBUSER=flibusta
39 | - FLIBUSTA_DBNAME=flibusta
40 | - FLIBUSTA_DBTYPE=postgres
41 | - FLIBUSTA_DBHOST=postgres
42 | - FLIBUSTA_DBPASSWORD_FILE=/run/secrets/FLIBUSTA_PWD
43 | secrets:
44 | - FLIBUSTA_PWD
45 |
46 |
47 | volumes:
48 | db-data:
49 | secrets:
50 | FLIBUSTA_PWD:
51 | file: ./secrets/flibusta_pwd.txt
--------------------------------------------------------------------------------
/getcovers.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #zipchkcdm='zip -T'
4 | zipchkcmd='7z -bsp0 -bso0 t'
5 |
6 | echo "Backup old zip files"
7 | mv cache/lib.a.attached.zip cache/lib.a.attached.zip.old
8 | mv cache/lib.b.attached.zip cache/lib.b.attached.zip.old
9 |
10 | wget --directory-prefix=cache -c -nc https://flibusta.is/sql/lib.a.attached.zip
11 | res=$?
12 | if test "$res" != "0"; then
13 | echo "the wget command failed with: $res"
14 | echo "Restore lib.a.attached.zip"
15 | mv cache/lib.a.attached.zip.old cache/lib.a.attached.zip
16 | fi
17 | wget --directory-prefix=cache -c -nc https://flibusta.is/sql/lib.b.attached.zip
18 | res=$?
19 | if test "$res" != "0"; then
20 | echo "the wget command failed with: $res"
21 | echo "Restore lib.b.attached.zip"
22 | mv cache/lib.b.attached.zip.old cache/lib.b.attached.zip
23 | fi
24 |
25 |
26 | eval $zipchkcmd cache/lib.a.attached.zip
27 | res=$?
28 | if test "$res" == "0"; then
29 | echo "Remove backup lib.a.attached.zip"
30 | rm cache/lib.a.attached.zip.old
31 | fi
32 |
33 | eval $zipchkcmd cache/lib.b.attached.zip
34 | res=$?
35 | if test "$res" == "0"; then
36 | echo "Remove backup lib.b.attached.zip"
37 | rm cache/lib.b.attached.zip.old
38 | fi
39 |
40 |
--------------------------------------------------------------------------------
/getsql.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | wget --directory-prefix=FlibustaSQL -c -nc http://flibusta.is/sql/lib.libavtor.sql.gz
3 | wget --directory-prefix=FlibustaSQL -c -nc http://flibusta.is/sql/lib.libtranslator.sql.gz
4 | wget --directory-prefix=FlibustaSQL -c -nc http://flibusta.is/sql/lib.libavtorname.sql.gz
5 | wget --directory-prefix=FlibustaSQL -c -nc http://flibusta.is/sql/lib.libbook.sql.gz
6 | wget --directory-prefix=FlibustaSQL -c -nc http://flibusta.is/sql/lib.libfilename.sql.gz
7 | wget --directory-prefix=FlibustaSQL -c -nc http://flibusta.is/sql/lib.libgenre.sql.gz
8 | wget --directory-prefix=FlibustaSQL -c -nc http://flibusta.is/sql/lib.libgenrelist.sql.gz
9 | wget --directory-prefix=FlibustaSQL -c -nc http://flibusta.is/sql/lib.libjoinedbooks.sql.gz
10 | wget --directory-prefix=FlibustaSQL -c -nc http://flibusta.is/sql/lib.librate.sql.gz
11 | wget --directory-prefix=FlibustaSQL -c -nc http://flibusta.is/sql/lib.librecs.sql.gz
12 | wget --directory-prefix=FlibustaSQL -c -nc http://flibusta.is/sql/lib.libseqname.sql.gz
13 | wget --directory-prefix=FlibustaSQL -c -nc http://flibusta.is/sql/lib.libseq.sql.gz
14 | wget --directory-prefix=FlibustaSQL -c -nc http://flibusta.is/sql/lib.reviews.sql.gz
15 | wget --directory-prefix=FlibustaSQL -c -nc http://flibusta.is/sql/lib.b.annotations.sql.gz
16 | wget --directory-prefix=FlibustaSQL -c -nc http://flibusta.is/sql/lib.a.annotations.sql.gz
17 | wget --directory-prefix=FlibustaSQL -c -nc http://flibusta.is/sql/lib.b.annotations_pics.sql.gz
18 | wget --directory-prefix=FlibustaSQL -c -nc http://flibusta.is/sql/lib.a.annotations_pics.sql.gz
19 | docker exec $(docker ps -q --filter "ancestor=flibusta_php-fpm") /application/tools/app_import_sql.sh
20 |
--------------------------------------------------------------------------------
/phpdocker/nginx/nginx.conf:
--------------------------------------------------------------------------------
1 | server {
2 | listen 80 default;
3 |
4 | client_max_body_size 508M;
5 |
6 | access_log /var/log/nginx/application.access.log;
7 |
8 |
9 | root /application/public;
10 | index index.php;
11 |
12 | # try to serve file directly, fallback to index.php
13 | location / {
14 | try_files $uri /index.php$is_args$args;
15 | }
16 |
17 | if (!-e $request_filename) {
18 | rewrite ^.*$ /index.php last;
19 | }
20 |
21 | location ~ \.php$ {
22 | add_header 'Content-Security-Policy' 'worker-src * blob:';
23 |
24 | fastcgi_pass php-fpm:9000;
25 | fastcgi_index index.php;
26 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
27 | fastcgi_param PHP_VALUE "error_log=/var/log/nginx/application_php_errors.log";
28 | fastcgi_buffers 16 16k;
29 | fastcgi_buffer_size 32k;
30 | include fastcgi_params;
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/phpdocker/pg/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM postgres:16
2 | WORKDIR /docker-entrypoint-initdb.d
3 | ENV POSTGRES_DB flibusta
4 | COPY init_db.sql /docker-entrypoint-initdb.d/
5 |
--------------------------------------------------------------------------------
/phpdocker/php-fpm/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM php:8.1-fpm-alpine
2 |
3 | ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
4 |
5 | WORKDIR "/application"
6 |
7 | RUN apk --update add postgresql-client;\
8 | apk add python3;\
9 | apk add coreutils;
10 | RUN chmod +x /usr/local/bin/install-php-extensions; install-php-extensions gd bz2 pdo_pgsql zip
11 |
--------------------------------------------------------------------------------
/phpdocker/php-fpm/php-fpm.conf:
--------------------------------------------------------------------------------
1 | php_flag[display_errors] = off
2 | php_admin_flag[log_errors] = on
3 | [www]
4 | pm.max_children = 10
5 |
--------------------------------------------------------------------------------
/phpdocker/php-fpm/php-ini-overrides.ini:
--------------------------------------------------------------------------------
1 | upload_max_filesize = 500M
2 | post_max_size = 508M
3 |
--------------------------------------------------------------------------------
/secrets/flibusta_pwd.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zlsl/flibusta/a7e8fcccef6ef49ead5b3e4dd7e95d55b73ce7e1/secrets/flibusta_pwd.txt
--------------------------------------------------------------------------------
/secrets/postgres_admin_pwd.txt:
--------------------------------------------------------------------------------
1 | flibusta
--------------------------------------------------------------------------------
/update_daily.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | URL="http://flibusta.is/daily/"
3 | DEST_DIR="./Flibusta.Net"
4 | mkdir -p "$DEST_DIR"
5 | curl -s "$URL" > page.html
6 | grep -Eo 'href="f\.(fb2|n)\.[0-9\-]+\.zip"' page.html | sed 's/href="//;s/"//' > links.txt
7 |
8 | while IFS= read -r file; do
9 | wget -c -P "$DEST_DIR" "$URL$file"
10 | done < links.txt
11 |
12 | rm page.html links.txt
13 |
--------------------------------------------------------------------------------