Compare commits

..

No commits in common. "master" and "md-articles" have entirely different histories.

65 changed files with 165 additions and 1373 deletions

2
.gitignore vendored
View File

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

24
.vscode/launch.json vendored
View File

@ -1,24 +0,0 @@
{
// 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": ""
},
]
}

View File

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

12
.vscode/tasks.json vendored
View File

@ -1,12 +0,0 @@
{
// 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
View File

@ -1 +0,0 @@
/

View File

@ -1,21 +0,0 @@
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"]

View File

@ -1 +0,0 @@
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_p/process_md.h"
#include "../../include/articles_op/process_md.h"
#define LINE_LENGTH 512
@ -28,6 +28,5 @@ 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

@ -1,34 +0,0 @@
#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

@ -1,22 +0,0 @@
#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,14 +5,11 @@
#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,8 +1 @@
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_p/article.h"
#include "../../include/articles_op/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,17 +43,11 @@ int list_articles(article_info **articles)
if (strlen(rest) > 0)
(*articles)[articles_amount - 1].title = strdup(rest);
else
(*articles)[articles_amount - 1].title = strdup("No title");
(*articles)[articles_amount - 1].title = "No 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);
printf("%ld - \"%s\"\n", (*articles)[articles_amount - 1].time, (*articles)[articles_amount - 1].title);
}
fclose(file);
free(buff);
return articles_amount;
@ -65,11 +59,10 @@ 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 = strdup("500");
article->content = "500";
return -1;
}
@ -80,18 +73,17 @@ long get_article_contents(article_info *article)
char *path = malloc(line_length);
if (path == NULL)
{
article->content = strdup("500");
article->content = "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 = strdup("404");
article->content = "404";
return -1;
}
@ -104,23 +96,9 @@ 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,6 +1,5 @@
#include "../../include/articles_p/html.h"
#include "../../include/articles_p/article.h"
#include "../../include/utils_op/utils.h"
#include "../../include/articles_op/html.h"
#include "../../include/articles_op/article.h"
int gen_html_article(article_info article, char **out)
{
@ -20,12 +19,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)
@ -36,9 +35,7 @@ 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;
}
@ -56,8 +53,6 @@ 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);
@ -71,13 +66,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,60 +1,16 @@
#include "../../include/articles_p/process_md.h"
#include "../../include/articles_op/process_md.h"
int process_md(article_info article, char **out)
{
*out = malloc(1);
(*out)[0] = '\0';
char *rest = strdup(article.content), *free_rest = rest;
char *rest = strdup(article.content);
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 = "";
@ -217,7 +173,9 @@ int process_md(article_info article, char **out)
while (buff[i + 2 + n] != ']')
n++;
if (buff[i + 2 + n + 1] == '(') {
if (buff[i + 2 + n + 1] != '(')
continue;
int k = 0;
while (buff[i + 2 + n + 2 + k] != ')')
k++;
@ -251,7 +209,6 @@ int process_md(article_info article, char **out)
continue;
}
}
if (buff[i] == '[')
{
@ -259,7 +216,9 @@ int process_md(article_info article, char **out)
while (buff[i + 1 + n] != ']')
n++;
if (buff[i + 1 + n + 1] == '(') {
if (buff[i + 1 + n + 1] != '(')
continue;
int k = 0;
while (buff[i + 1 + n + 2 + k] != ')')
k++;
@ -291,9 +250,10 @@ 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);
@ -305,6 +265,8 @@ 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);
@ -333,7 +295,5 @@ int process_md(article_info article, char **out)
}
(*out)[strlen(*out) - 1] = '\0';
free(free_rest);
return strlen(*out);
}

View File

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

View File

