Compare commits

...

56 Commits

Author SHA1 Message Date
dm1sh
df3502ad40 fixed a typo in the article 2025-02-28 23:45:49 +03:00
9eea574547
Added invisible mastodon link to head 2025-02-23 21:17:16 +03:00
19ededd901
Added mastodon to contacts 2025-02-23 21:07:31 +03:00
be1de50862
fixed typo in APK_modification.md 2025-02-23 21:07:08 +03:00
734557395d
Removed newline after code block opening to remove unnecessary whitespace above it in browser 2025-02-03 03:09:20 +03:00
0bcee6162b
Reordered commands in Dockerfile for caching usage 2025-02-03 02:52:04 +03:00
84aa11f7c0
Added new article APK_modification 2025-02-03 02:51:16 +03:00
578106404a
And even more about edits 2023-09-18 06:43:25 +03:00
175c2347b9
Fixed angle brackets encoding in articles 2023-09-18 06:23:25 +03:00
a7d1d58a9c
Added code blocks styling 2023-09-18 06:20:55 +03:00
521bed1d55
Fixed square brackets processing 2023-09-18 06:20:30 +03:00
c978b2a777
Updated about me text 2023-09-18 05:58:58 +03:00
615ae35a0e
Fixed too early image template free 2023-09-18 05:58:46 +03:00
0be879c3cb
Added vscode debugging setup 2023-09-18 05:58:00 +03:00
f6a9b7a405
Added vladivostok gallery album 2023-09-18 05:57:34 +03:00
43ba680da8
Updated projects list 2023-09-17 21:05:16 +03:00
d57a642d69
Added markdown code tag support 2023-09-13 08:43:33 +03:00
cbdfcae15b Update static/articles/list.db 2023-09-13 07:58:04 +03:00
90de7ed349 Add static/articles/Use_phone_camera_for_linux_desktop_(2023)/Use_phone_camera_for_linux_desktop_(2023).md 2023-09-13 07:39:50 +03:00
7e49c722ab Finally, reaping all zombies 2022-10-15 11:45:17 +03:00
4d959ce088 Included signal.h 2022-10-15 09:38:50 +03:00
15147b6430 Added forked processes termination 2022-10-15 09:19:18 +03:00
72eb14f9e0 Fixed includes 2022-07-15 16:19:00 +03:00
53a14d0c78
added article about using phone as linux camera 2022-05-24 03:04:58 +03:00
6594c9dd81
Updated Dockerfile 2022-03-20 17:25:55 +03:00
e7f9ff61f1
Switched from styled div to text logo 2022-03-06 16:01:44 +03:00
16f2cbf329
Added article "Mount_WSL_partition_on_Arch_Linux" 2022-03-06 16:01:13 +03:00
c818a029e4
Fixed memory leaks 2021-09-14 00:38:00 +03:00
4709313543
updated , restricted image height style 2021-09-13 22:50:39 +03:00
8d45a20e15
Added publite to projects 2021-08-01 21:30:26 +03:00
b862bd80f8
Added check file for Dokku deployment 2021-08-01 20:55:36 +03:00
b55e608404
Added article about publite 2021-08-01 20:50:59 +03:00
0cd8660876
Added hackathon project 2021-05-12 20:10:34 +05:00
f16b3fc389
Added article 2021-04-22 01:21:29 +05:00
de36eb5040
Fixed bottom spacing styles 2021-04-22 00:17:38 +05:00
a0d46f1df1
Updated about page 2021-04-22 00:12:45 +05:00
4e7e035db8
Added conways_game project 2021-04-22 00:06:25 +05:00
a8b4834244
Added stack_vm project 2021-04-17 23:58:49 +05:00
0e4895a8e1
Updated projects section 2021-04-12 00:41:05 +05:00
e16b534a8f
Added css variables and dark theme 2021-04-12 00:40:49 +05:00
fd6eefa397
Article: Ugra Hantaton 2021-04-10 13:41:32 +05:00
27e0036e9d
Added photos to gallery and fixed memory leaks 2021-04-10 13:37:31 +05:00
a50a85046f
Updated about me and fixed logo styles 2021-04-10 13:37:01 +05:00
9fa0ff195f
Updated dockerfile 2021-04-10 10:32:55 +05:00
bc6ff5fc55
fixed ports 2021-03-15 19:13:04 +05:00
788e0694d8
Added port environment var set and removed unneded files 2021-03-15 18:45:33 +05:00
cb02a1fdc6 Dockerized application 2020-09-13 13:48:28 +03:00
Dm1tr1y147
5b57419b96 Fixed page titles 2020-07-28 21:59:18 +05:00
Dm1tr1y147
558bc24f1d Added contacts link on "about" page, fixed layout 2020-07-28 17:23:51 +05:00
Dm1tr1y147
4d428a830b Added procfile 2020-07-28 12:20:02 +05:00
Dm1tr1y147
fadbc96146 Added getting port from environment variable 2020-07-28 12:14:28 +05:00
Dm1tr1y147
b62443ecf1 Trying to deploy to Heroku 2020-07-28 11:43:21 +05:00
Dm1tr1y147
b5053453d9 Updated "about me" information. Added contacts page 2020-07-28 07:48:17 +05:00
Dm1tr1y147
440000c438 Added projects tab and local projects list processing. Fxed some memory errors 2020-07-28 07:29:20 +05:00
Dm1tr1y147
21f5a392fa Added gallery site section and automatic directory scanning. Fixed some memory errors, removed obsolete logs 2020-07-28 06:06:00 +05:00
fd6007b22b Upgraded article title functionalify 2020-07-05 20:15:51 +05:00
65 changed files with 1371 additions and 163 deletions

2
.gitignore vendored
View File

@ -1,5 +1,5 @@
tmp/
build/
.vscode/
a.out
test_*
**/exif.?

24
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,24 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "C makefile launch",
"type": "cppdbg",
"request": "launch",
"targetArchitecture": "x64",
"program": "${workspaceRoot}/build/server",
"args": ["5000"],
"stopAtEntry": false,
"cwd": "${workspaceRoot}",
"environment": [],
"externalConsole": true,
"linux": {
"MIMode": "gdb",
},
"miDebuggerArgs": ""
},
]
}

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"files.associations": {
"utils.h": "c"
}
}

12
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,12 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Build makefile project",
"type": "shell",
"command": "make"
}
]
}

1
CHECKS Normal file
View File

@ -0,0 +1 @@
/

21
Dockerfile Normal file
View File

@ -0,0 +1,21 @@
FROM alpine as builder
RUN apk add --no-cache build-base
WORKDIR /app
COPY Makefile .
COPY src src/
COPY include include/
RUN make
FROM alpine
WORKDIR /srv
COPY static static/
COPY --from=builder /app/build/server .
CMD ["./server", "5000"]

1
Procfile Normal file
View File

@ -0,0 +1 @@
web: ./build/server $PORT

View File

@ -9,7 +9,7 @@
#include "../../include/file_op/file.h"
#include "../../include/utils_op/utils.h"
#include "../../include/articles_op/process_md.h"
#include "../../include/articles_p/process_md.h"
#define LINE_LENGTH 512
@ -28,5 +28,6 @@ typedef struct
int list_articles(article_info **articles);
long get_article_contents(article_info *article);
void free_article_info_arr(article_info **articles, int length);
#endif

View File

