Compare commits
69 Commits
33a31dac32
...
main
Author | SHA1 | Date | |
---|---|---|---|
b447c8cf13 | |||
e212d43bf2 | |||
2bf94c0f3c | |||
3f49d8294a | |||
323b76fe98 | |||
f714bc6eaa | |||
8ad2778dd0 | |||
0d99a7da69 | |||
c049f6c44a | |||
9acbe212ad | |||
aa29cca4f4 | |||
afc0a30660 | |||
647634addc | |||
dba65911a6 | |||
1067d0a3fd | |||
1ffd51b641 | |||
cd97df5f21 | |||
12dedf3700 | |||
ade745cdc5 | |||
ab5977eaae | |||
39813d246f | |||
975626fc5c | |||
1f47d59760 | |||
38abe411a8 | |||
e7216d51e3 | |||
2b244645c6 | |||
43589f7ddc | |||
b43a219fb3 | |||
7bf92f9049 | |||
577195cb7f | |||
fc64b742bb | |||
922eaeb124 | |||
65ec5a51aa | |||
8036b0c1e1 | |||
c505698b0b
|
|||
4e08375748
|
|||
912bf616b6
|
|||
d1ddbf2605 | |||
66b01bd58d | |||
01468670e3 | |||
1f09aae11e | |||
ce1ac7b09e | |||
f9faddf660 | |||
945f1b84f2 | |||
a9d2633107
|
|||
506d16e0c9
|
|||
30c3b0c37b | |||
2da4f81a6b | |||
cc482fc0ad | |||
51ea22fbc5 | |||
58595d5eb3 | |||
671d44017f | |||
95d24b734b | |||
c2e31fb440 | |||
2d3dab5646 | |||
4b2e12b374 | |||
c6323cae38 | |||
e05d42a956 | |||
426c474016 | |||
91ca908980 | |||
5a61508359 | |||
86c0e3cc97 | |||
1afa33f28b | |||
a22b1e67c8 | |||
f477b4525b | |||
462d35ea0d | |||
693c94274a | |||
af2e5b49ae | |||
00b7227d4d |
141
README.md
141
README.md
@ -4,85 +4,112 @@
|
||||

|
||||

