{"id":21711011,"url":"https://github.com/syndamia/pico-web","last_synced_at":"2025-03-20T18:16:54.148Z","repository":{"id":215751682,"uuid":"738497205","full_name":"Syndamia/pico-web","owner":"Syndamia","description":"Year 3 FMI Project","archived":false,"fork":false,"pushed_at":"2024-08-25T18:30:17.000Z","size":180,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-25T16:41:58.266Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://hub.docker.com/r/syndamia/pico-web-server","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Syndamia.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-01-03T11:11:20.000Z","updated_at":"2024-08-25T18:29:33.000Z","dependencies_parsed_at":null,"dependency_job_id":"d7c520bc-f5b8-4a66-a5fe-47d56a950a2e","html_url":"https://github.com/Syndamia/pico-web","commit_stats":null,"previous_names":["syndamia/pico-web"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Syndamia%2Fpico-web","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Syndamia%2Fpico-web/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Syndamia%2Fpico-web/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Syndamia%2Fpico-web/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Syndamia","download_url":"https://codeload.github.com/Syndamia/pico-web/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244666591,"owners_count":20490287,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-25T23:18:58.957Z","updated_at":"2025-03-20T18:16:54.115Z","avatar_url":"https://github.com/Syndamia.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pico-web\n\nSmall client-server network socket application.\nThe server receives a URL from a client and returns the appropriate page.\n\n## DevSecOps lifecycle\n\n### 1. Plan\n\nWith [GitHub issues](https://github.com/Syndamia/pico-web/issues) and/or [GitHub pull requests](https://github.com/Syndamia/pico-web/pulls) modifications to the project are started and discussed\n\n### 2. Code\n\nOur branching strategy is a \"feature workflow with stable branches\", meaning:\n\n- a feature branch is created (for each issue)\n- after the feature is completed in the branch, it is merged into the `dev` branch\n- after enough time has passed, the `dev` branch is merged into the `main` branch\n\nFeature branches don't require special naming (though obviously can't be called `dev` or `main`).  \nCode can be added to `dev` only via pull requests from feature branches.  \nCode can be added to `main` only via pull requests from `dev`.  \n\nMerge requests must always be approved by a contributor and `dev` merge requests to `main` must always have one of these labels: `release:major`, `release:minor` or `release:patch`.\n\nThese constraints are checked with workflows.\n\n### 3. Continuous Integration: Build, Test, Security\n\nOn each push to feature branches and `dev` we execute the \"cd\" pipeline, during which we do:\n\n- Code testing:\n  - unit tests\n  - [clang](https://clang.llvm.org/)'s `--analyze` static analysis\n- SAST, with multiple different tools:\n  - [flawfinder](https://dwheeler.com/flawfinder/)'s security analysis\n  - [SonarCloud](https://www.sonarsource.com/products/sonarcloud/) source code analysis *(automatic, not from workflow)*\n\u003c!--\n- SCA: https://github.com/multilang-depends/depends\n--\u003e\n- Application build\n- Container security testing (both production and dev containers):\n  - [Trivy](https://trivy.dev/) docker container (binary) analysis\n\n### 4. Continuous Deployment: Release, Deploy\n\nOn each successful merge request to `dev`,\n\n- a development docker image is released to [dockerhub](https://hub.docker.com/r/syndamia/pico-web-dev)\n\nOn each successful merge request to `main`,\n\n- the production docker image is released to [dockerhub](https://hub.docker.com/r/syndamia/pico-web), and it is scanned with [Trivy](https://trivy.dev/)\n- a [GitHub release](https://github.com/Syndamia/pico-web/releases) is created, according to the pull request label, and\n- the kubernetes cluster is deployed with [minkube](https://minikube.sigs.k8s.io/docs/) in the pipeline\n\n### Non-code solutions\n\n- [SonarCloud](https://www.sonarsource.com/products/sonarcloud/), since for C it would require a complete compilation toolchain remake\n- Certain branch protections/requirements, since they can only be configure with GitHub website settings\n\n## Project details\n\nYou get two binaries, `server` and `browser`.\n\nURIs (URLs) are in the form `userinfo@address:portPATH`, where `address` and `port` could be skipped.\nThe userinfo section is analogous to subdomains in normal web applications.\n\nIt's assumed that all pages are written in Markdown so the client adds special \"rendering\" like hyperlinks and bold text (via ANSI escape sequences).\nThe server is configured to send pages only in allowed directories, and can handle multiple directories with custom error pages.\n\n### Browser\n\nThe `browser` program takes no arguments.\nAbove every page you can see it's URI.\nWhen ran it displays a blank page by default.\n\nMarkdown anchors are handled in a very special manner: you don't see the actual address, only the \"name\", and before every name is appended a number.\nThis number is a unique index, referencing the given anchor.\n\nBelow the last page you can write commands for the browser.\nCommands come in four \"flavours\":\n\n- Full URI, which will be the next page to display.\n  You may omit the host or port, the last values will be taken (which by default are 127.0.0.1 and 8080).\n  For example: `hello@/`.\n\n- Relative path, which as the name suggests, is just a file path which will be requested on the previous username, address and host.\n  For example: `/index.md`.\n\n- Number, which is one of the aforementioned prepended numbers to anchors.\n  You would \"follow\" the anchor, effectively navigating to it's stored address.\n\n- Column command, a line which begins with the letter `:` and is then *immediately* followed by the name of the command.\n  There are only four command names: `quit`, `q`, `exit` and `e`, all exiting from the program.\n  For example: `:q`.\n\n### Server\n\nIt takes any number of comma-separated strings.\n\nBy default the server is available on address 127.0.0.1 and port 8080.\nIf the first argument contains only one comma (so two items), then it's parsed as an address-port pair (for example `127.0.0.2,8081`) which overrides the defaults.\n\nIf there are two commas (three items; and that's the required amount for any argument after the first), then it contains an access username, files root and error file.\nAll files under the \"files root\" directory will be available on the userinfo \"username\".\nIf the server cannot find a requested file, then the error file is returned (whose path is relative to the files root).\n\n*Note:* A quirk with Markdown anchors is that relative paths are always relative to the files root, not the current directory.\n\nFor example, if you want to share a folder `~/Documents` on username `mynotes` with an error file `./error.md` (again, this path is relative to `~/Documents`), then the corresponding argument to `server` would be `mynotes,~/Documents,./error.md`.\n\nWhen running you'll see logs, related to all connections with the server.\n\nYou can also type commands, similarly to [browser](#browser), the first character on the line must be `:`, followed immediately by the command name.\nThere are currently 3 distinct commands:\n\n- `help`, `h` and `?`, which print all available commands\n- `vhosts`, which prints out all shared folders, alongside their associated userinfo and error file\n- `quit`, `q`, `exit` and `e`, which exit out of the program\n\n### Demo\n\nThis project comes with a tiny assortment of pages.\nThis is a sample input and output of both programs, showing all of their capabilities (browser does add some special coloring in terminals, which can't be shown in this file), where shell commands are prepended with `$ ` and user input with `\u003e `:\n\n```\n$ ./server '127.0.0.1,8081` `demo,./demo,./demo/page.md`\nListening on 127.0.0.1:8081\n[127.0.0.1@4] Connected successfully!\n[127.0.0.1@4] Requested demo@/\n[127.0.0.1@4] Serving ./demo/index.md\n[127.0.0.1@4] Served!\n[127.0.0.1@4] Connected successfully!\n[127.0.0.1@4] Requested demo@/page.md\n[127.0.0.1@4] Serving ./demo/page.md\n[127.0.0.1@4] Served!\n[127.0.0.1@4] Connected successfully!\n[127.0.0.1@4] Requested demo@/\n[127.0.0.1@4] Serving ./demo/index.md\n[127.0.0.1@4] Served!\n[127.0.0.1@4] Connected successfully!\n[127.0.0.1@4] Requested demo@/dir\n[127.0.0.1@4] Serving ./demo/dir/index.md\n[127.0.0.1@4] Served!\n[127.0.0.1@4] Connected successfully!\n[127.0.0.1@4] Requested demo@/dir/page.md\n[127.0.0.1@4] Serving ./demo/dir/page.md\n[127.0.0.1@4] Served!\n[127.0.0.1@4] Connected successfully!\n[127.0.0.1@4] Requested demo@/page.md\n[127.0.0.1@4] Serving ./demo/page.md\n[127.0.0.1@4] Served!\n[127.0.0.1@4] Connected successfully!\n[127.0.0.1@4] Requested demo@/\n[127.0.0.1@4] Serving ./demo/index.md\n[127.0.0.1@4] Served!\n[127.0.0.1@4] Connected successfully!\n[127.0.0.1@4] Requested demo@/dira\n[127.0.0.1@4] Error opening ./demo/dira\n[127.0.0.1@4] Serving ./demo/page.md\n[127.0.0.1@4] Served!\n\u003e :help\nhelp,h,?    Prints this message\nvhosts      Prints all registered virtual hosts\nquit,exit,q,e   Exits the program\n\u003e :vhosts\nName: \"demo\" Root dir: \"./demo\" Error file: \"page.md\"\n\u003e :quit\nExiting...\n```\n\n```\n$ ./browser\nblank\n\n\u003e demo@127.0.0.1:8081/   \ndemo@127.0.0.1:8081/\n\u003c\u003c Index page \u003e\u003e\n\nGo to: 0page, 1dir\n\u003e 0\ndemo@127.0.0.1:8081/page.md\n\u003c\u003c Page \u003e\u003e\n\nGo to: 0Index\n\u003e 0\ndemo@127.0.0.1:8081/\n\u003c\u003c Index page \u003e\u003e\n\nGo to: 0page, 1dir\n\u003e 1\ndemo@127.0.0.1:8081./dir\n[[ Index of dir ]]\n\nGo to: 0Index, 1Page\n\u003e 1\ndemo@127.0.0.1:8081/dir/page.md\n[[ Page in dir ]]\n\nGo to: 0Index\n\u003e demo@/page.md\ndemo@/page.md\n\u003c\u003c Page \u003e\u003e\n\nGo to: 0Index\n\u003e /\ndemo@/\n\u003c\u003c Index page \u003e\u003e\n\nGo to: 0page, 1dir\n\u003e demo@127.0.0.1:8081/dira\n\u003c\u003c Page \u003e\u003e\n\nGo to: 0Index\n\u003e blank\nblank\n\n\u003e :quit\n```\n\n## Source code information\n\n### File hierarchy\n\n- `browser.c` - Main browser source code, handles communication with server\n- `browser-cli.c` - Handles rendering of pages (printing to stdout) and user interface (user input)\n\n- `server.c` - Main server source code, handles communication with client\n- `server-connection.c` - Parses received information from client and sends information back to client\n- `server-cli.c` - Handles user interface (user input)\n\n- `util.c` - Various functions in use by the browser and server apps\n\n### Networking\n\nThe server creates a socket on which it listens for incoming connections.\nOn client connection, a new child process is started, which will handle parsing of URI and sending of page.\n\nClient also creates a socket with which to connect to the server.\nWhen receiving a page, it prints it on standard output.\n\nRelevant (networking) code for the server is located in `server.c` as well as `on_connection` function in `server-connection.c`.\nFor the browser it's all in `browser.c`.\n\n### Page rendering\n\nThe client prints Markdown pages with special formatting.\nMost elements use [ANSI escape sequences](https://en.wikipedia.org/wiki/ANSI_escape_code) to show text in different colors and format.\n\nSpecial Markdown syntax (anchors, ...) is parsed with regular expressions via the POSIX regex.h.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsyndamia%2Fpico-web","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsyndamia%2Fpico-web","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsyndamia%2Fpico-web/lists"}