@ -0,0 +1,34 @@
#ifndef _LIST_GAL_H
#define _LIST_GAL_H
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
typedef struct {
char *description;
char *path;
char **tags;
time_t date_taken;
short int rating;
} img_t;
typedef struct album_s
{
char *title;
img_t *images;
int img_am;
struct album_s *next;
} gallery_t;
gallery_t *get_album_list();
gallery_t *new_album_item(char *title);
void free_albums_list(gallery_t *albums_list);
img_t new_img_item(char *path);
void free_img_item(img_t img);
int get_album_imgs(img_t **images_arr, int *size, char *title);
char *gen_gallery_html();
#define GALLERY_ROOT "static/gallery/albums/"
#endif

View File

@ -0,0 +1,22 @@
#ifndef _PROJECTS_H
#define _PROJECTS_H
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define LINE_LENGTH 512
typedef struct {
char *title;
char *description;
char *lang;
char *license;
char *url;
} project_t;
ssize_t read_list(project_t **list);
char *gen_project_html();
void free_proj_list(project_t **list, int len);
#endif

View File

@ -5,11 +5,14 @@
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <dirent.h>
void err_msg(char *msg);
char *concat_to_front(char **str1, char *str2);
char *get_status_message(int status_code);
char *to_lower(char *str);
char *trim(char *str);
char *repair_spaces(char *str);
ssize_t get_dir_list(char ***dir_list, char *path);
#endif

View File

@ -1 +1,8 @@
Webserver in c. !Experimental!
Deployment:
Docker and Heroku deployment are supported. To do Heroku deployment use https://github.com/heroku/heroku-buildpack-c buildpack. For Docker just build container image and run it exposing port:
docker build -t c-dmitriy.icu .
docker run -dp 5000:5000 c-dmitriy.icu

View File

@ -1,8 +1,8 @@
#include "../../include/articles_op/article.h"
#include "../../include/articles_p/article.h"
int list_articles(article_info **articles)
{
FILE *file = fopen("./static/articles_list.db", "r");
FILE *file = fopen("./static/articles/list.db", "r");
if (file == NULL)
{
perror("Couldn't open db file");
@ -43,11 +43,17 @@ int list_articles(article_info **articles)
if (strlen(rest) > 0)
(*articles)[articles_amount - 1].title = strdup(rest);
else
(*articles)[articles_amount - 1].title = "No title";
(*articles)[articles_amount - 1].title = strdup("No title");
printf("%ld - \"%s\"\n", (*articles)[articles_amount - 1].time, (*articles)[articles_amount - 1].title);
(*articles)[articles_amount - 1].content = malloc(0);
free(tmp);
// printf("Found article \"%s\" posted on %ld\n", (*articles)[articles_amount - 1].time, (*articles)[articles_amount - 1].title);
}
fclose(file);
free(buff);
return articles_amount;
@ -59,10 +65,11 @@ long get_article_contents(article_info *article)
if (strcmp(article->title, "No title") == 0)
{
int line_length = snprintf(NULL, 0, "%ld", article->time) + 1;
free(name);
name = malloc(line_length);
if (name == NULL)
{
article->content = "500";
article->content = strdup("500");
return -1;
}
@ -73,17 +80,18 @@ long get_article_contents(article_info *article)
char *path = malloc(line_length);
if (path == NULL)
{
article->content = "500";
article->content = strdup("500");
return -1;
}
snprintf(path, line_length, "./static/articles/%s/%s.md", name, name);
FILE *file = fopen(path, "r");
free(path);
if (file == NULL)
{
perror("Couldn't open article file");
article->content = "404";
article->content = strdup("404");
return -1;
}
@ -96,9 +104,23 @@ long get_article_contents(article_info *article)
article->content[article->length] = '\0';
free(name);
fclose(file);
return article->length;
}
void free_article_info_arr(article_info **articles, int length)
{
for (int i = 0; i < length; i++)
{
free((*articles)[i].title);
free((*articles)[i].content);
}
free(*articles);
}
// /* Only for testing purposes */
// int main()
// {

View File

@ -1,5 +1,6 @@
#include "../../include/articles_op/html.h"
#include "../../include/articles_op/article.h"
#include "../../include/articles_p/html.h"
#include "../../include/articles_p/article.h"
#include "../../include/utils_op/utils.h"
int gen_html_article(article_info article, char **out)
{
@ -19,12 +20,12 @@ int gen_html_article(article_info article, char **out)
template_str[i] = fgetc(template);
template_str[template_size] = '\0';
*out = malloc(template_size + article.length + 1);
char *content;
process_md(article, &content);
article.title = repair_spaces(article.title);
int line_length = snprintf(NULL, 0, template_str, article.title, article.title, content) + 1;
*out = malloc(line_length);
if (*out == NULL)
@ -35,7 +36,9 @@ int gen_html_article(article_info article, char **out)
snprintf(*out, line_length, template_str, article.title, article.title, content);
fclose(template);
free(template_str);
free(content);
return line_length;
}
@ -53,6 +56,8 @@ int gen_html_article_list(article_info *articles, int n, char **out)
for (int i = 0; i < n; i++)
{
articles[i].title = repair_spaces(articles[i].title);
int line_length = snprintf(NULL, 0, "<li><a href=\"/article/%d\" >%s</a></li>\n", i, articles[i].title) + 1;
insert = malloc(line_length);
@ -66,13 +71,13 @@ int gen_html_article_list(article_info *articles, int n, char **out)
snprintf(insert, line_length, "<li><a href=\"/article/%d\" >%s</a></li>\n", i, articles[i].title);
strcat(*out, insert);
free(insert);
}
*out = realloc(*out, strlen(*out) + strlen("</ul>") + 1);
strcat(*out, "</ul>");
free(insert);
return 0;
}

View File

@ -1,16 +1,60 @@
#include "../../include/articles_op/process_md.h"
#include "../../include/articles_p/process_md.h"
int process_md(article_info article, char **out)
{
*out = malloc(1);
(*out)[0] = '\0';
char *rest = strdup(article.content);
char *rest = strdup(article.content), *free_rest = rest;
char *buff;
int is_in_code = 0;
int is_in_list = 0;
while ((buff = strtok_r(rest, "\n", &rest)) != NULL)
{
if (strncmp(buff, "```", 3) == 0)
{
char *snippet;
if (is_in_code)
{
snippet = "</pre></code>\n";
is_in_code = 0;
}
else
{
snippet = "<pre><code>";
is_in_code = 1;
}
char *tmp_out = realloc(*out, strlen(*out) + strlen(snippet) + 1);
if (tmp_out == NULL)
{
perror("Couldn't allocate memory for new element");
continue;
}
*out = tmp_out;
strcat(*out, snippet);
continue;
}
if (is_in_code)
{
char *tmp_out = realloc(*out, strlen(*out) + strlen(buff) + strlen("<br/>") + 1);
if (tmp_out == NULL)
{
perror("Couldn't allocate memory for new element");
continue;
}
*out = tmp_out;
strcat(*out, buff);
strcat(*out, "<br/>");
continue;
}
if ((buff[0] == '*' && buff[1] == ' ') || (buff[0] == '-' && buff[1] == ' ') || (buff[0] == '+' && buff[1] == ' '))
{
char *begining = "";
@ -173,9 +217,7 @@ int process_md(article_info article, char **out)
while (buff[i + 2 + n] != ']')
n++;
if (buff[i + 2 + n + 1] != '(')
continue;
if (buff[i + 2 + n + 1] == '(') {
int k = 0;
while (buff[i + 2 + n + 2 + k] != ')')
k++;
@ -209,6 +251,7 @@ int process_md(article_info article, char **out)
continue;
}
}
if (buff[i] == '[')
{
@ -216,9 +259,7 @@ int process_md(article_info article, char **out)
while (buff[i + 1 + n] != ']')
n++;
if (buff[i + 1 + n + 1] != '(')
continue;
if (buff[i + 1 + n + 1] == '(') {
int k = 0;
while (buff[i + 1 + n + 2 + k] != ')')
k++;
@ -250,10 +291,9 @@ int process_md(article_info article, char **out)
free(href);
free(internal_text);
printf("++%d-%c++\n", i, buff[i]);
continue;
}
}
size_t len = strlen(*out);
char *tmp_out = realloc(*out, len + 2);
@ -265,8 +305,6 @@ int process_md(article_info article, char **out)
*out = tmp_out;
(*out)[len] = buff[i];
(*out)[len + 1] = '\0';
printf("**%d-%c**\n", i, buff[i]);
}
tmp_out = realloc(*out, strlen(*out) + strlen("</p>") + 1);
@ -295,5 +333,7 @@ int process_md(article_info article, char **out)
}
(*out)[strlen(*out) - 1] = '\0';
free(free_rest);
return strlen(*out);
}

