• R/O
  • SSH

提交

标签
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Gemini server written in Crystal


Commit MetaInfo

修订版dbbae5dcc82d5c3f93f3bcecdc04dce8b5dd1072 (tree)
时间2023-12-04 09:17:10
作者Remilia Scarlet <alexa@part...>
CommiterRemilia Scarlet

Log Message

Moved the repo

更改概述

  • modified: README.md (diff)
  • delete: INSTALL.md
  • delete: LICENSE
  • delete: NEWS.md
  • delete: aya-cgi.md
  • delete: rc.aya
  • delete: sample-config.yml
  • delete: shard.lock
  • delete: shard.yml
  • delete: src/config.cr
  • delete: src/main.cr
  • delete: src/server.cr
  • delete: src/utils.cr

差异

diff -r f8ed96c7941d -r dbbae5dcc82d INSTALL.md
--- a/INSTALL.md Sat Nov 18 16:01:35 2023 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,193 +0,0 @@
1-# Installing Aya as a System-Wide Program
2-
3-This document describes how to install Aya as a system-wide program. Typically
4-this is not needed if you just want to server files as a non-root user, but it's
5-an option should you wish to install Aya in a more traditional way.
6-
7-## Prerequisites
8-
9-You will need:
10-
11-* A Linux operating system with root access.
12-* A compiled binary of Aya, or the source code to build a binary yourself.
13-* The `nohup` program (this may be a built-in for your shell).
14-
15-Once you have these met, you will need to decide a few things ahead of time:
16-
17-* Where the server root will be (e.g. `/var/www/gemini/`)
18-* Where you want your log files (e.g. `/var/log/aya/`)
19-* The username and group you want to Aya to switch to after starting.
20-
21-### A Few Notes About Aya's Behavior
22-
23-When Aya starts up, it first loads (as the user/group it was started with) a
24-configuration file and the MIME file (if any). After this, Aya checks to see if
25-the configuration file specifies a UID and GID that it should change to. If
26-these exist, Aya will change the process's real and effective user ID group ID
27-to the values specified. Otherwise, it will continue to run as the user/group
28-that started it.
29-
30-Aya will then check to see if its process is running as root, even after
31-changing user/group IDs. If it is, Aya will print a warning (because allowing
32-Aya to continue to run as root is a bad idea).
33-
34-After this, the log files are opened for appending (or created if they don't
35-exist) if needed, and the server beings listening for connections. Because the
36-user/group ID has already changed, this implies that Aya cannot listen on
37-unprivileged ports (i.e. ports below 1024). Since Gemini runs on port 1965 by
38-default, this should not cause any problems.
39-
40-
41-## Creating Users, Groups, and Directories
42-
43-The first step is to create the `/etc/aya/` directory as root, set it up with
44-the correct permissions, and copy the example configuration over. This
45-directory and its files should be owned by root.
46-
47-```
48-# mkdir /etc/aya
49-# cp -v /path/to/sample-config.yaml /etc/aya/aya-config.yaml
50-# chown -Rv root:root /etc/aya
51-# chmod -v 755 /etc/aya
52-# chmod -v 640 /etc/aya/aya-config.yaml
53-```
54-
55-Next, you will need to add a new user and group to your system. This is because
56-allowing Aya to continue to run as root after it starts up is a bad idea. You
57-may need to change the user ID and group ID used here so they don't conflict
58-with any existing IDs on your system. Be sure to note the user ID and group ID
59-you use.
60-
61-```
62-# groupadd -g 199 aya
63-# useradd -u 199 -g 199 -d /var/run -s /bin/false aya
64-```
65-
66-Now you need to create some directories for Aya and fix their permissions.
67-These are the directories you decided on earlier in the prerequisites. These
68-should be owned by the user and group you just created, not by root.
69-
70-```
71-# mkdir /var/log/aya
72-# chown -v aya:aya /var/log/aya
73-# chmod -v 750 /var/log/aya
74-# mkdir /var/www/gemini
75-# chown -v aya:aya /var/www/gemini
76-# chmod -v 755 /var/www/gemini
77-# chmod g+s /var/www/gemini
78-```
79-
80-The final `chmod` (with the `g+s`) is to ensure that all files that get created
81-under your server root belong to the correct group. You also may want to adjust
82-the permissions of your server root to `775` (e.g.
83-`chmod -v 775 /var/www/gemini`) instead so that anyone within the group for
84-Aya can write files there.
85-
86-## Configuring Aya
87-
88-You now need to create a system-wide configuration file for Aya. When no
89-configuration file is specified on the command line, Aya will look for a config
90-file located at `/etc/aya/aya-config.yaml`. This will be your system-wide
91-configuration file. If you followed the directions in the previous section, you
92-should have a file named `/etc/aya/aya-config.yaml` that is ready for you to
93-edit. An example config might look like this:
94-
95-```yaml
96-# This is where you'll place your files that you want to serve.
97-server-root: /var/www/gemini
98-
99-# If you plan on having CGI scripts, you can place them in this directory.
100-# These should be executable by the user/group you created for Aya.
101-cgi-path: /var/www/gemini-cgi
102-
103-# This is the main log file for Aya.
104-log-file : /var/log/aya/aya.log
105-
106-# This is the file that Aya uses to log connections. Setting this to null
107-# disables logging of connections. This cannot be the same file as the
108-# main log-file above.
109-conn-log-file : aya-connections.log
110-
111-# This should match the user ID you created for Aya
112-uid: 199
113-
114-# This should match the group ID you created for Aya
115-gid: 199
116-
117-# Your SSL key and certificate chain should only be readable by root
118-# (e.g. chown root:root and chmod 400)
119-tls-key: /etc/ssl/private/aya.key
120-cert-chain: /etc/ssl/private/aya-chain.crt
121-
122-# The IP addresses/hostnames you want to listen for connections on.
123-listen:
124- - localhost
125- - 192.168.1.1 # obviously change this
126-
127-# Look at the sample-config.yaml for an explanation of these settings.
128-follow-symlinks: none
129-unknown-as-octet-stream: true
130-rate-limit: 0
131-rate-limit-type: nongemini
132-footer: null
133-mime-file: null
134-cgi-extensions: []
135-```
136-
137-## Installing the Binary
138-
139-Copy your Aya binary somewhere where root can read and execute it. Be sure it's
140-owned by root.
141-
142-```
143-# cp -v /path/to/your/downloaded/aya /usr/sbin/aya
144-# chown -v root:root /usr/sbin/aya
145-# chmod -v 755 /usr/sbin/aya
146-```
147-
148-### Installing The Init Script
149-
150-An init script, `rc.aya`, comes with the Aya source code. This script is
151-intended to be used on a [Slackware Linux](http://www.slackware.com/) system,
152-but it should work with other Unix/Linux distributions as well. You may need to
153-adjust it to fit your needs, however (e.g., your system needs a different type
154-of init file, or you are not using the example values mentioned in the
155-Prerequisites section).
156-
157-On a Slackware-like system, you can copy this into `/etc/rc.d`, then modify a
158-few files so Aya is started and stopped automatically.
159-
160-```
161-# cp -v /path/to/aya/sources/rc.aya /etc/rc.d
162-# chown -v root:root /etc/rc.d/rc.aya
163-# chmod a+x /etc/rc.d/rc.aya
164-```
165-
166-To start Aya automatically at startup, edit `/etc/rc.d/rc.local` and place this
167-at the end:
168-
169-```bash
170-if [ -x /etc/rc.d/rc.aya ]; then
171- /etc/rc.d/rc.aya start
172-fi
173-```
174-
175-Likewise, to stop Aya automatically at shutdown, edit
176-`/etc/rc.d/rc.local_shutdown` and place this at the end:
177-
178-```bash
179-if [ -x /etc/rc.d/rc.aya ]; then
180- /etc/rc.d/rc.aya stop
181-fi
182-```
183-
184-Note that this `rc.aya` init script uses the `nohup` command to run Aya as a
185-daemon-like program. Any errors during startup can be found in the file pointed
186-to by the `OUTPUT_LOG` variable in `rc.aya` (default:
187-`/var/log/aya/aya-output.log`). When using this `rc.aya` script, the `log-file`
188-configuration setting is therefore redundant and can be set to `null`.
189-
190-Additionally, `rc.aya` uses a PID file to check/stop a running Aya instance.
191-This file is set using the `PID_FILE` variable in the script, and defaults to
192-`/var/run/aya.pid`. Wherever this pid file gets placed, it should be a
193-directory where the user that initially runs Aya can create the file.
diff -r f8ed96c7941d -r dbbae5dcc82d LICENSE
--- a/LICENSE Sat Nov 18 16:01:35 2023 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,661 +0,0 @@
1- GNU AFFERO GENERAL PUBLIC LICENSE
2- Version 3, 19 November 2007
3-
4- Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
5- Everyone is permitted to copy and distribute verbatim copies
6- of this license document, but changing it is not allowed.
7-
8- Preamble
9-
10- The GNU Affero General Public License is a free, copyleft license for
11-software and other kinds of works, specifically designed to ensure
12-cooperation with the community in the case of network server software.
13-
14- The licenses for most software and other practical works are designed
15-to take away your freedom to share and change the works. By contrast,
16-our General Public Licenses are intended to guarantee your freedom to
17-share and change all versions of a program--to make sure it remains free
18-software for all its users.
19-
20- When we speak of free software, we are referring to freedom, not
21-price. Our General Public Licenses are designed to make sure that you
22-have the freedom to distribute copies of free software (and charge for
23-them if you wish), that you receive source code or can get it if you
24-want it, that you can change the software or use pieces of it in new
25-free programs, and that you know you can do these things.
26-
27- Developers that use our General Public Licenses protect your rights
28-with two steps: (1) assert copyright on the software, and (2) offer
29-you this License which gives you legal permission to copy, distribute
30-and/or modify the software.
31-
32- A secondary benefit of defending all users' freedom is that
33-improvements made in alternate versions of the program, if they
34-receive widespread use, become available for other developers to
35-incorporate. Many developers of free software are heartened and
36-encouraged by the resulting cooperation. However, in the case of
37-software used on network servers, this result may fail to come about.
38-The GNU General Public License permits making a modified version and
39-letting the public access it on a server without ever releasing its
40-source code to the public.
41-
42- The GNU Affero General Public License is designed specifically to
43-ensure that, in such cases, the modified source code becomes available
44-to the community. It requires the operator of a network server to
45-provide the source code of the modified version running there to the
46-users of that server. Therefore, public use of a modified version, on
47-a publicly accessible server, gives the public access to the source
48-code of the modified version.
49-
50- An older license, called the Affero General Public License and
51-published by Affero, was designed to accomplish similar goals. This is
52-a different license, not a version of the Affero GPL, but Affero has
53-released a new version of the Affero GPL which permits relicensing under
54-this license.
55-
56- The precise terms and conditions for copying, distribution and
57-modification follow.
58-
59- TERMS AND CONDITIONS
60-
61- 0. Definitions.
62-
63- "This License" refers to version 3 of the GNU Affero General Public License.
64-
65- "Copyright" also means copyright-like laws that apply to other kinds of
66-works, such as semiconductor masks.
67-
68- "The Program" refers to any copyrightable work licensed under this
69-License. Each licensee is addressed as "you". "Licensees" and
70-"recipients" may be individuals or organizations.
71-
72- To "modify" a work means to copy from or adapt all or part of the work
73-in a fashion requiring copyright permission, other than the making of an
74-exact copy. The resulting work is called a "modified version" of the
75-earlier work or a work "based on" the earlier work.
76-
77- A "covered work" means either the unmodified Program or a work based
78-on the Program.
79-
80- To "propagate" a work means to do anything with it that, without
81-permission, would make you directly or secondarily liable for
82-infringement under applicable copyright law, except executing it on a
83-computer or modifying a private copy. Propagation includes copying,
84-distribution (with or without modification), making available to the
85-public, and in some countries other activities as well.
86-
87- To "convey" a work means any kind of propagation that enables other
88-parties to make or receive copies. Mere interaction with a user through
89-a computer network, with no transfer of a copy, is not conveying.
90-
91- An interactive user interface displays "Appropriate Legal Notices"
92-to the extent that it includes a convenient and prominently visible
93-feature that (1) displays an appropriate copyright notice, and (2)
94-tells the user that there is no warranty for the work (except to the
95-extent that warranties are provided), that licensees may convey the
96-work under this License, and how to view a copy of this License. If
97-the interface presents a list of user commands or options, such as a
98-menu, a prominent item in the list meets this criterion.
99-
100- 1. Source Code.
101-
102- The "source code" for a work means the preferred form of the work
103-for making modifications to it. "Object code" means any non-source
104-form of a work.
105-
106- A "Standard Interface" means an interface that either is an official
107-standard defined by a recognized standards body, or, in the case of
108-interfaces specified for a particular programming language, one that
109-is widely used among developers working in that language.
110-
111- The "System Libraries" of an executable work include anything, other
112-than the work as a whole, that (a) is included in the normal form of
113-packaging a Major Component, but which is not part of that Major
114-Component, and (b) serves only to enable use of the work with that
115-Major Component, or to implement a Standard Interface for which an
116-implementation is available to the public in source code form. A
117-"Major Component", in this context, means a major essential component
118-(kernel, window system, and so on) of the specific operating system
119-(if any) on which the executable work runs, or a compiler used to
120-produce the work, or an object code interpreter used to run it.
121-
122- The "Corresponding Source" for a work in object code form means all
123-the source code needed to generate, install, and (for an executable
124-work) run the object code and to modify the work, including scripts to
125-control those activities. However, it does not include the work's
126-System Libraries, or general-purpose tools or generally available free
127-programs which are used unmodified in performing those activities but
128-which are not part of the work. For example, Corresponding Source
129-includes interface definition files associated with source files for
130-the work, and the source code for shared libraries and dynamically
131-linked subprograms that the work is specifically designed to require,
132-such as by intimate data communication or control flow between those
133-subprograms and other parts of the work.
134-
135- The Corresponding Source need not include anything that users
136-can regenerate automatically from other parts of the Corresponding
137-Source.
138-
139- The Corresponding Source for a work in source code form is that
140-same work.
141-
142- 2. Basic Permissions.
143-
144- All rights granted under this License are granted for the term of
145-copyright on the Program, and are irrevocable provided the stated
146-conditions are met. This License explicitly affirms your unlimited
147-permission to run the unmodified Program. The output from running a
148-covered work is covered by this License only if the output, given its
149-content, constitutes a covered work. This License acknowledges your
150-rights of fair use or other equivalent, as provided by copyright law.
151-
152- You may make, run and propagate covered works that you do not
153-convey, without conditions so long as your license otherwise remains
154-in force. You may convey covered works to others for the sole purpose
155-of having them make modifications exclusively for you, or provide you
156-with facilities for running those works, provided that you comply with
157-the terms of this License in conveying all material for which you do
158-not control copyright. Those thus making or running the covered works
159-for you must do so exclusively on your behalf, under your direction
160-and control, on terms that prohibit them from making any copies of
161-your copyrighted material outside their relationship with you.
162-
163- Conveying under any other circumstances is permitted solely under
164-the conditions stated below. Sublicensing is not allowed; section 10
165-makes it unnecessary.
166-
167- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
168-
169- No covered work shall be deemed part of an effective technological
170-measure under any applicable law fulfilling obligations under article
171-11 of the WIPO copyright treaty adopted on 20 December 1996, or
172-similar laws prohibiting or restricting circumvention of such
173-measures.
174-
175- When you convey a covered work, you waive any legal power to forbid
176-circumvention of technological measures to the extent such circumvention
177-is effected by exercising rights under this License with respect to
178-the covered work, and you disclaim any intention to limit operation or
179-modification of the work as a means of enforcing, against the work's
180-users, your or third parties' legal rights to forbid circumvention of
181-technological measures.
182-
183- 4. Conveying Verbatim Copies.
184-
185- You may convey verbatim copies of the Program's source code as you
186-receive it, in any medium, provided that you conspicuously and
187-appropriately publish on each copy an appropriate copyright notice;
188-keep intact all notices stating that this License and any
189-non-permissive terms added in accord with section 7 apply to the code;
190-keep intact all notices of the absence of any warranty; and give all
191-recipients a copy of this License along with the Program.
192-
193- You may charge any price or no price for each copy that you convey,
194-and you may offer support or warranty protection for a fee.
195-
196- 5. Conveying Modified Source Versions.
197-
198- You may convey a work based on the Program, or the modifications to
199-produce it from the Program, in the form of source code under the
200-terms of section 4, provided that you also meet all of these conditions:
201-
202- a) The work must carry prominent notices stating that you modified
203- it, and giving a relevant date.
204-
205- b) The work must carry prominent notices stating that it is
206- released under this License and any conditions added under section
207- 7. This requirement modifies the requirement in section 4 to
208- "keep intact all notices".
209-
210- c) You must license the entire work, as a whole, under this
211- License to anyone who comes into possession of a copy. This
212- License will therefore apply, along with any applicable section 7
213- additional terms, to the whole of the work, and all its parts,
214- regardless of how they are packaged. This License gives no
215- permission to license the work in any other way, but it does not
216- invalidate such permission if you have separately received it.
217-
218- d) If the work has interactive user interfaces, each must display
219- Appropriate Legal Notices; however, if the Program has interactive
220- interfaces that do not display Appropriate Legal Notices, your
221- work need not make them do so.
222-
223- A compilation of a covered work with other separate and independent
224-works, which are not by their nature extensions of the covered work,
225-and which are not combined with it such as to form a larger program,
226-in or on a volume of a storage or distribution medium, is called an
227-"aggregate" if the compilation and its resulting copyright are not
228-used to limit the access or legal rights of the compilation's users
229-beyond what the individual works permit. Inclusion of a covered work
230-in an aggregate does not cause this License to apply to the other
231-parts of the aggregate.
232-
233- 6. Conveying Non-Source Forms.
234-
235- You may convey a covered work in object code form under the terms
236-of sections 4 and 5, provided that you also convey the
237-machine-readable Corresponding Source under the terms of this License,
238-in one of these ways:
239-
240- a) Convey the object code in, or embodied in, a physical product
241- (including a physical distribution medium), accompanied by the
242- Corresponding Source fixed on a durable physical medium
243- customarily used for software interchange.
244-
245- b) Convey the object code in, or embodied in, a physical product
246- (including a physical distribution medium), accompanied by a
247- written offer, valid for at least three years and valid for as
248- long as you offer spare parts or customer support for that product
249- model, to give anyone who possesses the object code either (1) a
250- copy of the Corresponding Source for all the software in the
251- product that is covered by this License, on a durable physical
252- medium customarily used for software interchange, for a price no
253- more than your reasonable cost of physically performing this
254- conveying of source, or (2) access to copy the
255- Corresponding Source from a network server at no charge.
256-
257- c) Convey individual copies of the object code with a copy of the
258- written offer to provide the Corresponding Source. This
259- alternative is allowed only occasionally and noncommercially, and
260- only if you received the object code with such an offer, in accord
261- with subsection 6b.
262-
263- d) Convey the object code by offering access from a designated
264- place (gratis or for a charge), and offer equivalent access to the
265- Corresponding Source in the same way through the same place at no
266- further charge. You need not require recipients to copy the
267- Corresponding Source along with the object code. If the place to
268- copy the object code is a network server, the Corresponding Source
269- may be on a different server (operated by you or a third party)
270- that supports equivalent copying facilities, provided you maintain
271- clear directions next to the object code saying where to find the
272- Corresponding Source. Regardless of what server hosts the
273- Corresponding Source, you remain obligated to ensure that it is
274- available for as long as needed to satisfy these requirements.
275-
276- e) Convey the object code using peer-to-peer transmission, provided
277- you inform other peers where the object code and Corresponding
278- Source of the work are being offered to the general public at no
279- charge under subsection 6d.
280-
281- A separable portion of the object code, whose source code is excluded
282-from the Corresponding Source as a System Library, need not be
283-included in conveying the object code work.
284-
285- A "User Product" is either (1) a "consumer product", which means any
286-tangible personal property which is normally used for personal, family,
287-or household purposes, or (2) anything designed or sold for incorporation
288-into a dwelling. In determining whether a product is a consumer product,
289-doubtful cases shall be resolved in favor of coverage. For a particular
290-product received by a particular user, "normally used" refers to a
291-typical or common use of that class of product, regardless of the status
292-of the particular user or of the way in which the particular user
293-actually uses, or expects or is expected to use, the product. A product
294-is a consumer product regardless of whether the product has substantial
295-commercial, industrial or non-consumer uses, unless such uses represent
296-the only significant mode of use of the product.
297-
298- "Installation Information" for a User Product means any methods,
299-procedures, authorization keys, or other information required to install
300-and execute modified versions of a covered work in that User Product from
301-a modified version of its Corresponding Source. The information must
302-suffice to ensure that the continued functioning of the modified object
303-code is in no case prevented or interfered with solely because
304-modification has been made.
305-
306- If you convey an object code work under this section in, or with, or
307-specifically for use in, a User Product, and the conveying occurs as
308-part of a transaction in which the right of possession and use of the
309-User Product is transferred to the recipient in perpetuity or for a
310-fixed term (regardless of how the transaction is characterized), the
311-Corresponding Source conveyed under this section must be accompanied
312-by the Installation Information. But this requirement does not apply
313-if neither you nor any third party retains the ability to install
314-modified object code on the User Product (for example, the work has
315-been installed in ROM).
316-
317- The requirement to provide Installation Information does not include a
318-requirement to continue to provide support service, warranty, or updates
319-for a work that has been modified or installed by the recipient, or for
320-the User Product in which it has been modified or installed. Access to a
321-network may be denied when the modification itself materially and
322-adversely affects the operation of the network or violates the rules and
323-protocols for communication across the network.
324-
325- Corresponding Source conveyed, and Installation Information provided,
326-in accord with this section must be in a format that is publicly
327-documented (and with an implementation available to the public in
328-source code form), and must require no special password or key for
329-unpacking, reading or copying.
330-
331- 7. Additional Terms.
332-
333- "Additional permissions" are terms that supplement the terms of this
334-License by making exceptions from one or more of its conditions.
335-Additional permissions that are applicable to the entire Program shall
336-be treated as though they were included in this License, to the extent
337-that they are valid under applicable law. If additional permissions
338-apply only to part of the Program, that part may be used separately
339-under those permissions, but the entire Program remains governed by
340-this License without regard to the additional permissions.
341-
342- When you convey a copy of a covered work, you may at your option
343-remove any additional permissions from that copy, or from any part of
344-it. (Additional permissions may be written to require their own
345-removal in certain cases when you modify the work.) You may place
346-additional permissions on material, added by you to a covered work,
347-for which you have or can give appropriate copyright permission.
348-
349- Notwithstanding any other provision of this License, for material you
350-add to a covered work, you may (if authorized by the copyright holders of
351-that material) supplement the terms of this License with terms:
352-
353- a) Disclaiming warranty or limiting liability differently from the
354- terms of sections 15 and 16 of this License; or
355-
356- b) Requiring preservation of specified reasonable legal notices or
357- author attributions in that material or in the Appropriate Legal
358- Notices displayed by works containing it; or
359-
360- c) Prohibiting misrepresentation of the origin of that material, or
361- requiring that modified versions of such material be marked in
362- reasonable ways as different from the original version; or
363-
364- d) Limiting the use for publicity purposes of names of licensors or
365- authors of the material; or
366-
367- e) Declining to grant rights under trademark law for use of some
368- trade names, trademarks, or service marks; or
369-
370- f) Requiring indemnification of licensors and authors of that
371- material by anyone who conveys the material (or modified versions of
372- it) with contractual assumptions of liability to the recipient, for
373- any liability that these contractual assumptions directly impose on
374- those licensors and authors.
375-
376- All other non-permissive additional terms are considered "further
377-restrictions" within the meaning of section 10. If the Program as you
378-received it, or any part of it, contains a notice stating that it is
379-governed by this License along with a term that is a further
380-restriction, you may remove that term. If a license document contains
381-a further restriction but permits relicensing or conveying under this
382-License, you may add to a covered work material governed by the terms
383-of that license document, provided that the further restriction does
384-not survive such relicensing or conveying.
385-
386- If you add terms to a covered work in accord with this section, you
387-must place, in the relevant source files, a statement of the
388-additional terms that apply to those files, or a notice indicating
389-where to find the applicable terms.
390-
391- Additional terms, permissive or non-permissive, may be stated in the
392-form of a separately written license, or stated as exceptions;
393-the above requirements apply either way.
394-
395- 8. Termination.
396-
397- You may not propagate or modify a covered work except as expressly
398-provided under this License. Any attempt otherwise to propagate or
399-modify it is void, and will automatically terminate your rights under
400-this License (including any patent licenses granted under the third
401-paragraph of section 11).
402-
403- However, if you cease all violation of this License, then your
404-license from a particular copyright holder is reinstated (a)
405-provisionally, unless and until the copyright holder explicitly and
406-finally terminates your license, and (b) permanently, if the copyright
407-holder fails to notify you of the violation by some reasonable means
408-prior to 60 days after the cessation.
409-
410- Moreover, your license from a particular copyright holder is
411-reinstated permanently if the copyright holder notifies you of the
412-violation by some reasonable means, this is the first time you have
413-received notice of violation of this License (for any work) from that
414-copyright holder, and you cure the violation prior to 30 days after
415-your receipt of the notice.
416-
417- Termination of your rights under this section does not terminate the
418-licenses of parties who have received copies or rights from you under
419-this License. If your rights have been terminated and not permanently
420-reinstated, you do not qualify to receive new licenses for the same
421-material under section 10.
422-
423- 9. Acceptance Not Required for Having Copies.
424-
425- You are not required to accept this License in order to receive or
426-run a copy of the Program. Ancillary propagation of a covered work
427-occurring solely as a consequence of using peer-to-peer transmission
428-to receive a copy likewise does not require acceptance. However,
429-nothing other than this License grants you permission to propagate or
430-modify any covered work. These actions infringe copyright if you do
431-not accept this License. Therefore, by modifying or propagating a
432-covered work, you indicate your acceptance of this License to do so.
433-
434- 10. Automatic Licensing of Downstream Recipients.
435-
436- Each time you convey a covered work, the recipient automatically
437-receives a license from the original licensors, to run, modify and
438-propagate that work, subject to this License. You are not responsible
439-for enforcing compliance by third parties with this License.
440-
441- An "entity transaction" is a transaction transferring control of an
442-organization, or substantially all assets of one, or subdividing an
443-organization, or merging organizations. If propagation of a covered
444-work results from an entity transaction, each party to that
445-transaction who receives a copy of the work also receives whatever
446-licenses to the work the party's predecessor in interest had or could
447-give under the previous paragraph, plus a right to possession of the
448-Corresponding Source of the work from the predecessor in interest, if
449-the predecessor has it or can get it with reasonable efforts.
450-
451- You may not impose any further restrictions on the exercise of the
452-rights granted or affirmed under this License. For example, you may
453-not impose a license fee, royalty, or other charge for exercise of
454-rights granted under this License, and you may not initiate litigation
455-(including a cross-claim or counterclaim in a lawsuit) alleging that
456-any patent claim is infringed by making, using, selling, offering for
457-sale, or importing the Program or any portion of it.
458-
459- 11. Patents.
460-
461- A "contributor" is a copyright holder who authorizes use under this
462-License of the Program or a work on which the Program is based. The
463-work thus licensed is called the contributor's "contributor version".
464-
465- A contributor's "essential patent claims" are all patent claims
466-owned or controlled by the contributor, whether already acquired or
467-hereafter acquired, that would be infringed by some manner, permitted
468-by this License, of making, using, or selling its contributor version,
469-but do not include claims that would be infringed only as a
470-consequence of further modification of the contributor version. For
471-purposes of this definition, "control" includes the right to grant
472-patent sublicenses in a manner consistent with the requirements of
473-this License.
474-
475- Each contributor grants you a non-exclusive, worldwide, royalty-free
476-patent license under the contributor's essential patent claims, to
477-make, use, sell, offer for sale, import and otherwise run, modify and
478-propagate the contents of its contributor version.
479-
480- In the following three paragraphs, a "patent license" is any express
481-agreement or commitment, however denominated, not to enforce a patent
482-(such as an express permission to practice a patent or covenant not to
483-sue for patent infringement). To "grant" such a patent license to a
484-party means to make such an agreement or commitment not to enforce a
485-patent against the party.
486-
487- If you convey a covered work, knowingly relying on a patent license,
488-and the Corresponding Source of the work is not available for anyone
489-to copy, free of charge and under the terms of this License, through a
490-publicly available network server or other readily accessible means,
491-then you must either (1) cause the Corresponding Source to be so
492-available, or (2) arrange to deprive yourself of the benefit of the
493-patent license for this particular work, or (3) arrange, in a manner
494-consistent with the requirements of this License, to extend the patent
495-license to downstream recipients. "Knowingly relying" means you have
496-actual knowledge that, but for the patent license, your conveying the
497-covered work in a country, or your recipient's use of the covered work
498-in a country, would infringe one or more identifiable patents in that
499-country that you have reason to believe are valid.
500-
501- If, pursuant to or in connection with a single transaction or
502-arrangement, you convey, or propagate by procuring conveyance of, a
503-covered work, and grant a patent license to some of the parties
504-receiving the covered work authorizing them to use, propagate, modify
505-or convey a specific copy of the covered work, then the patent license
506-you grant is automatically extended to all recipients of the covered
507-work and works based on it.
508-
509- A patent license is "discriminatory" if it does not include within
510-the scope of its coverage, prohibits the exercise of, or is
511-conditioned on the non-exercise of one or more of the rights that are
512-specifically granted under this License. You may not convey a covered
513-work if you are a party to an arrangement with a third party that is
514-in the business of distributing software, under which you make payment
515-to the third party based on the extent of your activity of conveying
516-the work, and under which the third party grants, to any of the
517-parties who would receive the covered work from you, a discriminatory
518-patent license (a) in connection with copies of the covered work
519-conveyed by you (or copies made from those copies), or (b) primarily
520-for and in connection with specific products or compilations that
521-contain the covered work, unless you entered into that arrangement,
522-or that patent license was granted, prior to 28 March 2007.
523-
524- Nothing in this License shall be construed as excluding or limiting
525-any implied license or other defenses to infringement that may
526-otherwise be available to you under applicable patent law.
527-
528- 12. No Surrender of Others' Freedom.
529-
530- If conditions are imposed on you (whether by court order, agreement or
531-otherwise) that contradict the conditions of this License, they do not
532-excuse you from the conditions of this License. If you cannot convey a
533-covered work so as to satisfy simultaneously your obligations under this
534-License and any other pertinent obligations, then as a consequence you may
535-not convey it at all. For example, if you agree to terms that obligate you
536-to collect a royalty for further conveying from those to whom you convey
537-the Program, the only way you could satisfy both those terms and this
538-License would be to refrain entirely from conveying the Program.
539-
540- 13. Remote Network Interaction; Use with the GNU General Public License.
541-
542- Notwithstanding any other provision of this License, if you modify the
543-Program, your modified version must prominently offer all users
544-interacting with it remotely through a computer network (if your version
545-supports such interaction) an opportunity to receive the Corresponding
546-Source of your version by providing access to the Corresponding Source
547-from a network server at no charge, through some standard or customary
548-means of facilitating copying of software. This Corresponding Source
549-shall include the Corresponding Source for any work covered by version 3
550-of the GNU General Public License that is incorporated pursuant to the
551-following paragraph.
552-
553- Notwithstanding any other provision of this License, you have
554-permission to link or combine any covered work with a work licensed
555-under version 3 of the GNU General Public License into a single
556-combined work, and to convey the resulting work. The terms of this
557-License will continue to apply to the part which is the covered work,
558-but the work with which it is combined will remain governed by version
559-3 of the GNU General Public License.
560-
561- 14. Revised Versions of this License.
562-
563- The Free Software Foundation may publish revised and/or new versions of
564-the GNU Affero General Public License from time to time. Such new versions
565-will be similar in spirit to the present version, but may differ in detail to
566-address new problems or concerns.
567-
568- Each version is given a distinguishing version number. If the
569-Program specifies that a certain numbered version of the GNU Affero General
570-Public License "or any later version" applies to it, you have the
571-option of following the terms and conditions either of that numbered
572-version or of any later version published by the Free Software
573-Foundation. If the Program does not specify a version number of the
574-GNU Affero General Public License, you may choose any version ever published
575-by the Free Software Foundation.
576-
577- If the Program specifies that a proxy can decide which future
578-versions of the GNU Affero General Public License can be used, that proxy's
579-public statement of acceptance of a version permanently authorizes you
580-to choose that version for the Program.
581-
582- Later license versions may give you additional or different
583-permissions. However, no additional obligations are imposed on any
584-author or copyright holder as a result of your choosing to follow a
585-later version.
586-
587- 15. Disclaimer of Warranty.
588-
589- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
590-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
591-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
592-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
593-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
594-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
595-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
596-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
597-
598- 16. Limitation of Liability.
599-
600- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
601-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
602-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
603-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
604-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
605-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
606-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
607-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
608-SUCH DAMAGES.
609-
610- 17. Interpretation of Sections 15 and 16.
611-
612- If the disclaimer of warranty and limitation of liability provided
613-above cannot be given local legal effect according to their terms,
614-reviewing courts shall apply local law that most closely approximates
615-an absolute waiver of all civil liability in connection with the
616-Program, unless a warranty or assumption of liability accompanies a
617-copy of the Program in return for a fee.
618-
619- END OF TERMS AND CONDITIONS
620-
621- How to Apply These Terms to Your New Programs
622-
623- If you develop a new program, and you want it to be of the greatest
624-possible use to the public, the best way to achieve this is to make it
625-free software which everyone can redistribute and change under these terms.
626-
627- To do so, attach the following notices to the program. It is safest
628-to attach them to the start of each source file to most effectively
629-state the exclusion of warranty; and each file should have at least
630-the "copyright" line and a pointer to where the full notice is found.
631-
632- <one line to give the program's name and a brief idea of what it does.>
633- Copyright (C) <year> <name of author>
634-
635- This program is free software: you can redistribute it and/or modify
636- it under the terms of the GNU Affero General Public License as published by
637- the Free Software Foundation, either version 3 of the License, or
638- (at your option) any later version.
639-
640- This program is distributed in the hope that it will be useful,
641- but WITHOUT ANY WARRANTY; without even the implied warranty of
642- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
643- GNU Affero General Public License for more details.
644-
645- You should have received a copy of the GNU Affero General Public License
646- along with this program. If not, see <https://www.gnu.org/licenses/>.
647-
648-Also add information on how to contact you by electronic and paper mail.
649-
650- If your software can interact with users remotely through a computer
651-network, you should also make sure that it provides a way for users to
652-get its source. For example, if your program is a web application, its
653-interface could display a "Source" link that leads users to an archive
654-of the code. There are many ways you could offer source, and different
655-solutions will be better for different programs; see section 13 for the
656-specific requirements.
657-
658- You should also get your employer (if you work as a programmer) or school,
659-if any, to sign a "copyright disclaimer" for the program, if necessary.
660-For more information on this, and how to apply and follow the GNU AGPL, see
661-<https://www.gnu.org/licenses/>.
diff -r f8ed96c7941d -r dbbae5dcc82d NEWS.md
--- a/NEWS.md Sat Nov 18 16:01:35 2023 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
1-Aya v0.3.0
2-==========
3-
4-Changes since v0.2.0:
5----------------------
6-
7-Features:
8-* Fixed changing the real/effective UID and GID at startup.
9-* The SSL key and certificate chain can now be owned by a different user than
10- the UID/GID that Aya changes to.
11-* Added rc.aya sample init script.
12-* Connection logging now works as intended.
13-* The `cgi-extensions` configuration key can no longer be an empty list.
14-* Added the `--dump-config` command line option to dump an example
15- configuration.
16-* The default configuration file is now `/etc/aya/aya-config.yaml`.
17-* Added INSTALL.md that contains instructions for installing Aya system-wide.
18-
19-Changes since v0.1.2:
20----------------------
21-
22-* Aya now uses the RemiGemini library.
23-* Aya now uses the IdleGC library.
24-
25-Changes since v0.1.1:
26----------------------
27-
28-Features:
29-* Aya can now change her real and effective UID and GID on startup. See
30- sample-config.yml for an example of how to do this.
31-* The new configuration variable `footer` can be used to append a footer onto
32- each Gemtext page that is served.
diff -r f8ed96c7941d -r dbbae5dcc82d README.md
--- a/README.md Sat Nov 18 16:01:35 2023 -0700
+++ b/README.md Sun Dec 03 17:17:10 2023 -0700
@@ -1,70 +1,3 @@
11 # Aya Gemini Server
22
3-Aya is a simple
4-[Gemini](https://portal.mozz.us/gemini/gemini.circumlunar.space/) server written
5-in [Crystal](https://crystal-lang.org/) and released under the
6-[GNU Affero General Public License](https://www.gnu.org/licenses/agpl-3.0.html).
7-
8-Wanna support Remilia? [Buy me a coffee on Ko-Fi](https://ko-fi.com/L4L614QNC),
9-or support me through Liberapay.
10-
11-<a href='https://ko-fi.com/L4L614QNC' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://cdn.ko-fi.com/cdn/kofi2.png?v=3' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
12-<a href="https://liberapay.com/RemiliaScarlet/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a>
13-
14-## How do I get set up?
15-
16-You will need [Mercurial](https://www.mercurial-scm.org/) installed to clone
17-this repository.
18-
19-You will need [Fossil](https://fossil-scm.org/) installed to clone some of the
20-dependencies for this repository. You will also need Shards v0.17.1 or later.
21-If you have an earlier version of Shards, you will need to to build the [latest
22-version](https://github.com/crystal-lang/shards/) manually.
23-
24-1. Clone this repository
25-2. Run `shards` (or `shards --release` for a release build). The binary will be
26- in the `bin/` directory.
27-3. Create a configuration file by copying `sample-config.yml` and editing the
28- copy. Note that Aya will automatically attempt load a file named
29- `/etc/aya/aya-config.yaml`, otherwise you will need to use the `--config`
30- parameter.
31-4. Start Aya.
32-
33-If you wish to install Aya in a system-wide way, check the `INSTALL.md` in the
34-repository root.
35-
36-## Development
37-
38-### Style info
39-
40-I use a somewhat non-standard style for my code.
41-
42-- Keep lines 118 characters or shorter. Obviously sometimes you can't, but
43- please try. Use 80 or 115 characters for Markdown files, though.
44-- Please use pascalCase for variable and method names. Use CamelCase for type
45- names. Use UPPER_SNAKE_CASE for constants.
46-- Put parentheses around method parameters, except for these methods: `puts`,
47- `pp`, `p`, `raise`, `sleep`, `spawn`, `loop`, and `exit`.
48-- Always the full `do |foo|...end` syntax with blocks, except when it's all on
49- one line or an anonymous function, then use { and } or the normal `do
50- |foo|...end`.
51-- The type name for exceptions end with Error. For example, `ExternalProgramError`.
52-
53-## How do I contribute?
54-
55-1. Go to https://osdn.net/users/yukiraven/pf/aya/ and clone the Mercurial repository.
56-2. Create a new branch for your feature.
57-3. Push locally to the new branch
58-4. Create a ticket.
59-
60-## Contributors
61-
62-* Remilia Scarlet - creator and maintainer
63- * Homepage: [https://remilia.sdf.org/](https://remilia.sdf.org/)
64- * Gemini: [gemini://nanako.mooo.com/](gemini://nanako.mooo.com/)
65- * Mastodon: [@MistressRemilia@social.sdf.org](https://social.sdf.org/@MistressRemilia)
66- * Email: zremiliaz@postzeoz.jpz My real address does not contain Z's
67-
68-## Links and Licenses
69-
70-Aya is under the [GNU Affero General Public License version 3](https://www.gnu.org/licenses/agpl-3.0.html).
3+**MOVED!** Please visit https://nanako.mooo.com/fossil/aya/ for the latest code.
diff -r f8ed96c7941d -r dbbae5dcc82d aya-cgi.md
--- a/aya-cgi.md Sat Nov 18 16:01:35 2023 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
1-# Aya CGI Interface v0.1.0
2-
3-Aya can be configured to understand certain file extensions as CGI scripts.
4-This is done in the configuration file using the `cgi-extensions` key. The
5-protocol for handling these (aka, what you're reading now) is deliberately
6-simple and roughly based on usual CGI 1.1 spec.
7-
8-When a client sends a request and the path component has one of the CGI
9-extensions at the very end, Aya will attempt to execute that file. If the file
10-does not exist, is not executable, or exits with an exit code of anything other
11-than 0, a `40 Temporary Failure` response is sent. Otherwise its output is sent
12-verbatim to the requesting client.
13-
14-The CGI script's environment will have various variables set that are filled
15-with information from the client. The `PATH` environment variable is also set
16-strictly according to the `cgi-path` key in the configuration file. The
17-server's `PATH` is not inherited, and no other environment variables except
18-those listed below exist for the CGI process.
19-
20-## Environment Variables
21-
22-* **DOCUMENT_ROOT**: The server root path, equivalent to the `server-root` key in the config file.
23-* **GATEWAY_INTERFACE**: The name and version of the Aya CGI Interface. This
24- should be `ACGI`, a space, and then a syumantic version.
25-* **PATH_INFO**: The path component of the URI
26-* **PATH_TRANSLATED**: The path to the CGI script as the server sees it.
27-* **SCRIPT_FILENAME**: The filename of the CGI script
28-* **QUERY_STRING**: The query component of the URI.
29-* **REQUEST_FRAGMENT**: The request component of the URI.
30-* **SERVER_HOST**: The host component of the URI.
31-* **SERVER_PORT**: The port component of the URI. The `listen-port` value will
32- be inserted here if the URI did not have a port specified.
33-* **PATH**: Same as usual, the `PATH` as understood by the shell.
34-
35-## Standard Input, Standard Output, and Standard Error
36-
37-Nothing is passed to the CGI process on standard input.
38-
39-The CGI process is expected to produce a valid Gemini response header (and
40-corresponding body, if applicable) on standard output. This will be sent
41-verbatim over the socket back to the requesting client.
42-
43-If the CGI script encounters an error, it can be printed on standard error. Any
44-output on this stream will be logged by Aya to its own standard error, as well
45-as any configured log file.
diff -r f8ed96c7941d -r dbbae5dcc82d rc.aya
--- a/rc.aya Sat Nov 18 16:01:35 2023 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
1-#!/bin/bash
2-
3-#### This file is part of Aya.
4-####
5-#### Aya is free software: you can redistribute it and/or modify it under the
6-#### terms of the GNU Affero General Public License as published by the Free
7-#### Software Foundation, either version 3 of the License, or (at your option)
8-#### any later version.
9-####
10-#### This program is distributed in the hope that it will be useful, but WITHOUT
11-#### ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12-#### FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
13-#### License for more details.
14-####
15-#### You should have received a copy of the GNU Affero General Public License
16-#### along with this program. If not, see <https://www.gnu.org/licenses/>.
17-
18-# Start/stop/restart the Aya daemon:
19-
20-PATH=/sbin:/bin:/usr/sbin:/usr/bin
21-PROGRAM=/usr/sbin/aya
22-PID_FILE=/var/run/aya.pid
23-OUTPUT_LOG=/var/log/aya/aya-output.log
24-
25-# Starts Aya if it isn't yet running.
26-aya_start() {
27- if [ -f $PID_FILE ]; then
28- echo "Aya is already running"
29- else
30- echo "Starting Aya: nohup $PROGRAM --pid $PID_FILE > $OUTPUT_LOG"
31- nohup $PROGRAM --pid $PID_FILE > $OUTPUT_LOG
32-
33- sleep 2
34- if [ $? -ne 0 ]; then
35- echo "Aya failed to start, check $OUTPUT_LOG for details"
36- return 1
37- fi
38-
39- if [ ! -f $PID_FILE ]; then
40- echo "Aya may have failed to start (no PID file was created)"
41- echo "Check $OUTPUT_LOG for details."
42- return 1
43- fi
44-
45- echo "Aya has been started with PID $(cat $PID_FILE)"
46- fi
47-}
48-
49-# Checks if Aya is running. If it is, this sets $? to 0, otherwise it sets it
50-# to 1.
51-aya_status_quiet() {
52- if [ -f $PID_FILE ]; then
53- return 0
54- else
55- return 1
56- fi
57-}
58-
59-# Checks if Aya is running and prints a message. If it is, this sets $? to 0,
60-# otherwise it sets it to 1.
61-aya_status() {
62- if [ -f $PID_FILE ]; then
63- local PID=$(cat $PID_FILE)
64- echo "Aya is running with PID $PID"
65- return 0
66- else
67- echo "Aya is not running"
68- return 1
69- fi
70-}
71-
72-# Stops Aya if it's running.
73-aya_stop() {
74- if [ -f $PID_FILE ]; then
75- echo -n "Stopping Aya: "
76- local PID=$(cat $PID_FILE)
77- kill $PID
78- if [ $? -ne 0 ]; then
79- echo "Failed"
80- echo "Could not stop Aya (stale PID?)"
81- else
82- rm -f $PID_FILE
83- echo "Stopped"
84- fi
85- else
86- echo "Aya does not seem to be running"
87- fi
88-}
89-
90-# Restarts aya.
91-aya_restart() {
92- aya_stop
93- sleep 2
94- aya_start
95-}
96-
97-###
98-### Main entry point
99-###
100-
101-case "$1" in
102- 'start')
103- aya_status_quiet
104- if [ $? -eq 1 ]; then
105- aya_start
106- else
107- echo "Aya is already running."
108- fi
109- ;;
110-
111- 'stop')
112- aya_stop
113- ;;
114-
115- 'restart')
116- aya_restart
117- ;;
118-
119- 'status')
120- aya_status
121- ;;
122-
123- *)
124- echo "usage $0 start|stop|status|restart"
125- ;;
126-esac
diff -r f8ed96c7941d -r dbbae5dcc82d sample-config.yml
--- a/sample-config.yml Sat Nov 18 16:01:35 2023 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
1-####
2-#### Sample configuration file for the Aya Gemini Server.
3-####
4-#### You can get a much more minimal sample configuration by running
5-#### `aya --dump-config`, then modifying it with appropriate values.
6-####
7-
8-# Where to look for files to serve
9-server-root: /var/gemini-root
10-
11-# When a CGI script is executed, this string will be set as the PATH environment
12-# variable. The default is an empty string (no PATH).
13-cgi-path: ""
14-
15-# Files with these extensions in the server root will be treated as CGI programs
16-# to execute. Anything sent to standard output by these programs will be served
17-# as a response body. Output should include the response header and any
18-# applicable body. This cannot be an empty list.
19-#
20-# Be sure to include the dot (.) in the extension name.
21-cgi-extensions:
22- - .cgi
23-
24-# The port to listen on for connections. If this is not present, the default is
25-# 1965.
26-#listen-port: 1965
27-
28-# When this is a non-empty string, all non-connection related messages will be
29-# logged to this file as well as standard output/standard error.
30-log-file: aya.log
31-
32-# When this is a non-empty string, connections will be logged to this file.
33-# This cannot be the same file as specified in the log-file key.
34-conn-log-file: aya-connections.log
35-
36-# When this is present and not null, Aya will change her the real and effective
37-# UID during startup. If this is null (the default), Aya will use the UID of
38-# the user who launched the process.
39-uid: null
40-
41-# When this is present and not null, Aya will change her the real and effective
42-# GID during startup. If this is null (the default), Aya will use the GID of
43-# the user who launched the process.
44-gid: null
45-
46-# If 'none', then symlinks are never followed when serving a request. When
47-# 'all', then all symlinks will be followed (this is dangerous)
48-follow-symlinks: none
49-
50-# Where to find a mime.types file for MIME media type information. If this is
51-# null (the default), an attempt will be made to find a suitable default.
52-#
53-# Note that according to https://crystal-lang.org/api/1.0.0/MIME.html, these
54-# will be searched first, otherwise the types defined in MIME::DFEFAULT_TYPES is
55-# used.
56-# /etc/mime.types
57-# /etc/httpd/mime.types # Mac OS X
58-# /etc/httpd/conf/mime.types # Apache
59-# /etc/apache/mime.types # Apache 1
60-# /etc/apache2/mime.types # Apache 2
61-# /usr/local/etc/httpd/conf/mime.types
62-# /usr/local/lib/netscape/mime.types
63-# /usr/local/etc/httpd/conf/mime.types # Apache 1.2
64-# /usr/local/etc/mime.types # FreeBSD
65-# /usr/share/misc/mime.types # OpenBSD
66-mime-file: null
67-#mime-file: /path/to/mime.types
68-
69-# Dictates how files of unknown MIME media types are served. If this is 'true',
70-# files of unknown types are served as 'application/octet-stream'. Otherwise
71-# they are not served, error type 40 is sent, and an error is printed on the
72-# console.
73-unknown-as-octet-stream: true
74-
75-# The location of the TLS certificate key.
76-tls-key: /path/to/your.key
77-
78-# The location of the certificate chain
79-cert-chain: /path/to/chain.crt
80-
81-# When this is greater than zero, this will enable rate limiting of connections.
82-# This value is in kilobytes, so 60 = 60KiB/sec. Setting this to 0 disables
83-# rate limiting.
84-rate-limit: 0
85-
86-# If this is not an empty string, this tells Aya to append a footer onto the end
87-# of every Gemtext page served.
88-footer: |
89- ``` Footer telling the user the page was served with Aya (https://osdn.net/users/yukiraven/pf/aya/)
90- ---------
91- Page served by Aya https://osdn.net/users/yukiraven/pf/aya/
92- Aya is under the GNU Affero GPLv3 license
93- ```
94-
95-# Controls what gets rate limited. When this is set to 'all', all content is
96-# rate limited. If this is 'nongemini', then anything that is **NOT** of type
97-# text/gemini is rate limited.
98-rate-limit-type: nongemini
99-
100-# Which network addresses to listen on. There must be at least one.
101-listen:
102- - localhost
103- #- 192.168.1.1
diff -r f8ed96c7941d -r dbbae5dcc82d shard.lock
--- a/shard.lock Sat Nov 18 16:01:35 2023 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
1-version: 2.0
2-shards:
3- idle-gc:
4- git: https://github.com/compumike/idle-gc.git
5- version: 1.0.1
6-
7- libremiliacr:
8- fossil: https://chiselapp.com/user/MistressRemilia/repository/libremiliacr
9- version: 0.11.2+fossil.commit.319b5887393250591f7091fdc25d158d4c479fee3c34f0a91d98d669e687c29b
10-
11- remigemini:
12- fossil: https://chiselapp.com/user/MistressRemilia/repository/remigemini
13- version: 0.2.1+fossil.commit.55f3ab9502a299e6d6291b2689eb7744492fee668bb8e62ca2ba11958459ffbd
14-
diff -r f8ed96c7941d -r dbbae5dcc82d shard.yml
--- a/shard.yml Sat Nov 18 16:01:35 2023 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
1-name: aya
2-version: 0.3.0
3-crystal: 1.5.0
4-license: AGPLv3
5-
6-authors:
7- - Remilia Scarlet <remilia@posteo.jp>
8-
9-targets:
10- aya:
11- main: src/main.cr
12-
13-dependencies:
14- remigemini:
15- fossil: https://chiselapp.com/user/MistressRemilia/repository/remigemini
16- commit: 55f3ab9502a299e6d6291b2689eb7744492fee668bb8e62ca2ba11958459ffbd
17-
18- idle-gc:
19- github: compumike/idle-gc
diff -r f8ed96c7941d -r dbbae5dcc82d src/config.cr
--- a/src/config.cr Sat Nov 18 16:01:35 2023 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,195 +0,0 @@
1-#### Aya - A Gemini server
2-#### Copyright (C) 2021-2022 Remilia Scarlet <remilia@posteo.jp>
3-####
4-#### This program is free software: you can redistribute it and/or modify
5-#### it under the terms of the GNU Affero General Public License as
6-#### published by the Free Software Foundation, either version 3 of the
7-#### License, or (at your option) any later version.
8-####
9-#### This program is distributed in the hope that it will be useful,
10-#### but WITHOUT ANY WARRANTY; without even the implied warranty of
11-#### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12-#### GNU Affero General Public License for more details.
13-####
14-#### You should have received a copy of the GNU Affero General Public License
15-#### along with this program. If not, see <https://www.gnu.org/licenses/>.
16-require "yaml"
17-
18-module Aya
19- struct Config
20- include YAML::Serializable
21- include YAML::Serializable::Strict
22-
23- # Dictates how symlinks are handled.
24- enum FollowType
25- None
26- All
27- end
28-
29- # Specifies the rate limiting behavior.
30- enum RateLimitBehavior
31- All
32- NonGemini
33- end
34-
35- # Where to look for files to serve.
36- @[YAML::Field(key: "server-root")]
37- getter serverRoot : String
38-
39- # The port number to use for connections.
40- @[YAML::Field(key: "listen-port")]
41- getter listenPort : UInt16 = 1965u16
42-
43- # Specifies how symlinks should be handled.
44- @[YAML::Field(key: "follow-symlinks")]
45- getter followSymlinks : FollowType = FollowType::None
46-
47- # If this is non-`nil`, this tells Aya to append a footer onto the end of
48- # every Gemtext page served.
49- getter footer : String? = nil
50-
51- # Where to find a mime.types file for MIME media type information. If this
52- # is `nil` (the default), then the default behavior of the `MIME` is used,
53- # with handlers for text/gemini added.
54- @[YAML::Field(key: "mime-file", emit_null: true)]
55- getter mimeFile : String? = nil
56-
57- # The location of the TLS certificate key.
58- @[YAML::Field(key: "tls-key")]
59- getter tlsKey : String
60-
61- # The location of the certificate chain
62- @[YAML::Field(key: "cert-chain")]
63- getter certChain : String
64-
65- # When non-nil, change to this UID after startup. If this is not specified,
66- # it uses the UID of whoever started the program.
67- getter uid : Int32?
68-
69- # When non-nil, change to this GID after startup. If this is not specified,
70- # it uses the GID of whoever started the program.
71- getter gid : Int32?
72-
73- # Dictates how files of unknown MIME media types are served. If this is
74- # `true`, files of unknown types are served as application/octet-stream.
75- # Otherwise they are not served, error type 40 is sent, and an error is
76- # printed on the console.
77- @[YAML::Field(key: "unknown-as-octet-stream")]
78- getter unknownAsOctetStream : Bool = false
79-
80- # When this is non-`nil`, all messages that are logged to standard
81- # output/standard error will be logged to this file as well.
82- @[YAML::Field(key: "log-file", emit_null: true)]
83- getter logFile : String? = nil
84-
85- # When this is a non-`nil`, all connections are logged here. This cannot be
86- # the same as `#logFile`.
87- @[YAML::Field(key: "conn-log-file", emit_null: true)]
88- getter connLogFile : String? = nil
89-
90- # When greater than zero, limit transfers to this number of kilobytes per
91- # second.
92- @[YAML::Field(key: "rate-limit")]
93- getter rateLimit : UInt64 = 0u64
94-
95- # Controls what gets rate limited. When this is set to
96- # `RateLimitBehavior::All`, all content is rate limited. If this is
97- # `RateLimitBehavior::NonGemini`, then anything that is _not_ of type
98- # text/gemini is rate limited.
99- @[YAML::Field(key: "rate-limit-type")]
100- getter rateLimitType : RateLimitBehavior = RateLimitBehavior::NonGemini
101-
102- # Which network addresses to listen on. There must be at least one.
103- getter listen : Array(String) = ["127.0.0.1"]
104-
105- # Files with these extensions will be treated as CGI programs to execute.
106- # Anything sent to standard output by these programs will be served as a
107- # response body. Output should include the response header and any
108- # applicable body. This should never be an empty list.
109- #
110- # Be sure to include the dot (.) in the extension name.
111- @[YAML::Field(key: "cgi-extensions")]
112- getter cgiExtensions : Array(String) = [".cgi"]
113-
114- # What to use for the PATH environment variable for CGI scripts. This is
115- # passed verbatim to the PATH environment variable when invoking a CGI
116- # script.
117- @[YAML::Field(key: "cgi-path")]
118- getter cgiPath : String = ""
119-
120- # Creates a new (but useless) `Config` instance.
121- def initialize
122- @serverRoot = ""
123- @tlsKey = ""
124- @certChain = ""
125- end
126-
127- # Creates a new `Config` by loading one from `path`. If `path` doesn't
128- # exist, or the file cannot be loaded, this will call
129- # `RemiLib::Logger#fatal` with an appropriate error message.
130- def self.fromFile(path : String|Path)
131- begin
132- if File.exists?(path)
133- @@config = Config.from_yaml(File.open(path))
134- else
135- RemiLib.log.fatal("Cannot find file: #{path}")
136- end
137- rescue err : YAML::Error
138- RemiLib.log.fatal("#{err}")
139- end
140- end
141-
142- # Performs various checks to see if this is a valid config file. If it
143- # isn't, this will call `RemiLib::Logger#fatal` with the appropriate
144- # message.
145- def validate : Nil
146- if @serverRoot.empty?
147- RemiLib.log.fatal("Server root path is empty")
148- elsif !Dir.exists?(@serverRoot)
149- RemiLib.log.fatal("Server root does not exist: #{Aya.config.serverRoot}")
150- end
151-
152- if @tlsKey.empty?
153- RemiLib.log.fatal("TLS certificate key path is empty")
154- elsif !File.exists?(@tlsKey)
155- RemiLib.log.fatal("TLS certificate key does not exist: #{Aya.config.tlsKey}")
156- end
157-
158- if @certChain.empty?
159- RemiLib.log.fatal("TLS certificate key path is empty")
160- elsif !File.exists?(@certChain)
161- RemiLib.log.fatal("TLS certificate chain does not exist: #{Aya.config.certChain}")
162- end
163-
164- if (mime = @mimeFile) && !File.exists?(mime)
165- RemiLib.log.fatal("MIME types file does not exist: #{mime}")
166- end
167-
168- if @listen.empty?
169- RemiLib.log.fatal("No interfaces to listen on")
170- end
171-
172- if @cgiExtensions.empty?
173- RemiLib.log.fatal("No CGI extensions defined")
174- end
175-
176- if (logpath = @logFile)
177- if (connpath = @connLogFile)
178- logpath = Path[logpath].normalize
179- connpath = Path[connpath].normalize
180- if connpath == logpath
181- RemiLib.log.fatal("log-file and conn-log-file cannot point to the same file")
182- end
183- end
184- end
185- end
186-
187- def self.dump(dest : String|Path) : Nil
188- File.open(dest, "w") { |file| Config.dump(file) }
189- end
190-
191- def self.dump(dest : IO) : Nil
192- dest << Config.new.to_yaml
193- end
194- end
195-end
diff -r f8ed96c7941d -r dbbae5dcc82d src/main.cr
--- a/src/main.cr Sat Nov 18 16:01:35 2023 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,267 +0,0 @@
1-#### Aya - A Gemini server
2-#### Copyright (C) 2021-2022 Remilia Scarlet <remilia@posteo.jp>
3-####
4-#### This program is free software: you can redistribute it and/or modify
5-#### it under the terms of the GNU Affero General Public License as
6-#### published by the Free Software Foundation, either version 3 of the
7-#### License, or (at your option) any later version.
8-####
9-#### This program is distributed in the hope that it will be useful,
10-#### but WITHOUT ANY WARRANTY; without even the implied warranty of
11-#### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12-#### GNU Affero General Public License for more details.
13-####
14-#### You should have received a copy of the GNU Affero General Public License
15-#### along with this program. If not, see <https://www.gnu.org/licenses/>.
16-require "mime"
17-require "yaml"
18-require "libremiliacr"
19-require "idle-gc"
20-require "./utils"
21-require "./config"
22-require "./server"
23-
24-module Aya
25- # The current version of the program.
26- VERSION = "0.3.0"
27-
28- # The default system-wide configuration file.
29- DEFAULT_CONFIG_FILE = "/etc/aya/aya-config.yaml"
30-
31- # The MIME type for Gemtext.
32- GEMINI_MIME_TYPE = "text/gemini; charset=utf-8"
33-
34- # These are the command line arguments.
35- @@args : RemiLib::Args::ArgParser = RemiLib::Args::ArgParser.new("Aya", VERSION)
36- class_getter args
37-
38- # The loaded configuration file.
39- @@config : Config? = nil
40- class_getter! config
41-
42- # When non-nil, this is a separate logger used to log connections.
43- @@connLogger : RemiLib::ConcurrentLogger? = nil
44- class_getter connLogger
45-
46- # The OpenSSL context to use for connections.
47- @@sslCtx : OpenSSL::SSL::Context::Server? = nil
48- class_getter! sslCtx
49-
50- # Initializes the command line arguments, then parses them.
51- private def self.initCmdLine
52- @@args.addString("config", 'c', help: "The configuration file to load")
53- @@args.addFlag("init-only", 'I', help: "Initialize, but do not start, Aya.")
54- @@args.addString("dump-config", help: "Dumps a fresh, default config to the given destination, then exits. The destination can be '-' to dump to standard output.")
55- @@args.addString("pid", 'P', help: "Write the PID of the progress to the destination. It will be deleted when the program exists.")
56- @@args.addFlag("verbose", 'v', group: "Logging", help: "Enable verbose messages")
57- @@args.addFlag("debug", 'g', group: "Logging", help: "Enable debug messages")
58-
59- begin
60- @@args.parse
61- rescue err : RemiLib::Args::ArgumentError
62- RemiLib.log.fatal("#{err}")
63- end
64- end
65-
66- # Initializes basic logging settings for the main `RemiLib.log` instance.
67- # This does NOT initialize any log files or the connection logging.
68- private def self.initLogging
69- if @@args["verbose"].called?
70- RemiLib.log.verbosityLevel = 255u8
71- end
72-
73- if @@args["debug"].called?
74- RemiLib.log.debugLevel = 255u8
75- RemiLib.log.verbosityLevel = 255u8
76- end
77-
78- RemiLib.log.timestamp = "%c"
79- RemiLib.log.defaultHeader = "Aya"
80- RemiLib.log.forceFlush = true
81- end
82-
83- private def self.initLogFiles
84- if (logfile = Aya.config.logFile)
85- begin
86- RemiLib.log.vlog("Init log file: #{logfile}")
87- RemiLib.log.otherStreams << File.open(logfile, "a")
88- rescue err : File::Error
89- RemiLib.log.fatal("Cannot open log file: #{err}")
90- end
91- end
92-
93- if (connFile = Aya.config.connLogFile)
94- begin
95- RemiLib.log.log("Logging connections to #{connFile}")
96- file = File.open(connFile, "a")
97- @@connLogger = RemiLib::ConcurrentLogger.new
98- @@connLogger.not_nil!.forceFlush = true
99- @@connLogger.not_nil!.defaultStream = file
100- @@connLogger.not_nil!.debugStream = file
101- @@connLogger.not_nil!.warnStream = file
102- @@connLogger.not_nil!.errorStream = file
103- @@connLogger.not_nil!.timestamp = "%c"
104- @@connLogger.not_nil!.defaultHeader = "Connection"
105- @@connLogger.not_nil!.start
106- rescue err : File::Error
107- RemiLib.log.fatal("Cannot open connection log file: #{err}")
108- end
109- else
110- RemiLib.log.log("Not logging connections")
111- end
112- end
113-
114-
115- # Loads the configuration file. If `--config`/`-c` is used, then the
116- # specified configuration file is loaded. Otherwise, an attempt is made to
117- # load the config located at `DEFAULT_CONFIG_FILE`. This will quit the
118- # program if no configuration file could be found.
119- private def self.initConfig
120- RemiLib.log.vlog("Init configuration file")
121-
122- if @@args["config"].called?
123- @@config = Config.fromFile(@@args["config"].str)
124- elsif File.exists?(DEFAULT_CONFIG_FILE)
125- @@config = Config.fromFile(DEFAULT_CONFIG_FILE)
126- else
127- RemiLib.log.fatal("No configuration file found#{!@@args["config"].called? ? " and none specified" : ""}")
128- end
129-
130- # Make sure the config is all good.
131- Aya.config.validate
132- end
133-
134- # Initializes the MIME types.
135- private def self.initMime
136- RemiLib.log.vlog("Init MIME database")
137- if (mimeFile = Aya.config.mimeFile)
138- RemiLib.log.vlog("Loading MIME type database: #{Aya.config.mimeFile}")
139- File.open(mimeFile) do |file|
140- MIME.load_mime_database(file)
141- end
142- end
143- end
144-
145- # Handle SIGINT signals.
146- Signal::INT.trap do
147- RemiLib.log.log("Ctrl-C detected, shutting down...")
148- RemiLib.log.otherStreams.each &.flush
149- RemiLib.log.otherStreams.each &.close
150- exit
151- end
152-
153- # Handle SIGTERM signals.
154- Signal::TERM.trap do
155- RemiLib.log.log("TERM signal detected, shutting down...")
156- RemiLib.log.otherStreams.each &.flush
157- RemiLib.log.otherStreams.each &.close
158- exit
159- end
160-
161- # Possibly excessive?
162- at_exit do
163- if @@args["pid"].called? && File.exists?(@@args["pid"].str)
164- File.delete(@@args["pid"].str)
165- end
166-
167- RemiLib.log.otherStreams.each &.flush
168- RemiLib.log.otherStreams.each &.close
169- end
170-
171- # Setup and parse command line arguments, then initialize the loggers
172- initCmdLine
173- initLogging
174-
175- @@args.withCalledStringArg("dump-config") do |arg|
176- begin
177- if arg.value == "-"
178- Config.dump(STDOUT)
179- STDOUT << '\n'
180- STDOUT.flush
181- else
182- Config.dump(arg.value)
183- puts "Dumped a new config to #{arg.value}"
184- end
185- exit 0
186- rescue err : Exception
187- RemiLib.log.fatal("Could not dump config file: #{err}")
188- end
189- end
190-
191- # Initialize config file and MIME table
192- initConfig
193- initMime
194-
195- # Exit if --init-only was used
196- exit 0 if @@args["init-only"].called?
197-
198- # Create the SSL context. We do this before changing UID/GID because, if Aya
199- # is started as root but changes to a non-privileged user, then ideally the
200- # key/cert chain are owned by root and not the target user.
201- begin
202- RemiLib.log.log("Loading SSL key and certificate chain")
203- @@sslCtx = RemiGemini::Server.makeSSLContext(Aya.config.tlsKey, Aya.config.certChain)
204- rescue err : Exception
205- RemiLib.log.fatal("Could not create TLS context: #{err}")
206- end
207-
208- # Possibly create a PID file.
209- @@args.withCalledStringArg("pid") do |arg|
210- begin
211- File.open(arg.value, "w") do |file|
212- file << Process.pid
213- end
214- rescue err : Exception
215- RemiLib.log.fatal("Could not write PID to #{arg.value}: #{err}")
216- end
217-
218- # Change ownership
219- begin
220- File.chmod(arg.value, 0o0644)
221- uid = Aya.config.uid
222- gid = Aya.config.gid
223-
224- if uid
225- if gid
226- File.chown(arg.value, uid: uid, gid: gid)
227- else
228- File.chown(arg.value, uid: uid)
229- end
230- elsif gid
231- File.chown(arg.value, gid: gid)
232- end
233- rescue err : Exception
234- RemiLib.log.fatal("Could not write PID to #{arg.value}: #{err}")
235- end
236- end
237-
238- # Change UID/GID as-needed. The GID must be set first in case the new UID
239- # does not have permissions to change the GID.
240- if (gid = Aya.config.gid)
241- RemiLib.log.log("Changing GID to #{gid}")
242- unless (err = LibC.setregid(gid, gid)) == 0
243- RemiLib.log.fatal("Could not change GID, error #{Errno.value}")
244- end
245- elsif LibC.getgid == 0
246- RemiLib.log.warn("You are running as the root group!")
247- end
248-
249- if (uid = Aya.config.uid)
250- RemiLib.log.log("Changing UID to #{uid}")
251- unless (err = LibC.setreuid(uid, uid)) == 0
252- RemiLib.log.fatal("Could not change UID, error #{Errno.value}")
253- end
254- elsif LibC.getuid == 0
255- RemiLib.log.warn("You are running as root!")
256- end
257-
258- RemiLib.log.warn("Real UID is still root!") if LibC.geteuid() == 0
259- RemiLib.log.warn("Real GID is still root!") if LibC.getegid() == 0
260-
261- # Initialize log files
262- initLogFiles
263-
264- # Initialize IdleGC, then start the server
265- IdleGC.start
266- Server.new.run
267-end
diff -r f8ed96c7941d -r dbbae5dcc82d src/server.cr
--- a/src/server.cr Sat Nov 18 16:01:35 2023 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,248 +0,0 @@
1-#### Aya - A Gemini server
2-#### Copyright (C) 2021-2022 Remilia Scarlet <remilia@posteo.jp>
3-####
4-#### This program is free software: you can redistribute it and/or modify
5-#### it under the terms of the GNU Affero General Public License as
6-#### published by the Free Software Foundation, either version 3 of the
7-#### License, or (at your option) any later version.
8-####
9-#### This program is distributed in the hope that it will be useful,
10-#### but WITHOUT ANY WARRANTY; without even the implied warranty of
11-#### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12-#### GNU Affero General Public License for more details.
13-####
14-#### You should have received a copy of the GNU Affero General Public License
15-#### along with this program. If not, see <https://www.gnu.org/licenses/>.
16-require "remigemini"
17-
18-module Aya
19- SHOW_DIRECTORY_FILE = ".showdir"
20-
21- class Server
22- @serv : RemiGemini::Server
23-
24- def initialize
25- RemiLib.log.log("Init server")
26- @serv = RemiGemini::Server.new(->handleConnection(RemiGemini::Server::Request))
27- end
28-
29- def run
30- RemiLib.log.log("Starting server")
31- Aya.config.listen.each do |addr|
32- begin
33- fancyAddr = @serv.bind(addr, Aya.sslCtx, port: Aya.config.listenPort)
34- RemiLib.log.log("Listening on gemini://#{fancyAddr}")
35- rescue err : Exception
36- RemiLib.log.error("#{err}")
37- end
38- end
39-
40- @serv.listen
41- end
42-
43- private def transferFile(sock : IO, mtype : String, path : Path)
44- File.open(path) do |infile|
45- if Aya.config.rateLimit > 0 && (Aya.config.rateLimitType.all? || mtype != GEMINI_MIME_TYPE)
46- sock.rateLimitedCopy(Aya.config.rateLimit * 1024, infile)
47- else
48- IO.copy(infile, sock)
49- end
50- end
51-
52- if mtype == GEMINI_MIME_TYPE
53- Aya.config.footer.try { |str| sock << '\n' << str << '\n' }
54- end
55- end
56-
57- private def validURI?(uri : URI) : Bool
58- return false unless uri.scheme == "gemini"
59- return false unless uri.host
60- return false if uri.userinfo
61- true
62- end
63-
64- private def serveDirectory(sock, uri, path)
65- uriPath = Path[uri.path]
66-
67- gemtext = String.build do |str|
68- str << "# Listing of #{uri}\n\n"
69-
70- if inServerRoot?(path.parent) && File.exists?(Dir[path.parent].join(SHOW_DIRECTORY_FILE))
71- str << "=> #{uriPath.parent} (up one directory)\n"
72- end
73-
74- Dir.each_child(path) do |child|
75- fullpath = path.join(child)
76- unless File.info(fullpath).symlink? || fullpath.basename == SHOW_DIRECTORY_FILE
77- str << "=> #{uriPath.join(child)} #{child}\n"
78- end
79- end
80- end
81-
82- sock << "20 #{GEMINI_MIME_TYPE}\r\n"
83- sock << gemtext
84- Aya.config.footer.try { |str| sock << '\n' << str << '\n' }
85- return
86- end
87-
88- private def inServerRoot?(path : Path) : Bool
89- begin
90- otherParts = path.parts
91- Path[Aya.config.serverRoot].parts.each_with_index do |part, idx|
92- return false unless otherParts[idx] == part
93- end
94- rescue Exception
95- return false
96- end
97-
98- true
99- end
100-
101- def handleConnection(req : RemiGemini::Server::Request) : Nil
102- uri = req.uri
103- sock = req.sock.as?(OpenSSL::SSL::Socket)
104- unless sock
105- RemiLib.log.error("RemiGemini library gave us a socket of type #{req.sock.class}")
106- req.sock << "40 Internal error\r\n"
107- return
108- end
109-
110- begin
111- # Convert the URI's path into a Path instance
112- path = Path[Aya.config.serverRoot].join(uri.path).normalize
113-
114- # Path must be inside the server root
115- unless inServerRoot?(path)
116- Aya.connLogger.try &.log("#{sock.local_address} :: 51 Not Found: #{uri.path}")
117- sock << "51 Not found: #{uri.path}\r\n"
118- return
119- end
120-
121- if Dir.exists?(path)
122- if File.exists?(path.join(SHOW_DIRECTORY_FILE))
123- # Generate a dynamic directory listing
124- serveDirectory(sock, uri, path)
125- return
126- else
127- # Append index.gmi to the path
128- path = path.join("index.gmi")
129- end
130- elsif path.basename == SHOW_DIRECTORY_FILE
131- # Never serve .showdir files
132- Aya.connLogger.try &.log("#{sock.local_address} :: 51 Not Found: #{uri.path}")
133- sock << "51 Not found: #{uri.path}\r\n"
134- return
135- else
136- # Requested file must exist
137- unless File.exists?(path)
138- Aya.connLogger.try &.log("#{sock.local_address} :: 51 Not Found: #{uri.path}")
139- sock << "51 Not found: #{uri.path}\r\n"
140- return
141- end
142- end
143-
144- # Requested file must exist
145- unless File.exists?(path)
146- Aya.connLogger.try &.log("#{sock.local_address} :: 51 Not Found: #{uri.path}")
147- sock << "51 Not found: #{uri.path}\r\n"
148- return
149- end
150-
151- # Handle symlinks
152- if File.info(path).symlink? && Aya.config.followSymlinks.none?
153- Aya.connLogger.try &.log("#{sock.local_address} :: 51 Not Found: #{uri.path}")
154- sock << "51 Not found\r\n"
155- return
156- end
157-
158- path.each_parent do |parent|
159- if File.info(parent).symlink? && Aya.config.followSymlinks.none?
160- Aya.connLogger.try &.log("#{sock.local_address} :: 51 Not Found: #{uri.path}")
161- sock << "51 Not found\r\n"
162- return
163- end
164- end
165-
166- # CGI script? Handle that separately.
167- if Aya.config.cgiExtensions.includes?(path.extension)
168- handleCGI(sock, uri, path)
169- return
170- end
171-
172- # Serve the request
173- begin
174- mtype = MIME.from_filename?(path)
175- unless mtype
176- if Aya.config.unknownAsOctetStream
177- mtype = "application/octet-stream"
178- else
179- sock << "40 Internal error\r\n"
180- RemiLib.log.error("Cannot serve file, unknown MIME type: #{path}")
181- return
182- end
183- end
184-
185- Aya.connLogger.try &.log("#{sock.local_address} :: 20: #{uri.path}")
186- sock << "20 #{mtype.not_nil!}\r\n"
187- transferFile(sock, mtype, path)
188- IdleGC.background_collect
189- rescue err : File::NotFoundError
190- sock << "51 Not found: #{uri.path}\r\n"
191- return
192- end
193- rescue err : Exception
194- Aya.connLogger.try &.log("#{sock.local_address} :: 40 Internal error: #{uri.path}")
195- sock << "40 Internal error\r\n"
196- RemiLib.log.error("#{typeof(err)} while attempting to serve #{uri}")
197- RemiLib.log.error(err)
198- ensure
199- sock.close
200- end
201- end
202-
203- private def handleCGI(sock, uri, path)
204- # Setup the environment we'll use for the process.
205- env = {} of String => String
206- env["DOCUMENT_ROOT"] = Aya.config.serverRoot
207- env["GATEWAY_INTERFACE"] = "ACGI 0.1.0" # "Aya CGI" with symver
208- env["PATH_INFO"] = uri.path || ""
209- env["PATH_TRANSLATED"] = path.to_s
210- env["SCRIPT_FILENAME"] = path.basename.to_s
211- env["QUERY_STRING"] = uri.query || ""
212- env["REQUEST_FRAGMENT"] = uri.fragment || ""
213- env["SERVER_HOST"] = uri.host || ""
214- env["SERVER_PORT"] = uri.port.try &.to_s || Aya.config.listenPort.to_s
215- env["PATH"] = Aya.config.cgiPath
216-
217- begin
218- # Start the process and connect I/O
219- proc = Process.new(path.to_s, env: env, clear_env: true,
220- input: Process::Redirect::Pipe, output: Process::Redirect::Pipe,
221- error: Process::Redirect::Pipe)
222- # HACK This will easily eat ram.
223- result = proc.output.gets_to_end
224- error = proc.error.gets_to_end
225-
226- # Wait for the process to finish, then send a response.
227- status = proc.wait
228- if status.success?
229- sock << result
230- else
231- RemiLib.log.error("CGI script #{path} exited with status #{status.exit_code}")
232- Aya.connLogger.try &.log("#{sock.local_address} :: 40 Internal error: #{uri.path}")
233- sock << "40 Internal Error\r\n"
234- end
235-
236- # If we had output on stderr, log that now.
237- unless error.empty?
238- RemiLib.log.error("Error while executing #{path}: #{error}")
239- end
240- rescue err : IO::Error
241- # Process failed to start! D:
242- RemiLib.log.error("Error executing #{path}: #{err}")
243- Aya.connLogger.try &.log("#{sock.local_address} :: 40 Internal error: #{uri.path}")
244- sock << "40 Internal error\r\n"
245- end
246- end
247- end
248-end
diff -r f8ed96c7941d -r dbbae5dcc82d src/utils.cr
--- a/src/utils.cr Sat Nov 18 16:01:35 2023 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
1-#### Aya - A Gemini server
2-#### Copyright (C) 2021-2022 Remilia Scarlet <remilia@posteo.jp>
3-####
4-#### This program is free software: you can redistribute it and/or modify
5-#### it under the terms of the GNU Affero General Public License as
6-#### published by the Free Software Foundation, either version 3 of the
7-#### License, or (at your option) any later version.
8-####
9-#### This program is distributed in the hope that it will be useful,
10-#### but WITHOUT ANY WARRANTY; without even the implied warranty of
11-#### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12-#### GNU Affero General Public License for more details.
13-####
14-#### You should have received a copy of the GNU Affero General Public License
15-#### along with this program. If not, see <https://www.gnu.org/licenses/>.
16-
17-lib LibC
18- # This was introduced in Crystal 1.4.0
19- {% if compare_versions(Crystal::VERSION, "1.5.0") < 0 %}
20- fun getuid() : Int32
21- {% end %}
22-
23- fun setregid(rgid : Int32, egid : Int32) : Int32
24- fun setreuid(ruid : Int32, euid : Int32) : Int32
25- fun getgid() : Int32
26- fun geteuid() : Int32
27- fun getegid() : Int32
28-end