|
||||
|
||||
This repo contains all the source code for my personal website, [ngn.tf](https://ngn.tf)
|
||||
All code is licensed under AGPL version 3 (see [LICENSE.txt](LICENSE.txt))
|
||||
This repo contains all the source code for my personal website,
|
||||
[ngn.tf](https://ngn.tf) All code is licensed under AGPL version 3 (see
|
||||
[LICENSE.txt](LICENSE.txt))
|
||||
|
||||
## Directory structure
|
||||
|
||||
### `app`
|
||||
|
||||
Contains frontend application, written with SvelteKit. It supports full SSR.
|
||||
Contains modified CSS from [github-markdown-css](https://github.com/sindresorhus/github-markdown-css)
|
||||
and fonts from [NerdFonts](https://www.nerdfonts.com/)
|
||||
Contains modified CSS from
|
||||
[github-markdown-css](https://github.com/sindresorhus/github-markdown-css) and
|
||||
fonts from [NerdFonts](https://www.nerdfonts.com/)
|
||||
|
||||
### `api`
|
||||
Contains the API server, written in Go. It uses the [Fiber](https://github.com/gofiber/fiber) web
|
||||
framework which offers an [Express](https://expressjs.com/) like experience. I choose Fiber since I've used
|
||||
worked with express a lot in the past. However previously the I was using [Gin](https://github.com/gin-gonic/gin)
|
||||
(see history section).
|
||||
|
||||
API stores all the data in a local SQLite(3) database. Go doesn't support SQLite3 out of the box so
|
||||
I'm using [mattn's sqlite3 driver](https://github.com/mattn/go-sqlite3).
|
||||
Contains the API server, written in Go. It uses the
|
||||
[Fiber](https://github.com/gofiber/fiber) web framework which offers an
|
||||
[Express](https://expressjs.com/) like experience. I choose Fiber since I've
|
||||
used worked with express a lot in the past. However previously the I was using
|
||||
[Gin](https://github.com/gin-gonic/gin) (see history section).
|
||||
|
||||
API stores all the data in a local SQLite(3) database. Go doesn't support
|
||||
SQLite3 out of the box so I'm using
|
||||
[mattn's sqlite3 driver](https://github.com/mattn/go-sqlite3).
|
||||
|
||||
### `doc`
|
||||
Contains the documentation server, written in C. It uses the [ctorm](https://github.com/ngn13/ctorm) web
|
||||
framework, which is a framework that I myself wrote. Unlike the frontend application or the API server, it's not
|
||||
accessable by public, the frontend application gets the documentation content from this server and renders it using
|
||||
SSR. The reason I don't use the API for hosting the documentation content is that I want a separate server for hosting
|
||||
|
||||
Contains the documentation server, written in C. It uses the
|
||||
[ctorm](https://github.com/ngn13/ctorm) web framework, which is a framework that
|
||||
I myself wrote. Unlike the frontend application or the API server, it's not
|
||||
accessable by public, the frontend application gets the documentation content
|
||||
from this server and renders it using SSR. The reason I don't use the API for
|
||||
hosting the documentation content is that I want a separate server for hosting
|
||||
static content, API is only for hosting dynamic stuff.
|
||||
|
||||
### `admin`
|
||||
The frontend application does not contain an admin interface, I do the administration stuff (such as adding news posts,
|
||||
adding services etc.) using the python script in this directory. This script can be installed on to the PATH by running
|
||||
the Makefile install script. After installation it can be used by running `admin_script`.
|
||||
|
||||
The frontend application does not contain an admin interface, I do the
|
||||
administration stuff (such as adding news posts, adding services etc.) using the
|
||||
python script in this directory. This script can be installed on to the PATH by
|
||||
running the Makefile install script. After installation it can be used by
|
||||
running `admin_script`.
|
||||
|
||||
## Deployment
|
||||
Easiest way to deploy is to use docker. There is `compose.yml` and a `run.sh` script in the [deploy](deploy/) directory
|
||||
that can be used to startup all the docker containers. Configuration options are passed during build time for the frontend
|
||||
application, and for others it's passed with environment variables.
|
||||
|
||||
Easiest way to deploy is to use docker. There is `compose.yml` and a `run.sh`
|
||||
script in the [deploy](deploy/) directory that can be used to startup all the
|
||||
docker containers. Configuration options are passed during build time for the
|
||||
frontend application, and for others it's passed with environment variables.
|
||||
|
||||
## History
|
||||
|
||||
Some nostalgic history/changelog stuff (just for the major version numbers):
|
||||
|
||||
- **v0.1 (late 2020 - early 2021)**: First ever version of my website, it was just a simple HTML/CSS page,
|
||||
I never published any of the source code and I wiped the local copy on my USB drive in early 2022, I still
|
||||
remember what it looked like though, it looked like I made entire website in microsoft paint... while blindfoled,
|
||||
so yeah it was shit.
|
||||
- **v0.1 (late 2020 - early 2021)**: First ever version of my website, it was
|
||||
just a simple HTML/CSS page, I never published any of the source code and I
|
||||
wiped the local copy on my USB drive in early 2022, I still remember what it
|
||||
looked like though, it looked like I made entire website in microsoft paint...
|
||||
while blindfoled, so yeah it was shit.
|
||||
|
||||
- **v1.0 (early 2021 - late 2022)**: This version was actualy hosted on my github.io page, and all the source code
|
||||
was (and still is) avaliable, it was just a simple static site, [here is a screenshot](assets/githubio.png).
|
||||
- **v1.0 (early 2021 - late 2022)**: This version was actualy hosted on my
|
||||
github.io page, and all the source code was (and still is) avaliable, it was
|
||||
just a simple static site, [here is a screenshot](assets/githubio.png).
|
||||
|
||||
- **vLOST (late 2022 - early 2023)**: As I learned more JS, I decided to rewrite (and rework) my website with one
|
||||
of the fancy JS frameworks. I decided to go with Svelte. Not the kit version, at the time svelte did not support SSR.
|
||||
I do not remember writting an API for it so I guess I just updated it everytime I wanted to add content? It was pretty
|
||||
much like a static website and was hosted on `ngn13.fun` as at this point I had my own hosting. The source code for
|
||||
this website was in a deleted github repository of mine, I looked for a local copy on my old hard drive but I wasn't able
|
||||
to find it. I also do not remember how it looked like, sooo this version is pretty much lost :(
|
||||
- **vLOST (late 2022 - early 2023)**: As I learned more JS, I decided to rewrite
|
||||
(and rework) my website with one of the fancy JS frameworks. I decided to go
|
||||
with Svelte. Not the kit version, at the time svelte did not support SSR. I do
|
||||
not remember writting an API for it so I guess I just updated it everytime I
|
||||
wanted to add content? It was pretty much like a static website and was hosted
|
||||
on `ngn13.fun` as at this point I had my own hosting. The source code for this
|
||||
website was in a deleted github repository of mine, I looked for a local copy
|
||||
on my old hard drive but I wasn't able to find it. I also do not remember how
|
||||
it looked like, sooo this version is pretty much lost :(
|
||||
|
||||
- **v2.0 (early 2023 - late 2023)**: After I discovered what SSR is, I decided to rewrite and rework my website one more
|
||||
time in NuxtJS. I had really "fun" time using vue stuff. As NuxtJS supported server-side code, this website had its own
|
||||
built in API. This website was also hosted on `ngn13.fun`. This also the first version that lives on this git repository.
|
||||
- **v2.0 (early 2023 - late 2023)**: After I discovered what SSR is, I decided
|
||||
to rewrite and rework my website one more time in NuxtJS. I had really "fun"
|
||||
time using vue stuff. As NuxtJS supported server-side code, this website had
|
||||
its own built in API. This website was also hosted on `ngn13.fun`. This also
|
||||
the first version that lives on this git repository.
|
||||
|
||||
- **v3.0 (2023 august - 2023 november)**: In agust of 2023, I decided to rewrite and rework my website again, this time
|
||||
I was going with SvelteKit as I haven't had the greatest experience with NuxtJS. SvelteKit was really fun to work with
|
||||
and I got my new website done pretty quickly. (I don't wanna brag or something but I really imporeved the CSS/styling
|
||||
stuff ya know). I also wrote a new API with Go and Gin. I did not publish the source code for the API, the code lived
|
||||
on my local git server until I deleted it when I was done with 6.0. This website was hosted on `ngn13.fun` as well.
|
||||
- **v3.0 (2023 august - 2023 november)**: In agust of 2023, I decided to rewrite
|
||||
and rework my website again, this time I was going with SvelteKit as I haven't
|
||||
had the greatest experience with NuxtJS. SvelteKit was really fun to work with
|
||||
and I got my new website done pretty quickly. (I don't wanna brag or something
|
||||
but I really imporeved the CSS/styling stuff ya know). I also wrote a new API
|
||||
with Go and Gin. I did not publish the source code for the API, the code lived
|
||||
on my local git server until I deleted it when I was done with 6.0. This
|
||||
website was hosted on `ngn13.fun` as well.
|
||||
|
||||
- **v4.0 (2023 november - 2024 october)**: In this version the frontend was still similar to 3.0, the big changes are in
|
||||
the API. I rewrote the API with Fiber. This version was the first version hosted on `ngn.tf` which is my new domain name.
|
||||
Here is a [picture of the index](assets/4.0_index.png) and the [blog page](assets/4.0_blog.png).
|
||||
- **v4.0 (2023 november - 2024 october)**: In this version the frontend was
|
||||
still similar to 3.0, the big changes are in the API. I rewrote the API with
|
||||
Fiber. This version was the first version hosted on `ngn.tf` which is my new
|
||||
domain name. Here is a [picture of the index](assets/4.0_index.png) and the
|
||||
[blog page](assets/4.0_blog.png).
|
||||
|
||||
- **v5.0 (2024 october - 2025 january)**: This version just had simple frontend UI changes compared to 4.0, at this
|
||||
point I was thinking about doing a massive rework (which I did with 6.0), however I was working on some other shit at
|
||||
the time, so I just did some small changes with the limited time I had for this project.
|
||||
- **v5.0 (2024 october - 2025 january)**: This version just had simple frontend
|
||||
UI changes compared to 4.0, at this point I was thinking about doing a massive
|
||||
rework (which I did with 6.0), however I was working on some other shit at the
|
||||
time, so I just did some small changes with the limited time I had for this
|
||||
project.
|
||||
|
||||
- **v6.0 (2025 january - ...)**: The current major version of my website, frontend had a massive rework, API has been
|
||||
cleaned up and extended to do status checking for the services I host. The `doc` server has been added to the mix
|
||||
so I can host static documentation. The most important thing about this version is that it adds multi-language support,
|
||||
so literally everything on the website (including the API and documentation content) is localized for both English
|
||||
and Turkish, which was something I wanted to do for the longest time ever.
|
||||
|
||||
Damn it has been 4 years since I wrote that shit HTML page huh? Time flies...
|
||||
|
||||
## Screenshots (from v6.0)
|
||||

|
||||

|
||||
- **v6.0 (2025 january - ...)**: The current major version of my website,
|
||||
frontend had a massive rework, API has been cleaned up and extended to do
|
||||
status checking for the services I host. The `doc` server has been added to
|
||||
the mix so I can host static documentation. The most important thing about
|
||||
this version is that it adds multi-language support, so literally everything
|
||||
on the website (including the API and documentation content) is localized for
|
||||
both English and Turkish, which was something I wanted to do for the longest
|
||||
time ever.
|
||||
|
@ -1,4 +1,4 @@
|
||||
FROM golang:1.24.2
|
||||
FROM golang:1.24.4
|
||||
|
||||
WORKDIR /api
|
||||
|
||||
|
@ -3,8 +3,9 @@ module github.com/ngn13/website/api
|
||||
go 1.24.0
|
||||
|
||||
require (
|
||||
github.com/gofiber/fiber/v2 v2.52.6
|
||||
github.com/mattn/go-sqlite3 v1.14.27
|
||||
github.com/gofiber/fiber/v2 v2.52.8
|
||||
github.com/mattn/go-sqlite3 v1.14.28
|
||||
github.com/ngn13/ortam v0.0.0-20250421004351-8dea81680817
|
||||
)
|
||||
|
||||
require (
|
||||
@ -14,7 +15,6 @@ require (
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/ngn13/ortam v0.0.0-20250412195317-e76e62a7a305 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasthttp v1.51.0 // indirect
|
||||
|
@ -2,6 +2,8 @@ github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1
|
||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||
github.com/gofiber/fiber/v2 v2.52.6 h1:Rfp+ILPiYSvvVuIPvxrBns+HJp8qGLDnLJawAu27XVI=
|
||||
github.com/gofiber/fiber/v2 v2.52.6/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
|
||||
github.com/gofiber/fiber/v2 v2.52.8 h1:xl4jJQ0BV5EJTA2aWiKw/VddRpHrKeZLF0QPUxqn0x4=
|
||||
github.com/gofiber/fiber/v2 v2.52.8/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||
@ -15,8 +17,12 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.27 h1:drZCnuvf37yPfs95E5jd9s3XhdVWLal+6BOK6qrv6IU=
|
||||
github.com/mattn/go-sqlite3 v1.14.27/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A=
|
||||
github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/ngn13/ortam v0.0.0-20250412195317-e76e62a7a305 h1:1YxtSMwR14PklXNlZxIqcmfpiq2+G98YNmhSuz7GKCQ=
|
||||
github.com/ngn13/ortam v0.0.0-20250412195317-e76e62a7a305/go.mod h1:MSJZ4ZstrLvVEvivbp9hhup+iL8rvtpgKcYaF3DSOKk=
|
||||
github.com/ngn13/ortam v0.0.0-20250421004351-8dea81680817 h1:WkHM4w51N5jCsWcDVcPsXz3zhi/kCfNp/VGh2uPjwsk=
|
||||
github.com/ngn13/ortam v0.0.0-20250421004351-8dea81680817/go.mod h1:MSJZ4ZstrLvVEvivbp9hhup+iL8rvtpgKcYaF3DSOKk=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
|
@ -1,5 +1,5 @@
|
||||
# build the application with node
|
||||
FROM node:23.11.0 AS build
|
||||
FROM node:23.11.1 AS build
|
||||
|
||||
ARG WEBSITE_REPORT_URL
|
||||
ARG WEBSITE_SOURCE_URL
|
||||
|
94
app/package-lock.json
generated
94
app/package-lock.json
generated
@ -841,14 +841,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@sveltejs/adapter-auto": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-auto/-/adapter-auto-6.0.0.tgz",
|
||||
"integrity": "sha512-7mR2/G7vlXakaOj6QBSG9dwBfTgWjV+UnEMB5Z6Xu0ZbdXda6c0su1fNkg0ab0zlilSkloMA2NjCna02/DR7sA==",
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-auto/-/adapter-auto-6.0.1.tgz",
|
||||
"integrity": "sha512-mcWud3pYGPWM2Pphdj8G9Qiq24nZ8L4LB7coCUckUEy5Y7wOWGJ/enaZ4AtJTcSm5dNK1rIkBRoqt+ae4zlxcQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"import-meta-resolve": "^4.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@sveltejs/kit": "^2.0.0"
|
||||
}
|
||||
@ -870,23 +867,25 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@sveltejs/kit": {
|
||||
"version": "2.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.20.5.tgz",
|
||||
"integrity": "sha512-zT/97KvVUo19jEGZa972ls7KICjPCB53j54TVxnEFT5VEwL16G+YFqRVwJbfxh7AmS7/Ptr1rKF7Qt4FBMDNlw==",
|
||||
"version": "2.22.0",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.22.0.tgz",
|
||||
"integrity": "sha512-DJm0UxVgzXq+1MUfiJK4Ridk7oIQsIets6JwHiEl97sI6nXScfXe+BeqNhzB7jQIVBb3BM51U4hNk8qQxRXBAA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sveltejs/acorn-typescript": "^1.0.5",
|
||||
"@types/cookie": "^0.6.0",
|
||||
"acorn": "^8.14.1",
|
||||
"cookie": "^0.6.0",
|
||||
"devalue": "^5.1.0",
|
||||
"esm-env": "^1.2.2",
|
||||
"import-meta-resolve": "^4.1.0",
|
||||
"kleur": "^4.1.5",
|
||||
"magic-string": "^0.30.5",
|
||||
"mrmime": "^2.0.0",
|
||||
"sade": "^1.8.1",
|
||||
"set-cookie-parser": "^2.6.0",
|
||||
"sirv": "^3.0.0"
|
||||
"sirv": "^3.0.0",
|
||||
"vitefu": "^1.0.6"
|
||||
},
|
||||
"bin": {
|
||||
"svelte-kit": "svelte-kit.js"
|
||||
@ -895,9 +894,9 @@
|
||||
"node": ">=18.13"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0",
|
||||
"svelte": "^4.0.0 || ^5.0.0-next.0",
|
||||
"vite": "^5.0.3 || ^6.0.0"
|
||||
"vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sveltejs/vite-plugin-svelte": {
|
||||
@ -966,9 +965,10 @@
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.14.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
||||
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
|
||||
"version": "8.14.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
|
||||
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@ -1084,9 +1084,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/dompurify": {
|
||||
"version": "3.2.5",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.5.tgz",
|
||||
"integrity": "sha512-mLPd29uoRe9HpvwP2TxClGQBzGXeEC/we/q+bFlmPPmj2p2Ugl3r6ATu/UU1v77DXNcehiBg9zsr1dREyA/dJQ==",
|
||||
"version": "3.2.6",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.6.tgz",
|
||||
"integrity": "sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==",
|
||||
"license": "(MPL-2.0 OR Apache-2.0)",
|
||||
"optionalDependencies": {
|
||||
"@types/trusted-types": "^2.0.7"
|
||||
@ -1204,9 +1204,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esrap": {
|
||||
"version": "1.4.6",
|
||||
"resolved": "https://registry.npmjs.org/esrap/-/esrap-1.4.6.tgz",
|
||||
"integrity": "sha512-F/D2mADJ9SHY3IwksD4DAXjTt7qt7GWUf3/8RhCNWmC/67tyb55dpimHmy7EplakFaflV0R/PC+fdSPqrRHAQw==",
|
||||
"version": "1.4.9",
|
||||
"resolved": "https://registry.npmjs.org/esrap/-/esrap-1.4.9.tgz",
|
||||
"integrity": "sha512-3OMlcd0a03UGuZpPeUC1HxR3nA23l+HEyCiZw3b3FumJIN9KphoGzDJKMXI1S72jVS1dsenDyQC0kJlO1U9E1g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.4.15"
|
||||
@ -1299,17 +1299,6 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/import-meta-resolve": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz",
|
||||
"integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/intl-messageformat": {
|
||||
"version": "10.7.11",
|
||||
"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.11.tgz",
|
||||
@ -1396,9 +1385,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/marked": {
|
||||
"version": "15.0.11",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-15.0.11.tgz",
|
||||
"integrity": "sha512-1BEXAU2euRCG3xwgLVT1y0xbJEld1XOrmRJpUwRCcy7rxhSCwMrmEu9LXoPhHSCJG41V7YcQ2mjKRr5BA3ITIA==",
|
||||
"version": "15.0.12",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-15.0.12.tgz",
|
||||
"integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"marked": "bin/marked.js"
|
||||
@ -1543,9 +1532,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-plugin-svelte": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.3.3.tgz",
|
||||
"integrity": "sha512-yViK9zqQ+H2qZD1w/bH7W8i+bVfKrD8GIFjkFe4Thl6kCT9SlAsXVNmt3jCvQOCsnOhcvYgsoVlRV/Eu6x5nNw==",
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.4.0.tgz",
|
||||
"integrity": "sha512-pn1ra/0mPObzqoIQn/vUTR3ZZI6UuZ0sHqMK5x2jMLGrs53h0sXhkVuDcrlssHwIMk7FYrMjHBPoUSyyEEDlBQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
@ -1661,9 +1650,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/svelte": {
|
||||
"version": "5.26.2",
|
||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.26.2.tgz",
|
||||
"integrity": "sha512-e2TEcGK2YKVwDWYy5OsptVclYgDvfY1E/8IzPiOq63uG/GDo/j5VUYTC9EinQNraoZalbMWN+5f5TYC1QlAqOw==",
|
||||
"version": "5.34.7",
|
||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.34.7.tgz",
|
||||
"integrity": "sha512-5PEg+QQKce4t1qiOtVUhUS3AQRTtxJyGBTpxLcNWnr0Ve8q4r06bMo0Gv8uhtCPWlztZHoi3Ye7elLhu+PCTMg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.3.0",
|
||||
@ -1675,7 +1664,7 @@
|
||||
"axobject-query": "^4.1.0",
|
||||
"clsx": "^2.1.1",
|
||||
"esm-env": "^1.2.1",
|
||||
"esrap": "^1.4.6",
|
||||
"esrap": "^1.4.8",
|
||||
"is-reference": "^3.0.3",
|
||||
"locate-character": "^3.0.0",
|
||||
"magic-string": "^0.30.11",
|
||||
@ -2160,9 +2149,9 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "5.4.18",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.18.tgz",
|
||||
"integrity": "sha512-1oDcnEp3lVyHCuQ2YFelM4Alm2o91xNoMncRm1U7S+JdYfYOvbiGZ3/CxGttrOu2M/KcGz7cRC2DoNUA6urmMA==",
|
||||
"version": "5.4.19",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz",
|
||||
"integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -2220,12 +2209,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vitefu": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.0.3.tgz",
|
||||
"integrity": "sha512-iKKfOMBHob2WxEJbqbJjHAkmYgvFDPhuqrO82om83S8RLk+17FtyMBfcyeH8GqD0ihShtkMW/zzJgiA51hCNCQ==",
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.0.6.tgz",
|
||||
"integrity": "sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"tests/deps/*",
|
||||
"tests/projects/*"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0-beta.0"
|
||||
"vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"vite": {
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 156 KiB |
Binary file not shown.
Before Width: | Height: | Size: 111 KiB |
@ -81,7 +81,7 @@ BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 120
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
|
35
doc/.clang-tidy
Normal file
35
doc/.clang-tidy
Normal file
@ -0,0 +1,35 @@
|
||||
---
|
||||
# "gnu-zero-variadic-macro-arguments" ignored because we are using GNU99
|
||||
# standart
|
||||
|
||||
# "clang-diagnostic-language-extension-token" is ignored because we need the
|
||||
# asm() extension token
|
||||
|
||||
# "DeprecatedOrUnsafeBufferHandling" ignored because C11 "_s" functions are not
|
||||
# secure either
|
||||
Checks: >-
|
||||
clang-diagnostic-*,
|
||||
-clang-diagnostic-gnu-zero-variadic-macro-arguments,
|
||||
-clang-diagnostic-language-extension-token,
|
||||
clang-analyzer-*,
|
||||
-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
|
||||
portability-*,
|
||||
performance-*,
|
||||
WarningsAsErrors: '*'
|
||||
HeaderFileExtensions:
|
||||
- ''
|
||||
- h
|
||||
- hh
|
||||
- hpp
|
||||
- hxx
|
||||
ImplementationFileExtensions:
|
||||
- c
|
||||
- cc
|
||||
- cpp
|
||||
- cxx
|
||||
HeaderFilterRegex: '.*'
|
||||
ExcludeHeaderFilterRegex: ''
|
||||
FormatStyle: file
|
||||
SystemHeaders: false
|
||||
...
|
||||
|
@ -1,9 +1,9 @@
|
||||
FROM ghcr.io/ngn13/ctorm:1.7
|
||||
FROM ghcr.io/ngn13/ctorm:1.8.1
|
||||
|
||||
WORKDIR /doc
|
||||
|
||||
COPY Makefile ./
|
||||
COPY docs ./docs
|
||||
COPY pages ./pages
|
||||
COPY inc ./inc
|
||||
COPY src ./src
|
||||
|
||||
|
@ -26,10 +26,13 @@ $(DISTDIR)/%.o: src/%.c
|
||||
format:
|
||||
clang-format -i -style=file $(CSRCS) $(HSRCS)
|
||||
|
||||
lint:
|
||||
clang-tidy --warnings-as-errors --config= $(CSRCS) $(HSRCS)
|
||||
|
||||
clean:
|
||||
rm -rf $(DISTDIR)
|
||||
|
||||
run:
|
||||
./doc.elf
|
||||
|
||||
.PHONY: format clean run
|
||||
.PHONY: format lint clean run
|
||||
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"title": "privacy",
|
||||
"desc": "Learn how I respect your privacy"
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"title": "gizlilik",
|
||||
"desc": "Gizliliğinize nasıl önem verdiğimi öğrenin"
|
||||
}
|
@ -3,11 +3,11 @@
|
||||
#include <stdbool.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "file.h"
|
||||
|
||||
typedef struct {
|
||||
DIR *dir;
|
||||
util_file_t *file;
|
||||
file_t *file;
|
||||
char name[NAME_MAX + 1];
|
||||
char *lang;
|
||||
} docs_t;
|
||||
|
10
doc/inc/file.h
Normal file
10
doc/inc/file.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
char *content;
|
||||
int64_t size;
|
||||
} file_t;
|
||||
|
||||
file_t *file_load(int dirfd, char *path);
|
||||
void file_free(file_t *file);
|
@ -4,16 +4,8 @@
|
||||
#include <stdint.h>
|
||||
#include <ctype.h>
|
||||
|
||||
typedef struct {
|
||||
char *content;
|
||||
uint64_t size;
|
||||
} util_file_t;
|
||||
|
||||
#define util_toupper(str) \
|
||||
for (char *c = str; *c != 0; c++) \
|
||||
*c = toupper(*c)
|
||||
uint64_t util_endswith(char *str, char *suf);
|
||||
void util_send(ctorm_res_t *res, uint16_t code, cJSON *json);
|
||||
util_file_t *util_file_load(int dirfd, char *path);
|
||||
void util_file_free(util_file_t *file);
|
||||
bool util_parse_doc_name(char *name, char **lang, const char *ext);
|
||||
|
4
doc/pages/privacy.en.json
Normal file
4
doc/pages/privacy.en.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"title": "privacy",
|
||||
"desc": "Privacy policy"
|
||||
}
|
4
doc/pages/privacy.tr.json
Normal file
4
doc/pages/privacy.tr.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"title": "gizlilik",
|
||||
"desc": "Gizlilik ilkesi"
|
||||
}
|
@ -12,21 +12,24 @@
|
||||
option_t options[] = {
|
||||
// name value requied
|
||||
{"host", "0.0.0.0:7003", true }, // host the server should listen on
|
||||
{"docs_dir", "./docs", true }, // documentation directory
|
||||
{"dir", "./pages", true }, // documentation pages directory
|
||||
{"", NULL, false},
|
||||
};
|
||||
|
||||
bool config_load(config_t *conf) {
|
||||
bzero(conf, sizeof(*conf));
|
||||
memset(conf, 0, sizeof(*conf));
|
||||
|
||||
char name_env[OPT_NAME_MAX + 10], name_copy[OPT_NAME_MAX], *value = NULL;
|
||||
conf->options = options;
|
||||
|
||||
for (option_t *opt = conf->options; opt->value != NULL; opt++, conf->count++) {
|
||||
strcpy(name_copy, opt->name);
|
||||
for (option_t *opt = conf->options; opt->value != NULL;
|
||||
opt++, conf->count++) {
|
||||
// convert option name to environment variable name
|
||||
strncpy(name_copy, opt->name, OPT_NAME_MAX);
|
||||
util_toupper(name_copy);
|
||||
snprintf(name_env, sizeof(name_env), "WEBSITE_%s", name_copy);
|
||||
|
||||
// attempt to load the value from the environment
|
||||
if ((value = getenv(name_env)) != NULL)
|
||||
opt->value = value;
|
||||
|
||||
@ -36,7 +39,9 @@ bool config_load(config_t *conf) {
|
||||
if (!opt->required || NULL != opt->value)
|
||||
continue;
|
||||
|
||||
ctorm_fail("please specify a value for the required config option: %s (%s)", opt->name, name_env);
|
||||
ctorm_fail("please specify a value for the required config option: %s (%s)",
|
||||
opt->name,
|
||||
name_env);
|
||||
errno = EFAULT;
|
||||
return false;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <linux/limits.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
#define DOCS_LANG_CODE_LEN 2
|
||||
|
||||
bool __docs_parse_name(docs_t *docs, char *ext) {
|
||||
bool _docs_parse_name(docs_t *docs, char *ext) {
|
||||
// check the extension
|
||||
uint64_t ext_pos = util_endswith(docs->name, ext);
|
||||
|
||||
@ -22,7 +22,8 @@ bool __docs_parse_name(docs_t *docs, char *ext) {
|
||||
// example.en\0json\0
|
||||
// |
|
||||
// `--- find this
|
||||
for (docs->lang = docs->name; *docs->lang != 0 && *docs->lang != '.'; docs->lang++)
|
||||
for (docs->lang = docs->name; *docs->lang != 0 && *docs->lang != '.';
|
||||
docs->lang++)
|
||||
continue;
|
||||
|
||||
if (*docs->lang != '.')
|
||||
@ -39,11 +40,11 @@ bool __docs_parse_name(docs_t *docs, char *ext) {
|
||||
return strlen(docs->lang) == DOCS_LANG_CODE_LEN && *docs->name != 0;
|
||||
}
|
||||
|
||||
void __docs_clean(docs_t *docs) {
|
||||
void _docs_clean(docs_t *docs) {
|
||||
if (NULL == docs->file)
|
||||
return;
|
||||
|
||||
util_file_free(docs->file);
|
||||
file_free(docs->file);
|
||||
docs->file = NULL;
|
||||
}
|
||||
|
||||
@ -53,7 +54,7 @@ bool docs_init(docs_t *docs, char *dir) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bzero(docs, sizeof(*docs));
|
||||
memset(docs, 0, sizeof(*docs));
|
||||
return NULL != (docs->dir = opendir(dir));
|
||||
}
|
||||
|
||||
@ -64,15 +65,15 @@ char *docs_next(docs_t *docs, char *name, bool content) {
|
||||
}
|
||||
|
||||
struct dirent *ent = NULL;
|
||||
__docs_clean(docs);
|
||||
_docs_clean(docs);
|
||||
|
||||
while (NULL != (ent = readdir(docs->dir))) {
|
||||
if (*ent->d_name == '.')
|
||||
continue;
|
||||
|
||||
strcpy(docs->name, ent->d_name);
|
||||
strncpy(docs->name, ent->d_name, NAME_MAX);
|
||||
|
||||
if (!__docs_parse_name(docs, content ? ".md" : ".json"))
|
||||
if (!_docs_parse_name(docs, content ? ".md" : ".json"))
|
||||
continue;
|
||||
|
||||
if (NULL == name || strncmp(docs->name, name, NAME_MAX) == 0)
|
||||
@ -84,7 +85,7 @@ char *docs_next(docs_t *docs, char *name, bool content) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (NULL == (docs->file = util_file_load(dirfd(docs->dir), ent->d_name)))
|
||||
if (NULL == (docs->file = file_load(dirfd(docs->dir), ent->d_name)))
|
||||
return NULL;
|
||||
|
||||
return docs->file->content;
|
||||
@ -99,8 +100,8 @@ void docs_free(docs_t *docs) {
|
||||
if (NULL == docs)
|
||||
return;
|
||||
|
||||
__docs_clean(docs);
|
||||
_docs_clean(docs);
|
||||
closedir(docs->dir);
|
||||
|
||||
bzero(docs, sizeof(*docs));
|
||||
memset(docs, 0, sizeof(*docs));
|
||||
}
|
||||
|
56
doc/src/file.c
Normal file
56
doc/src/file.c
Normal file
@ -0,0 +1,56 @@
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "file.h"
|
||||
|
||||
file_t *file_load(int dirfd, char *path) {
|
||||
if (NULL == path) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file_t *file = NULL;
|
||||
int fd = -1;
|
||||
|
||||
// open the taarget file
|
||||
if ((fd = openat(dirfd, path, O_RDONLY)) < 0)
|
||||
goto end; // errno set by open
|
||||
|
||||
// allocate a new file structure
|
||||
if (NULL == (file = calloc(1, sizeof(file_t))))
|
||||
goto end; // errno set by malloc
|
||||
|
||||
// calculate the file size
|
||||
if ((file->size = lseek(fd, 0, SEEK_END)) < 0)
|
||||
goto end;
|
||||
|
||||
// memory map the file
|
||||
if (NULL ==
|
||||
(file->content = mmap(0, file->size, PROT_READ, MAP_PRIVATE, fd, 0)))
|
||||
goto end; // errno set by mmap
|
||||
|
||||
end:
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
|
||||
if (NULL != file && NULL == file->content) {
|
||||
free(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
void file_free(file_t *file) {
|
||||
if (NULL == file)
|
||||
return;
|
||||
|
||||
munmap(file->content, file->size);
|
||||
free(file);
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
#include <ctorm/app.h>
|
||||
#include <ctorm/ctorm.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@ -19,25 +20,28 @@ int main() {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// initialize the app config
|
||||
ctorm_config_new(&app_config);
|
||||
app_config.disable_logging = true;
|
||||
|
||||
// create a new app
|
||||
app = ctorm_app_new(&app_config);
|
||||
|
||||
// middlewares
|
||||
MIDDLEWARE_ALL(app, "/*", route_cors);
|
||||
MIDDLEWARE_ALL(app, "/*/*", route_cors);
|
||||
ALL(app, "/*", route_cors);
|
||||
ALL(app, "/*/*", route_cors);
|
||||
|
||||
// routes
|
||||
GET(app, "/list", route_list);
|
||||
GET(app, "/get/:name", route_get);
|
||||
|
||||
ctorm_app_all(app, route_notfound);
|
||||
ctorm_app_default(app, route_notfound);
|
||||
ctorm_app_local(app, "config", &conf);
|
||||
|
||||
ctorm_info("starting the web server on %s", host);
|
||||
|
||||
if (!ctorm_app_run(app, host))
|
||||
ctorm_fail("failed to start the app: %s", ctorm_geterror());
|
||||
ctorm_fail("failed to start the app: %s", ctorm_error());
|
||||
|
||||
ctorm_app_free(app);
|
||||
return EXIT_SUCCESS;
|
||||
|
@ -3,7 +3,8 @@
|
||||
void route_cors(ctorm_req_t *req, ctorm_res_t *res) {
|
||||
RES_SET("Access-Control-Allow-Origin", "*");
|
||||
RES_SET("Access-Control-Allow-Headers",
|
||||
"Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, "
|
||||
"Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, "
|
||||
"Authorization, accept, origin, Cache-Control, "
|
||||
"X-Requested-With");
|
||||
RES_SET("Access-Control-Allow-Methods", "PUT, DELETE, GET");
|
||||
}
|
||||
|
@ -1,31 +1,30 @@
|
||||
#include <cjson/cJSON.h>
|
||||
#include <dirent.h>
|
||||
#include <linux/limits.h>
|
||||
#include <cjson/cJSON.h>
|
||||
#include <ctorm/ctorm.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "routes.h"
|
||||
#include "config.h"
|
||||
#include "util.h"
|
||||
#include "docs.h"
|
||||
|
||||
void route_get(ctorm_req_t *req, ctorm_res_t *res) {
|
||||
config_t *conf = REQ_LOCAL("config");
|
||||
char *doc_name = REQ_PARAM("name");
|
||||
char *docs_dir = config_get(conf, "docs_dir"), *doc_data = NULL;
|
||||
char *name = REQ_PARAM("name");
|
||||
char *dir = config_get(conf, "dir"), *doc_data = NULL;
|
||||
cJSON *json = NULL, *doc_json = NULL;
|
||||
docs_t docs;
|
||||
|
||||
if (NULL == doc_name) {
|
||||
if (NULL == name) {
|
||||
ctorm_fail("documentation name not specified (how did that even happend)");
|
||||
util_send(res, 500, NULL);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!docs_init(&docs, docs_dir)) {
|
||||
ctorm_fail("docs_init failed: %s", ctorm_geterror());
|
||||
if (!docs_init(&docs, dir)) {
|
||||
ctorm_fail("docs_init failed: %s", ctorm_error());
|
||||
util_send(res, 500, NULL);
|
||||
goto end;
|
||||
}
|
||||
@ -36,7 +35,7 @@ void route_get(ctorm_req_t *req, ctorm_res_t *res) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
while (NULL != (doc_data = docs_next(&docs, doc_name, false))) {
|
||||
while (NULL != (doc_data = docs_next(&docs, name, false))) {
|
||||
if (NULL == (doc_json = cJSON_Parse(doc_data))) {
|
||||
ctorm_fail("failed to parse JSON: %s (%s)", docs.name, docs.lang);
|
||||
continue;
|
||||
@ -53,7 +52,7 @@ void route_get(ctorm_req_t *req, ctorm_res_t *res) {
|
||||
|
||||
docs_reset(&docs);
|
||||
|
||||
while (NULL != (doc_data = docs_next(&docs, doc_name, true))) {
|
||||
while (NULL != (doc_data = docs_next(&docs, name, true))) {
|
||||
if (NULL == (doc_json = cJSON_GetObjectItem(json, docs.lang)))
|
||||
continue;
|
||||
|
||||
|
@ -3,21 +3,21 @@
|
||||
#include <ctorm/ctorm.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "routes.h"
|
||||
#include "config.h"
|
||||
#include "util.h"
|
||||
#include "docs.h"
|
||||
|
||||
void route_list(ctorm_req_t *req, ctorm_res_t *res) {
|
||||
config_t *conf = REQ_LOCAL("config");
|
||||
char *docs_dir = config_get(conf, "docs_dir"), *doc_data = NULL;
|
||||
char *dir = config_get(conf, "dir"), *doc_data = NULL;
|
||||
cJSON *array = NULL, *json = NULL, *doc_json = NULL;
|
||||
docs_t docs;
|
||||
|
||||
if (!docs_init(&docs, docs_dir)) {
|
||||
ctorm_fail("docs_init failed: %s", ctorm_geterror());
|
||||
if (!docs_init(&docs, dir)) {
|
||||
ctorm_fail("docs_init failed: %s", ctorm_error());
|
||||
util_send(res, 500, NULL);
|
||||
goto end;
|
||||
}
|
||||
@ -31,7 +31,8 @@ void route_list(ctorm_req_t *req, ctorm_res_t *res) {
|
||||
while (NULL != (doc_data = docs_next(&docs, NULL, false))) {
|
||||
if (NULL == (array = cJSON_GetObjectItem(json, docs.lang)) &&
|
||||
NULL == (array = cJSON_AddArrayToObject(json, docs.lang))) {
|
||||
ctorm_fail("failed to create an array object for the language %s", docs.lang);
|
||||
ctorm_fail(
|
||||
"failed to create an array object for the language %s", docs.lang);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1,17 +1,8 @@
|
||||
#include <linux/limits.h>
|
||||
#include <ctorm/ctorm.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <dirent.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "util.h"
|
||||
@ -57,45 +48,3 @@ void util_send(ctorm_res_t *res, uint16_t code, cJSON *json) {
|
||||
|
||||
RES_JSON(json);
|
||||
}
|
||||
|
||||
util_file_t *util_file_load(int dirfd, char *path) {
|
||||
if (NULL == path) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
util_file_t *file = NULL;
|
||||
struct stat buf;
|
||||
int fd = -1;
|
||||
|
||||
if (NULL == (file = malloc(sizeof(util_file_t))))
|
||||
goto end; // errno set by malloc
|
||||
|
||||
if ((fd = openat(dirfd, path, O_RDONLY)) < 0)
|
||||
goto end; // errno set by open
|
||||
|
||||
if (fstat(fd, &buf) < 0)
|
||||
goto end; // errno set by fstat
|
||||
|
||||
if (NULL == (file->content = mmap(0, (file->size = buf.st_size), PROT_READ, MAP_PRIVATE, fd, 0)))
|
||||
goto end; // errno set by mmap
|
||||
|
||||
end:
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
|
||||
if (NULL == file->content) {
|
||||
free(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
void util_file_free(util_file_t *file) {
|
||||
if (NULL == file)
|
||||
return;
|
||||
|
||||
munmap(file->content, file->size);
|
||||
free(file);
|
||||
}
|
||||
|
Reference in New Issue
Block a user