View File

@ -9,13 +9,12 @@
*/
char *gen_file_path(char *req_path)
{
char *path = (char *)malloc(strlen(req_path) + 1);
strcpy(path, req_path);
char *path = strdup(req_path);
if (strchr(req_path, '.') == NULL)
{
if (req_path[strlen(req_path) - 1] != '/')
{
path = realloc(path, strlen(path) + 1);
path = realloc(path, strlen(path) + 2);
path = strcat(path, "/");
}
path = realloc(path, strlen(path) + strlen("index.html") + 1);
@ -24,7 +23,7 @@ char *gen_file_path(char *req_path)
char *webroot = "static";
path = realloc(path, strlen(path) + strlen(webroot));
path = realloc(path, strlen(path) + strlen(webroot) + 1);
path = concat_to_front(&path, webroot);
return path;
@ -46,7 +45,6 @@ int send_file(int cli_fd, struct file_s *file)
}
close(file->fd);
free(file);
return 0;
}
@ -58,7 +56,7 @@ int send_file(int cli_fd, struct file_s *file)
*/
struct file_s *get_file_info(char *file_path)
{
struct file_s *file = (struct file_s *)malloc(sizeof(struct file_s));
struct file_s *file = malloc(sizeof(struct file_s));
if (file == NULL)
{

230
src/gallery_p/gallery.c Normal file
View File

@ -0,0 +1,230 @@
#include "../../include/gallery_p/gallery.h"
#include "../../include/utils_op/utils.h"
#include "../../include/file_op/file.h"
#include "../../include/utils_op/arr.h"
/**
* @brief Get the list of albums on server
*
* @return gallery_t*
*/
gallery_t *get_album_list()
{
gallery_t *list = NULL, *curr = list;
char **albums_titles_list = malloc(0);
ssize_t albums_am = get_dir_list(&albums_titles_list, GALLERY_ROOT);
if (albums_am < 0)
{
err_msg("couldn't read albums list");
return list;
}
if (albums_am == 0)
return list;
list = new_album_item(albums_titles_list[0]);
get_album_imgs(&list->images, &list->img_am, albums_titles_list[0]);
curr = list;
for (unsigned int i = 1; i < albums_am; i++)
{
curr->next = new_album_item(albums_titles_list[i]);
curr = curr->next;
get_album_imgs(&curr->images, &curr->img_am, albums_titles_list[i]);
}
free_arr(albums_titles_list, albums_am);
return list;
}
/**
* @brief Free gallery_t structure
*
* @return void
*/
void free_albums_list(gallery_t *albums_list)
{
gallery_t *curr_item = albums_list;
while (curr_item != NULL)
{
free(curr_item->title);
for (int i = 0; i < curr_item->img_am; i++)
free_img_item(curr_item->images[i]);
free(curr_item->images);
curr_item = curr_item->next;
}
free(albums_list);
}
/**
* @brief Generates new album item
*
* @param title
* @return gallery_t*
*/
gallery_t *new_album_item(char *folder_name)
{
gallery_t *new = calloc(1, sizeof(gallery_t));
char *title = strdup(folder_name);
title[strlen(title) - 1] = '\0';
new->title = strdup(repair_spaces(title));
free(title);
new->img_am = 0;
new->images = NULL;
new->next = NULL;
return new;
}
/**
* @brief Generates new image item
*
* @param path
* @return img_t
*/
img_t new_img_item(char *path)
{
img_t img;
img.date_taken = 0;
img.description = NULL;
img.path = strdup(path);
img.rating = 0;
img.tags = NULL;
return img;
}
/**
* @brief Free img_t structure
*
* @return void
*/
void free_img_item(img_t img)
{
free(img.description);
free(img.path);
free(img.tags);
}
int get_album_imgs(img_t **images_arr, int *size, char *title)
{
char **photos_list = calloc(0, sizeof(char *));
char *album_path = strdup(GALLERY_ROOT);
album_path = realloc(album_path, strlen(album_path) + strlen(title) + 1);
album_path = strcat(album_path, title);
ssize_t photos_am = get_dir_list(&photos_list, album_path);
free(album_path);
*images_arr = calloc(photos_am, sizeof(img_t));
for (int j = 0; j < photos_am; j++)
{
char *img_path = strdup("/gallery/albums/");
img_path = realloc(img_path, strlen(img_path) + strlen(title) + strlen(photos_list[j]) + 1);
img_path = strcat(img_path, title);
img_path = strcat(img_path, photos_list[j]);
(*images_arr)[j] = new_img_item(img_path);
free(img_path);
}
*size = photos_am;
free_arr(photos_list, photos_am);
return photos_am;
}
char *gen_gallery_html()
{
FILE *album_template_fp = fopen("static/gallery/album.html", "r");
FILE *image_template_fp = fopen("static/gallery/image.html", "r");
size_t album_file_size = get_file_size(album_template_fp) + 1;
char *album_template = calloc(1, album_file_size);
size_t image_file_size = get_file_size(image_template_fp) + 1;
char *image_template = calloc(1, image_file_size);
fread(album_template, album_file_size, 1, album_template_fp);
fclose(album_template_fp);
fread(image_template, image_file_size, 1, image_template_fp);
fclose(image_template_fp);
gallery_t *albums_list = get_album_list();
gallery_t *albums_list_item = albums_list;
char *gallery_content = strdup("");
while (albums_list_item != NULL)
{
if (albums_list_item->img_am <= 0)
{
albums_list_item = albums_list_item->next;
continue;
}
char *album_content = strdup("");
for (int i = 0; i < albums_list_item->img_am; i++)
{
char *link = albums_list_item->images[i].path;
size_t line_length = snprintf(NULL, 0, image_template, link, link) + 1;
char *image_content = calloc(1, line_length);
if (image_content == NULL)
return "500 Internal Error\n";
sprintf(image_content, image_template, link, link);
char *tmp = realloc(album_content, strlen(album_content) + strlen(image_content) + 1);
if (tmp == NULL)
return "500 Internal Error\n";
album_content = tmp;
album_content = strcat(album_content, image_content);
free(image_content);
}
size_t line_length = snprintf(NULL, 0, album_template, albums_list_item->title, album_content) + 1;
char *album_html = calloc(1, line_length);
if (album_html == NULL)
return "500 Internal Error\n";
sprintf(album_html, album_template, albums_list_item->title, album_content);
gallery_content = realloc(gallery_content, strlen(gallery_content) + line_length);
gallery_content = strcat(gallery_content, album_html);
free(album_content);
free(album_html);
albums_list_item = albums_list_item->next;
}
free(album_template);
free(image_template);
free_albums_list(albums_list);
return gallery_content;
}

View File

@ -2,8 +2,10 @@
#include "../../include/utils_op/utils.h"
#include "../../include/file_op/file.h"
#include "../../include/file_op/mime.h"
#include "../../include/articles_op/html.h"
#include "../../include/articles_op/article.h"
#include "../../include/articles_p/html.h"
#include "../../include/articles_p/article.h"
#include "../../include/gallery_p/gallery.h"
#include "../../include/projects_p/projects.h"
/**
* @brief Send 404 response
@ -15,19 +17,23 @@ void res_404(int fd, char *path)
{
FILE *fp = fopen("static/404.html", "r");
const ssize_t fsize = 512;
char buff[fsize], msg[fsize];
char *buff = malloc(fsize), *msg = malloc(fsize);
fread(buff, fsize, 1, fp);
fclose(fp);
sprintf(msg, buff, path, path);
free(buff);
struct header_s *header = gen_header(404, strlen(msg), "text/html");
send(fd, header->str, header->size - 1, 0);
free(header->str);
free(header);
send(fd, msg, strlen(msg), 0);
close(fd);
free(msg);
printf("404 ERROR\n");
}
@ -74,10 +80,10 @@ struct header_s *gen_header(int status_code, size_t file_size, char *mime_type)
char *curr_date = asctime(ptm);
int header_length = snprintf(NULL, 0, "HTTP/1.1 %d %s\nDate: %sConnection: close\nContent-Length: %ld\nContent-Type: %s\r\n\r\n", status_code, status_message, curr_date, file_size, mime_type) + 1;
char *header_string = (char *)malloc(header_length);
char *header_string = malloc(header_length);
snprintf(header_string, header_length, "HTTP/1.1 %d %s\nDate: %sConnection: close\nContent-Length: %ld\nContent-Type: %s\r\n\r\n", status_code, status_message, curr_date, file_size, mime_type);
struct header_s *header = (struct header_s *)malloc(header_length + sizeof(size_t));
struct header_s *header = malloc(header_length + sizeof(size_t));
header->size = header_length;
header->str = header_string;
@ -102,6 +108,7 @@ int send_response(int fd, char *req_path)
{
res_500(fd);
free(file_path);
return 0;
}
@ -109,6 +116,8 @@ int send_response(int fd, char *req_path)
{
res_404(fd, req_path);
free(file_path);
free(file);
return 0;
}
@ -132,6 +141,11 @@ int send_response(int fd, char *req_path)
close(fd);
free(header->str);
free(header);
free(file);
free(file_path);
return 0;
}
@ -173,6 +187,7 @@ void handle_get_request(int fd, char *request)
fread(template, file_size, 1, fp);
fclose(fp);
template[file_size-1] = '\0';
article_info *articles = malloc(0);
int amount = list_articles(&articles);
@ -203,12 +218,20 @@ void handle_get_request(int fd, char *request)
printf("Sent home page\n");
free(header->str);
free(header);
free(msg);
free(template);
free_article_info_arr(&articles, amount);
free(articles_list_str);
return;
}
if (strncmp(path, "/article/", strlen("/article/")) == 0)
{
char *id_str = (char *)malloc(strlen(path) - strlen("/article/") + 1);
char *id_str = malloc(strlen(path) - strlen("/article/") + 1);
memmove(id_str, path + strlen("/article/"), strlen(path) - strlen("/article/") + 1);
char *remaining;
@ -216,8 +239,11 @@ void handle_get_request(int fd, char *request)
if (id < 0 || strcmp(id_str, remaining) == 0)
{
res_404(fd, path);
free(id_str);
return;
}
free(id_str);
article_info *articles = malloc(0);
int amount = list_articles(&articles);
@ -235,7 +261,7 @@ void handle_get_request(int fd, char *request)
get_article_contents(&(articles[id]));
char *html;
char *html = NULL;
gen_html_article(articles[id], &html);
struct header_s *header = gen_header(200, strlen(html), "text/html");
@ -246,12 +272,93 @@ void handle_get_request(int fd, char *request)
printf("Sent article with id=%d\n", id);
free(articles);
free(header->str);
free(header);
free_article_info_arr(&articles, amount);
free(html);
return;
}
if (strcmp(path, "/gallery") == 0 || strcmp(path, "/gallery/") == 0 || strcmp(path, "/gallery/index.html") == 0)
{
FILE *page_template_fp = fopen("static/gallery/index.html", "r");
if (page_template_fp == NULL)
{
res_404(fd, path);
return;
}
size_t page_file_size = get_file_size(page_template_fp) + 1;
char *page_template = calloc(1, page_file_size);
fread(page_template, page_file_size, 1, page_template_fp);
fclose(page_template_fp);
char *gallery_content = gen_gallery_html();
size_t line_length = snprintf(NULL, 0, page_template, gallery_content) + 1;
char *res_page = calloc(1, line_length);
sprintf(res_page, page_template, gallery_content);
struct header_s *header = gen_header(200, line_length, "text/html");
send(fd, header->str, header->size - 1, 0);
send(fd, res_page, line_length, 0);
close(fd);
printf("Sent gallery page\n");
free(header->str);
free(header);
free(page_template);
free(gallery_content);
free(res_page);
return;
}
if (strcmp(path, "/projects") == 0 || strcmp(path, "/projects/") == 0)
{
FILE *page_template_fp = fopen("static/projects/index.html", "r");
if (page_template_fp == NULL)
{
res_404(fd, path);
return;
}
size_t page_file_size = get_file_size(page_template_fp) + 1;
char *page_template = calloc(1, page_file_size);
fread(page_template, page_file_size, 1, page_template_fp);
fclose(page_template_fp);
char *projects_content = gen_project_html();
size_t line_length = snprintf(NULL, 0, page_template, projects_content) + 1;
char *res_page = calloc(1, line_length);
sprintf(res_page, page_template, projects_content);
struct header_s *header = gen_header(200, line_length, "text/html");
send(fd, header->str, header->size - 1, 0);
send(fd, res_page, line_length, 0);
close(fd);
printf("Sent projects page\n");
free(header->str);
free(header);
free(page_template);
free(projects_content);
free(res_page);
return;
}
if (send_response(fd, path) < 0)
{
err_msg("couldn't send response");

104
src/projects_p/projects.c Normal file
View File

@ -0,0 +1,104 @@
#include "../../include/projects_p/projects.h"
#include "../../include/utils_op/arr.h"
#include "../../include/file_op/file.h"
ssize_t read_list(project_t **list)
{
FILE *fp = fopen("static/projects/list.db", "r");
if (fp == NULL)
{
perror("couldn't open projectDB file");
return -1;
}
char *buff = NULL;
size_t length = LINE_LENGTH;
size_t projects_amount = 0;
while (getline(&buff, &length, fp) > 0)
{
if (buff[strlen(buff) - 1] == '\n')
buff[strlen(buff) - 1] = '\0';
if (strlen(buff) == 0)
continue;
projects_amount++;
*list = realloc(*list, sizeof(project_t) * projects_amount);
char *tmp = strdup(buff), *rest = tmp;
(*list)[projects_amount - 1].title = strdup(strtok_r(tmp, ";", &rest));
(*list)[projects_amount - 1].description = strdup(strtok_r(rest, ";", &rest));
(*list)[projects_amount - 1].lang = strdup(strtok_r(rest, ";", &rest));
(*list)[projects_amount - 1].license = strdup(strtok_r(rest, ";", &rest));
(*list)[projects_amount - 1].url = strdup(strtok_r(rest, ";", &rest));
free(tmp);
}
fclose(fp);
free(buff);
return projects_amount;
}
char *gen_project_html()
{
FILE *template_fp = fopen("static/projects/item.html", "r");
if (template_fp == NULL)
{
perror("couldn't open project tesplate");
return NULL;
}
size_t template_file_size = get_file_size(template_fp) + 1;
char *template = calloc(1, template_file_size);
fread(template, template_file_size, 1, template_fp);
fclose(template_fp);
project_t *list = malloc(0);
size_t length = read_list(&list);
char *content = strdup("");
for (size_t i = 0; i < length; i++)
{
int line_length = snprintf(NULL, 0, template, list[i].url, list[i].title, list[i].description, list[i].lang, list[i].license) + 1;
char *project_content = calloc(1, line_length);
sprintf(project_content, template, list[i].url, list[i].title, list[i].description, list[i].lang, list[i].license);
content = realloc(content, strlen(content) + line_length);
content = strcat(content, project_content);
free(project_content);
}
free_proj_list(&list, length);
free(template);
return content;
}
void free_proj_list(project_t **list, int len)
{
for (int i = 0; i < len; i++)
{
free((*list)[i].description);
free((*list)[i].lang);
free((*list)[i].license);
free((*list)[i].title);
free((*list)[i].url);
}
free(*list);
}

View File

@ -1,8 +1,10 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
@ -58,6 +60,22 @@ void handle_connection(int fd)
close(fd);
}
/**
* @brief Handles child process removal (to prevent zombies)
*
* @param signum
*/
void handle_process_termination(int signum)
{
int status;
pid_t pid;
do {
pid = waitpid(-1, &status, WNOHANG);
}
while (pid > 0);
}
/**
* Main
*/
@ -67,12 +85,18 @@ int main(int argc, char *argv[])
struct sockaddr_storage cli_addr;
char s[INET6_ADDRSTRLEN];
if (argc != 2)
char *port;
if (argc == 2)
port = argv[1];
else
port = getenv("PORT");
if (port == NULL)
{
err_msg("Usage: <Server Port>\n");
perror("Port must be specified either as an argument or environment variable \"PORT\"");
exit(1);
}
char *port = argv[1];
int listenfd = get_listener_socket(port);
if (listenfd < 0)
@ -82,6 +106,8 @@ int main(int argc, char *argv[])
}
printf("Waiting for connection on port %s...\n", port);
signal(SIGCHLD, handle_process_termination);
while (1)
{
socklen_t sin_size = sizeof cli_addr;

View File

@ -24,6 +24,8 @@ char *concat_to_front(char **str1, char *str2)
strcpy(*str1, str2);
strcat(*str1, tmp);
free(tmp);
return *str1;
}
@ -86,3 +88,56 @@ char *trim(char *str)
return str;
}
char *repair_spaces(char *str)
{
for (int i = 0; i < strlen(str); i++)
{
if (str[i] == '_')
{
str[i] = ' ';
}
}
return str;
}
/**
* @brief Gets the list of files and directories at the specified path
*
* @param dir_list
* @param path
* @return ssize_t
*/
ssize_t get_dir_list(char ***dir_list, char *path)
{
DIR *dir;
struct dirent *ent;
if ((dir = opendir(path)) == NULL)
{
perror("\nOpendir");
return -1;
}
ssize_t n = 0;
while ((ent = readdir(dir)) != NULL)
{
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
continue;
n++;
*dir_list = realloc(*dir_list, sizeof(char *) * n);
(*dir_list)[n - 1] = strdup(ent->d_name);
if (ent->d_type == DT_DIR)
{
(*dir_list)[n - 1] = realloc((*dir_list)[n - 1], strlen((*dir_list)[n - 1]) + 2);
(*dir_list)[n - 1] = strcat((*dir_list)[n - 1], "/");
}
}
closedir(dir);
return n;
}