@ -1,230 +0,0 @@
#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,10 +2,8 @@
#include "../../include/utils_op/utils.h"
#include "../../include/file_op/file.h"
#include "../../include/file_op/mime.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"
#include "../../include/articles_op/html.h"
#include "../../include/articles_op/article.h"
/**
* @brief Send 404 response
@ -17,23 +15,19 @@ void res_404(int fd, char *path)
{
FILE *fp = fopen("static/404.html", "r");
const ssize_t fsize = 512;
char *buff = malloc(fsize), *msg = malloc(fsize);
char buff[fsize], msg[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");
}
@ -80,10 +74,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 = malloc(header_length);
char *header_string = (char *)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 = malloc(header_length + sizeof(size_t));
struct header_s *header = (struct header_s *)malloc(header_length + sizeof(size_t));
header->size = header_length;
header->str = header_string;
@ -108,7 +102,6 @@ int send_response(int fd, char *req_path)
{
res_500(fd);
free(file_path);
return 0;
}
@ -116,8 +109,6 @@ int send_response(int fd, char *req_path)
{
res_404(fd, req_path);
free(file_path);
free(file);
return 0;
}
@ -141,11 +132,6 @@ int send_response(int fd, char *req_path)
close(fd);
free(header->str);
free(header);
free(file);
free(file_path);
return 0;
}
@ -187,7 +173,6 @@ 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);
@ -218,20 +203,12 @@ 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 = malloc(strlen(path) - strlen("/article/") + 1);
char *id_str = (char *)malloc(strlen(path) - strlen("/article/") + 1);
memmove(id_str, path + strlen("/article/"), strlen(path) - strlen("/article/") + 1);
char *remaining;
@ -239,11 +216,8 @@ 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);
@ -253,7 +227,7 @@ void handle_get_request(int fd, char *request)
return;
}
if (id > amount - 1)
if (id > amount-1)
{
res_404(fd, path);
return;
@ -261,7 +235,7 @@ void handle_get_request(int fd, char *request)
get_article_contents(&(articles[id]));
char *html = NULL;
char *html;
gen_html_article(articles[id], &html);
struct header_s *header = gen_header(200, strlen(html), "text/html");
@ -272,93 +246,12 @@ void handle_get_request(int fd, char *request)
printf("Sent article with id=%d\n", id);
free(header->str);
free(header);
free_article_info_arr(&articles, amount);
free(articles);
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");

View File

@ -1,104 +0,0 @@
#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,10 +1,8 @@
#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>
@ -60,22 +58,6 @@ 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
*/
@ -85,18 +67,12 @@ int main(int argc, char *argv[])
struct sockaddr_storage cli_addr;
char s[INET6_ADDRSTRLEN];
char *port;
if (argc == 2)
port = argv[1];
else
port = getenv("PORT");
if (port == NULL)
if (argc != 2)
{
perror("Port must be specified either as an argument or environment variable \"PORT\"");
err_msg("Usage: <Server Port>\n");
exit(1);
}
char *port = argv[1];
int listenfd = get_listener_socket(port);
if (listenfd < 0)
@ -106,8 +82,6 @@ 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,8 +24,6 @@ char *concat_to_front(char **str1, char *str2)
strcpy(*str1, str2);
strcat(*str1, tmp);
free(tmp);
return *str1;
}
@ -88,56 +86,3 @@ 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,154 +6,17 @@
<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">&#9632</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"><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>
</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

@ -1,35 +0,0 @@
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!

View File

@ -1,6 +1,7 @@
# 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](/articles/My_first_article_on_this_site/P5RIaj.png)
![Data flow](https://c.imge.to/2020/07/03/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: 34 KiB

View File

@ -1,41 +0,0 @@
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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

View File

@ -1,20 +0,0 @@
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.

Before

Width:  |  Height:  |  Size: 599 KiB

View File

@ -1,31 +0,0 @@
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

@ -1,13 +0,0 @@
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.

Before

Width:  |  Height:  |  Size: 590 KiB

View File

@ -1,31 +0,0 @@
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

@ -1,21 +0,0 @@
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,16 +6,15 @@
<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">&#9632</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"><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>
</header>
<main>
<h1 id="header">%s</h1>

View File

@ -1,8 +0,0 @@
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

1
static/articles_list.db Normal file
View File

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

View File

@ -1,31 +0,0 @@
<!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

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 322 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 KiB

View File

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

View File

@ -6,36 +6,17 @@
<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">&#9632</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"><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>
</header>
<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>
<h1>Work in porgress</h1>
</body>
</html>

View File

@ -5,17 +5,16 @@
<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>Shishkov Dmitriy</title>
<link href="https://pub.dm1sh.ru/@dm1sh" rel="me">
<title>Test</title>
<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> -->
<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>
</header>
<main>
<h1>Home</h1>
@ -23,7 +22,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="/contacts">Contacts</a></li>
<li><a href="/philosophy">Philosophy</a></li>
</ul>
<h1>Articles</h1>
%s

BIN
static/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 B

View File

@ -1,37 +0,0 @@
<!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

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

View File

@ -1,11 +0,0 @@
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,31 +2,27 @@
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";
}
:root {
--background: #ffffff;
--accent: #000000;
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";
}
::selection {
background-color: var(--accent);
color: var(--background);
background-color: #000000;
color: #ffffff;
}
html, body {
height: 100%;
}
body {
background-color: var(--background);
border-top: solid 5px var(--accent);
background-color: #ffffff;
border-top: solid 5px #000000;
padding: 45px;
color: var(--accent);
}
a {
font-family: monospace;
color: var(--accent);
color: #000000;
}
header {
@ -38,60 +34,41 @@ header img {
height: 100%;
}
#logo {
text-decoration: none;
font-size: 111px;
line-height: 65px;
margin-left: -5px;
}
/* header #modern {
header #modern {
line-height: 65px;
text-align: center;
vertical-align: top;
margin-left: 30px;
font-size: 18px;
color: var(--accent);
color: #000000;
font-family: monospace;
}
header #modern:hover
{
text-decoration: none;
} */
}
main {
max-width: 800px;
}
main > * {
main>* {
margin-bottom: 30px;
}
main img {
max-width: 100%;
max-height: 100vh;
}
main > ul {
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;
}
@ -99,15 +76,10 @@ main a:hover {
main blockquote {
margin-left: 20px;
padding-left: 10px;
border-left: var(--accent) solid 5px;
border-left: #000000 solid 5px;
}
main details,
main summary {
outline: none;
}
main > #header {
main>#header {
font-size: 45px;
}
@ -119,14 +91,3 @@ main > #header {
margin-left: 25px;
}
}
ul ul > li {
margin-left: 20px;
}
@media (prefers-color-scheme: dark) {
:root {
--background: #000000;
--accent: #ffffff;
}
}