View File

@ -6,17 +6,154 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
<title>About</title>
<link href="https://pub.dm1sh.ru/@dm1sh" rel="me">
<link rel="stylesheet" href="/style.css">
</head>
<body>
<header>
<a href="/" id="logo"><img src="/logo.png" alt="logo" /></a>
<a id="modern" href="/modern"
title="If you have modern browser, you can visit more fancy version of my site">Modernize</a>
<a href="/" id="logo">&#9632</a>
<!-- <a id="modern" href="/modern"
title="If you have modern browser, you can visit more fancy version of my site">Modernize</a> -->
</header>
<main>
<h1>About me</h1>
<p>
Hello, my name is Dmitriy Shishkov. I am a 17-year-old computer programmer. I
also do photography as a hobby. As for autumn 2021, I study radiotechnics
at "Saint Petersburg Electrotechnical University "LETI".
</p>
<p>
I consider myself a full-stack web developer. All web services and applications
I deploy on my home server, powered by Fedora Server. For it, I use Podman,
Ansible, and Cockpit. I have also used PaaSes such as <a href="https://vercel.com">
Vercel Now</a> or <a href="https://heroku.com">Heroku</a> for previews or small
projects.
</p>
<p>
I also do some C/C++ development for my workspace tools and to better
understand how the software I use works. You can see some examples in the
<a href="/projects">projects</a> section. Even this site is powered by a page
generator written in C.
</p>
<p>Some of the technologies I have worked with:</p>
<ul>
<li>JS
<ul>
<li><a href="https://www.typescriptlang.org">TypeScript</a></li>
<li><a href="https://reactjs.org">React</a>:
<ul>
<li><a href="https://reactrouter.com">React Router</a></li>
<li><a href="https://github.com/molefrog/wouter">Wouter</a></li>
<li><a href="https://www.framer.com/motion">Framer Motion</a></li>
<li><a href="https://styled-components.com">Styled Components</a></li>
</ul>
</li>
<li>Web APIs:
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API">Service Worker</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components">Web Components</a></li>
</ul>
</li>
<li><a href="https://redux.js.org">Redux</a></li>
<li><a href="https://nextjs.org">Next.js</a></li>
<li><a href="https://nodejs.org">NodeJS</a></li>
<li><a href="https://graphql.org">Graphql</a>:
<ul>
<li><a href="https://www.apollographql.com">Apollo</a></li>
</ul>
</li>
<li><a href="https://www.prisma.io">Prisma</a></li>
<li><a href="https://www.mongodb.com">MongoDB</a>
<ul>
<li><a href="https://mongoosejs.com">Mongoose</a></li>
</ul>
</li>
<li><a href="https://www.postgresql.org">PostgreSQL</a>
<ul>
<li><a href="https://node-postgres.com">Node-postgres</a></li>
<li><a href="https://typeorm.io">TypeORM</a></li>
<li><a href="https://www.cockroachlabs.com/product">CockroachDB</a></li>
</ul>
</li>
<li>Styling:
<ul>
<li><a href="https://mui.com/material-ui">Material UI</a></li>
<li><a href="https://getbootstrap.com/">Bootstrap:
<ul>
<li><a href="https://react-bootstrap.github.io/">React Bootstrap</a></li>
</ul>
</a></li>
</ul>
</li>
<li><a href="https://www.npmjs.com/package/jsonwebtoken">jsonwebtoken</a></li>
<li><a href="https://sendgrid.com">SendGrid</a></li>
<li><a href="https://github.com/jakearchibald/idb">idb</a></li>
<li><a href="https://github.com/websockets/ws">ws</a></li>
<li><a href="https://immerjs.github.io/immer">Immer</a></li>
<li><a href="https://expressjs.com">ExpressJS</a></li>
<li>Dev environment:
<ul>
<li><a href="https://vitejs.dev">Vite</a></li>
<li><a href="https://eslint.org">ESLint</a></li>
<li><a href="https://prettier.io">Prettier</a></li>
<li><a href="https://jestjs.io">Jest</a></li>
<li><a href="https://mochajs.org">Mocha</a></li>
<li><a href="https://webpack.js.org">Webpack</a></li>
<li><a href="https://www.snowpack.dev">Snowpack</a></li>
<li><a href="https://storybook.js.org">Storybook</a></li>
<li><a href="https://esbuild.github.io">esbuild</a></li>
<li><a href="https://babeljs.io">Babel</a></li>
</ul>
</li>
</ul>
</li>
<li>Deployment:
<ul>
<li><a href="https://podman.io">Podman</a></li>
<li><a href="https://www.docker.com">Docker</a></li>
<li><a href="https://docs.docker.com/compose">docker-compose</a></li>
<li><a href="https://www.ansible.com">Ansible</a></li>
<li><a href="https://kubernetes.io">Kubernetes</a></li>
<li><a href="https://dokku.com">Dokku</a></li>
<li><a href="https://heroku.com">Heroku</a></li>
<li><a href="https://vercel.com">Vercel Now</a></li>
</ul>
</li>
<li><a href="https://www.python.org">Python</a>
<ul>
<li><a href="https://ipython.org/notebook.html">Jupyter Notebook</a></li>
<li><a href="https://matplotlib.org">Matplotlib</a></li>
<li><a href="https://numpy.org">Numpy</a></li>
<li><a href="https://fastapi.tiangolo.com">FastAPI</a></li>
<li><a href="https://palletsprojects.com/p/jinja">Jinja2</a></li>
<li><a href="https://www.sqlalchemy.org">SQLAlchemy</a></li>
<li><a href="https://pytorch.org">PyTorch</a></li>
</ul>
</li>
<li>C</li>
<li>C++:
<ul>
<li><a href="https://www.wxwidgets.org">wxWidgets</a></li>
<li><a href="https://www.arduino.cc">Arduino</a></li>
<li><a href="https://learn.microsoft.com/en-us/cpp/mfc/mfc-desktop-applications">MFC</a></li>
</ul>
</li>
<li><a href="https://go.dev">Golang</a></li>
<li><a href="https://www.lua.org">Lua</a></li>
<li>C#
<ul>
<li><a href="https://dotnet.microsoft.com">.NET Core</a></li>
</ul>
</li>
<li><a href="https://kotlinlang.org">Kotlin</a></li>
</ul>
<p>See <a href="/contacts">contacts</a> to get in touch with me.</p>
<p>You can reach my resume by following
<a href="https://git.dm1sh.ru/dm1sh/dm1sh/src/branch/main/resume.md">this link</a>.
</p>
</main>
</body>
</html>

View File

@ -0,0 +1,35 @@
First, decompile apk file with [apktool](https://apktool.org):
```
apktool d &lt;file_name&gt;.apk
```
Replace assets or edit *Manifest.xml*. [smali2java](https://github.com/AlexeySoshin/smali2java) can be of use for code modifications.
Recompile apk:
```
apktool b &lt;file_name&gt;
```
Alignment is necessary for modern android versions (I believe, 30+ SDK):
```
zipalign -v -f -p 4 &lt;file_name&gt;/dist/&lt;file_name&gt;.apk aligned-&lt;file_name&gt;.apk
```
Create a signing key. Fields values do not matter. Especially for personal use.
```
keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 1000
```
Actually sign apk with it:
```
apksigner.jar sign -ks my-release-key.keystore --ks-key-alias alias_name aligned-&lt;file_name&gt;.apk
```
It will overwrite the provided apk with a signed one.
We're awesome!

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

View File

@ -0,0 +1,41 @@
If you dualboot Windows and Linux, you may need to transfer files between your bare-metal Linux and WSL.
Firstly, mount your Windows disk C: on Linux. For it, run:
```
sudo pacman -S ntfs-3g
sudo mkdir -p /mnt/c
sudo mount /dev/&lt;Windows partition name> /mnt/c
```
WSL filesystem is stored as .vhdx file, so we will use qemu-nbd to mount it as usual disk drive.
Install and enable nbd kernel module:
```
sudo pacman -S nbd
sudo modprobe nbd
```
Install qemu:
```
sudo pacman -S qemu
```
Connect .vhdx file to nbd device:
```
sudo qemu-hbd -c /dev/nbd0 /mnt/c/&lt;path to .vhdx file>
```
By default, path must look like Users/[user]/AppData/Local/Packages/[distro]/LocalState/[distroPackageName]/ext4.vhdx
Finally, mount ndb device:
```
sudo mkdir /mnt/wsl
sudo mount /dev/ndb0 /mnt/wsl
```
Now you can transfer files or chroot into it.

View File

@ -1,7 +1,6 @@
# My first article on this site
This is my own site written in pure C with templates in html and some css styles. All articles are stored in markdown format and are processed by server to convert them to html and send to client. Links list on the homepage is also generated dynamically to show all the articles, currntly avaliable on disk.
![Data flow](https://c.imge.to/2020/07/03/P5RIaj.png)
![Data flow](/articles/My_first_article_on_this_site/P5RIaj.png)
*Data flow*
As for all the pages of this site are pure html, it can be read from really old computers or text-based browsers. Server Side Rendered (SSR) webpages are also good for search engines.

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

View File

@ -0,0 +1,20 @@
I like reading books. Really like. But I can't bring paper ones everywhere I want and not all books are available in the local library. So I have to use my phone or laptop. Until now I tried lots of various ebook readers, but no one of them satisfied all my requirements. Some were too complicated for just reading text, some, on the other hand, lacked functionality, and some just had an awful design.
After some searches, I understood, that nothing can fit my needs but my own tool. So I created Publite — a web application for book reading. For it I also created a backend for converting EPUB and FB2 files to HTML After adding the book, you can read it offline. The book is split into pages fitting window size.
The first version of the application is already available at [publite.dmitriy.icu](https://publite.dmitriy.icu). It is a React.JS SPA using LocalStorage as book storage. To provide simple routing without dramatic bundle size growth I used [Wouter](https://github.com/molefrog/wouter) instead of React-Router.
But this implementation is not ideal. First of all, it would be difficult and ugly to add server synchronization to the current data flow. Secondly, pagination which I stole from [this article](https://blog.cacoveanu.com/2020/2020.08.14.pagination_in_ebooks.html) is too inefficient for my case.
I already started solving the first problem by switching from React context to fetches caught by ServiceWorker. Books will be stored in IndexedDB. I also added caching of static assets with browser Cache API. It allows me to turn the app into PWA and even publish it to Play Market (if I won't abandon this project).
As for pagination, it is also very important and I have a couple of ideas on how to improve it, but so far, we have to deal with it. Now I'm applying to university and traveling across Belarus. So I don't have much time for this project.
![Book adding screenshot](/articles/Publite_-_an_Ebook_reader/LDwoOj469e.jpg)
*Book adding screenshot*
![Book list screenshot](/articles/Publite_-_an_Ebook_reader/88PVXytCcA.jpg)
*Book list screenshot*
![Book view screenshot](/articles/Publite_-_an_Ebook_reader/qMCsbHZi67.jpg)
*Book view screenshot*

Binary file not shown.

After

Width:  |  Height:  |  Size: 599 KiB

View File

@ -0,0 +1,31 @@
The idea of creating my own virtual machine came to my mind a year ago. Then I didn't have enough skills and desire. But now, when I have my final exams in a month and a half, I started working on this project.
## Overview
It is a stack-based virtual machine that runs simple byte-code. Currently, it supports basic stack operations (push, pop), arithmetic operations, input-output, and strings. Assembly language is a sequence of commands with/(or without) parameters. Assembly language compiler and runner are combined to one binary with *build* and *run* commands resp.
Every command is represented as 4 bytes number. It can have arguments each of which is a 4 bytes number.
Every string is initialized with zero number in the stack. Currently, the only command using this structure is *OUTS*. It puts characters from stack to console until it reaches zero — end of the string.
## File structure
### Header
Total number of commands - 4 bytes
### Body
A sequence of command structures:
### Command
Command code - 4 bytes
(Optional) Arguments - 4 bytes per each
## Plans
It is just a test stand. After exams, I'm planning to dramatically refactor VM code, change bytecode structure by decreasing command size, and adding string declaration in the header. I'm also going to add conditions and jumps for loop support.
Also, there are plans for separating compiler and VM core. If I will read find information about bootloader development, I will also try to create a bootloader for this VM to run it natively.

View File

@ -0,0 +1,13 @@
On November 29 I took part in online hackathon "Югорский Хантатон". During it, our command developed a web application for interactional city tours. It is called KOMAP
I was a member of S.S.H&K.K. command. Besides me, there were 4 more members: Artem Stukalov as a backend developer, Timofey Sedov as a frontend developer, same as me, Dariya Kuznetsova and Victoria Kruk as designers.
This is an application description from the project repository:
> The main idea is to create routes passing through the sights of the cities of the Khanty-Mansi Autonomous Okrug (in particular Khanty-Mansiysk), along which people will be invited to walk. The routes will pass not only through the sights but also through cafes, shopping centers, etc. At the end of the route, people will be able to leave reviews, and after passing 3 basic routes they will be able to create their own, which will subsequently be moderated and added to the site as "new routes". We plan to cooperate with stores and coffee houses to build routes through them, thereby creating an unobtrusive advertisement. At the end of the route, we will provide discount coupons from partner stores, thereby we will be able to interest more people.
During the hackathon, we developed this idea, implemented a backend service for this application and a landing page presenting our product. Currently, this project is still not finished, but not abandoned. We took first place in the junior league and got a lot of new experience.
You can get source code of this project on [github](https://github.com/SSH-KK/hackathon2020_komap)
![Coding mood](/articles/Ugra_Hantaton/qsyj8SF.jpeg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 590 KiB

View File

@ -0,0 +1,31 @@
First, we need to install an application, that'll provide MJPEG video stream. There is IP Webcam, but it is closed source, so it doesn't fit our requirements, through it could be a simplier solution. We will use [ScreenStream](https://github.com/dkrivoruchko/ScreenStream) instead, that is also [available](https://f-droid.org/packages/info.dvkr.screenstream) on F-Droid. With it we can share anything displayed on the phone screen, so, to stream video from camera, we can use any camera solution.
Next, we need to connect phone with our linux PC. For it you can connect them to the same network. But to lower thresold, you can connect them with a wire, enable USB debugging and forward port with adb:
```
adb forward tcp:8000 tcp:8080
```
Prior command will set up PC' port 8000 to phone's 8080. Also note, then if you use ScreenStream, you need to enable local host in its settings.
Next step is to set up a dummy interface for our camera. For it, install and enable v4l2loopback kernel module:
```
sudo pacman -S v4l2loopback-dkms
```
It will create a dummy video interface on `/dev/video0`. We'll assume, it is enough, but if you need more then one device, you can easely google, what params need to be passed while manually enabling the module.
Then, if you don't have ffmpeg, install it:
```
sudo pacman -S ffmpeg
```
And finally:
```
sudo ffmpeg -i http://[localhost или ip адресс телефона]:8000/stream.mjpeg -fflags nobuffer -pix_fmt yuv420p -r 30 -f v4l2 /dev/video0
```
That's all, now you can use your phone camera (or, any other app) just like your PC camera.

View File

@ -0,0 +1,21 @@
I've moved to Fedora Linux and new mjpeg streaming app was released, since the previous article was written. So, because I needed a camera again, I decided to update this manual.
First of all, there is a new app by Thomas SIMON: [RemoteCam](https://github.com/Ruddle/RemoteCam). It directly streams video from camera and permits multiple settings like video resolution and jpeg quality.
To create a dummy camera interface on Fedora, we need to install v4l2loopback packet:
```bash
sudo dnf install v4l2loopback
```
Next, after reboot, we're ready to start the stream with ffmpeg:
```bash
sudo ffmpeg -f mjpeg -r 5 -i "http://&lt;Phone IP>:8080/cam.mjpeg?fps=10" -r 10 -pix_fmt yuv420p -f v4l2 /dev/video0
```
My Wi-Fi connection speed was enough for such stream. But it is still possible to use it with adb port forwarding over usb:
```bash
adb forward tcp:8080 tcp:8080
```

View File

@ -6,15 +6,16 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
<title>%s</title>
<link href="https://pub.dm1sh.ru/@dm1sh" rel="me">
<link rel="stylesheet" href="/style.css">
</head>
<body>
<header>
<a href="/" id="logo"><img src="/logo.png" alt="logo" /></a>
<a id="modern" href="/modern"
title="If you have modern browser, you can visit more fancy version of my site">Modernize</a>
<a href="/" id="logo">&#9632</a>
<!-- <a id="modern" href="/modern"
title="If you have modern browser, you can visit more fancy version of my site">Modernize</a> -->
</header>
<main>
<h1 id="header">%s</h1>

8
static/articles/list.db Normal file
View File

@ -0,0 +1,8 @@
1594048366000 My_first_article_on_this_site
1606819380000 Ugra_Hantaton
1619034957605 Stack_VM_V1.0
1627839955679 Publite_-_an_Ebook_reader
1646570601234 Mount_WSL_partition_on_Arch_Linux
1653350638050 Use_phone_as_camera_for_linux_desktop
1694581049776 Use_phone_camera_for_linux_desktop_(2023)
1738537323514 APK_modification

View File

@ -1 +0,0 @@
1593768639 First article

View File

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
<title>Contacts</title>
<link href="https://pub.dm1sh.ru/@dm1sh" rel="me">
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<a href="/" id="logo">&#9632</a>
<!-- <a id="modern" href="/modern"
title="If you have modern browser, you can visit more fancy version of my site">Modernize</a> -->
</header>
<main>
<h1>Contacts:</h1>
<ul>
<li><a href="https://t.me/dm1sh">Telegram</a></li>
<li><a href="mailto:me@dmitriy.icu">Mail (me@dmitriy.icu)</a></li>
<li><a rel="me" href="https://pub.dm1sh.ru/@dm1sh">Mastodon</a></li>
<li><a href="https://vk.com/dm1sh">VK</a></li>
</ul>
</main>
</body>
</html>

View File

@ -0,0 +1,6 @@
<details>
<summary title="Press to expand">
<h2>%s</h2>
</summary>
<ul>%s</ul>
</details>

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 KiB

View File

@ -0,0 +1,3 @@
<li>
<a href="%s"><img src="%s"></a>
</li>

View File

@ -6,17 +6,36 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
<title>Gallery</title>
<link href="https://pub.dm1sh.ru/@dm1sh" rel="me">
<link rel="stylesheet" href="/style.css">
</head>
<body>
<header>
<a href="/" id="logo"><img src="./logo.png" alt="logo" /></a>
<a id="modern" href="/modern"
title="If you have modern browser, you can visit more fancy version of my site">Modernize</a>
<a href="/" id="logo">&#9632</a>
<!-- <a id="modern" href="/modern"
title="If you have modern browser, you can visit more fancy version of my site">Modernize</a> -->
</header>
<h1>Work in porgress</h1>
<main>
<h1>Gallery</h1>
<p>Heare are some of my photos.</p>
%s
</main>
<style>
summary h2 {
display: inline;
}
details>ul img {
margin-bottom: 30px;
}
details>ul li {
list-style-type: none;
display: inline;
}
</style>
</body>
</html>

View File

@ -5,16 +5,17 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
<title>Test</title>
<title>Shishkov Dmitriy</title>
<link href="https://pub.dm1sh.ru/@dm1sh" rel="me">
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<a href="/" id="logo"><img src="/logo.png" alt="logo" /></a>
<a id="modern" href="/modern"
title="If you have modern browser, you can visit more fancy version of my site">Modernize</a>
<a href="/" id="logo">&#9632;</a>
<!-- <a id="modern" href="/modern"
title="If you have modern browser, you can visit more fancy version of my site">Modernize</a> -->
</header>
<main>
<h1>Home</h1>
@ -22,7 +23,7 @@
<li><a href="/about">About me</a></li>
<li><a href="/gallery">Gallery</a></li>
<li><a href="/projects">Projects</a></li>
<li><a href="/philosophy">Philosophy</a></li>
<li><a href="/contacts">Contacts</a></li>
</ul>
<h1>Articles</h1>
%s

Binary file not shown.

Before

Width:  |  Height:  |  Size: 602 B

View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
<title>Projects</title>
<link href="https://pub.dm1sh.ru/@dm1sh" rel="me">
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<a href="/" id="logo">&#9632</a>
<!-- <a id="modern" href="/modern"
title="If you have modern browser, you can visit more fancy version of my site">Modernize</a> -->
</header>
<main>
<h1 id="header">My projects</h1>
<ul>%s</ul>
</main>
<style>
main>ul li {
margin-bottom: 30px;
}
main>ul li>a {
display: block;
}
</style>
</body>
</html>

View File

@ -0,0 +1,7 @@
<li>
<a href="%s">
%s
</a>
<p>%s - <b><i>%s</i></b></p>
<span><i>%s</i></span>
</li>

11
static/projects/list.db Normal file
View File

@ -0,0 +1,11 @@
Porridger;Eco-oriented bulletin board;TypeScript+React+Python+FastAPI;None;https://git.dm1sh.ru/polka_billy/porridger
The Invisible Centaur;Interface for human and AI integration, which helps to play Go game;JavaScript+React+Redux;GPL-3.0;https://github.com/SSH-KK/goHackathon
Publite;EBook reader supporting Epub and FB2 file formats;TypeScript+React+Python+FastAPI;AGPL-3.0;https://git.dm1sh.ru/publite
QuestionForm;Simplified Google Forms analog;TypeScript+React+Apollo+Prisma;MIT License;https://git.dm1sh.ru/dm1sh/QuestionForm
timetable-generator;Classes scheduling application;TypeScript+React+Bootstrap;None;https://github.com/SSH-KK/timetable-generator
school_documents;School documents (seminars and homeworks) archive;TypeScript+React;None;https://github.com/SSH-KK/school_documents
KGS_LeaderBoard;Leaderboard application for KGS Go server;TypeScript+React+Brython;MIT License;https://github.com/SSH-KK/KGS_LeaderBoard
QRCodeLibrary;Library for QR code generation from text or any sequence of bytes;C++;None;https://git.dm1sh.ru/dm1sh/QRCodeLibrary
c-dmitriy.icu;HTTP/1 web server, supporting static content disposal and HTML-code generation from Markdown;C;None;https://git.dm1sh.ru/dm1sh/c-dmitriy.icu
wxMahjong;Crossplatform game mahjong (solitare);wxWidgets+C++;MIT License;https://git.dm1sh.ru/dm1sh/wxMahjong
mshell;A simple yet comfortable Unix shell;C;MIT License;https://git.dm1sh.ru/dm1sh/mshell

View File

@ -2,27 +2,31 @@
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
"Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji",
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}
:root {
--background: #ffffff;
--accent: #000000;
}
::selection {
background-color: #000000;
color: #ffffff;
}
html, body {
height: 100%;
background-color: var(--accent);
color: var(--background);
}
body {
background-color: #ffffff;
border-top: solid 5px #000000;
background-color: var(--background);
border-top: solid 5px var(--accent);
padding: 45px;
color: var(--accent);
}
a {
font-family: monospace;
color: #000000;
color: var(--accent);
}
header {
@ -34,19 +38,26 @@ header img {
height: 100%;
}
header #modern {
#logo {
text-decoration: none;
font-size: 111px;
line-height: 65px;
margin-left: -5px;
}
/* header #modern {
line-height: 65px;
text-align: center;
vertical-align: top;
margin-left: 30px;
font-size: 18px;
color: #000000;
color: var(--accent);
font-family: monospace;
}
header #modern:hover
{
text-decoration: none;
}
} */
main {
max-width: 800px;
@ -58,17 +69,29 @@ main>* {
main img {
max-width: 100%;
max-height: 100vh;
}
main > ul {
padding-left: 30px;
}
main p, main blockquote, main li {
main p,
main blockquote,
main li {
font-size: 20px;
line-height: 30px;
}
main pre {
font-size: 17px;
overflow-x: auto;
}
main code {
font-family: monospace;
}
main a:hover {
text-decoration: none;
}
@ -76,7 +99,12 @@ main a:hover {
main blockquote {
margin-left: 20px;
padding-left: 10px;
border-left: #000000 solid 5px;
border-left: var(--accent) solid 5px;
}
main details,
main summary {
outline: none;
}
main > #header {
@ -91,3 +119,14 @@ main>#header {
margin-left: 25px;
}
}
ul ul > li {
margin-left: 20px;
}
@media (prefers-color-scheme: dark) {
:root {
--background: #000000;
--accent: #ffffff;
}
}