1
0
Fork 0

Compare commits

...

No commits in common. "7f7d10aeee55d0af1b33408880440873dcd9425e" and "18828ca7207fbd11662b40ca5a9759ea6cdf348a" have entirely different histories.

19 changed files with 10324 additions and 257 deletions

View file

@ -1,16 +0,0 @@
#!/bin/bash
format() {
sed -e 's/^fix:/доза:/' \
-e '/^# ------------------------ >8 ------------------------$/,$d' \
-e '/^#/d'
}
translated="$(curl -s \
http://localhost:9000/translate \
-H 'Content-Type: text/html' \
--data-binary @- -o- < <(format < "$1") | \
tail -n +2 | \
perl -pe 's,<SPAN CLASS=UNKNOWN_WORD>(.*?)</SPAN>,\1,g')"
[ -n "$translated" ] && echo "$translated" > "$1"

4
.gitignore vendored
View file

@ -1,4 +1,6 @@
build/
.cache/
/test
build/
cache/
cmake-build*/
compile_commands.json

3
.gitmodules vendored
View file

@ -1,3 +0,0 @@
[submodule "puppy/include/http"]
path = puppy/include/http
url = https://github.com/yhirose/cpp-httplib

View file

@ -1,34 +0,0 @@
# promty
## Собирание
Чтобы строить проект, Вы нуждаетесь:
1. Получить **законную копию** &quot;X-переводчика ПРОМТ Magic Gooddy 6.0.0.205&quot; (да, мы фактически имеем эти DVD),
2. Установите это на вашей машине "Окна"
3. Бегите сервером SSH на той машине
4. Управляемый `puppy/scripts/prepare_environment.sh "WINDOWS_USER@WINDOWS_IP"`. Это будет тянуть все необходимые файлы и ключи регистр
5. Управляемый `docker compose up -d --build`
## Вклад
### Передайте Стиль
Эти использования проекта, для которых "обычное передает формат", передают сообщения.
```
напечатайте [возможности]: передайте описание
дополнительное тело
дополнительная нижняя
```
Мы используем только известный, стандартизированный передают типы как определено спецификацией:
| Напечатать | Описание |
|------------------------|-----------------------------------------------------------------------------------------------------------|
| `подвиг` | Добавляет, что новая особенность к codebase |
| `доза` | Залатать неполадки в codebase |
| `доктора` | Изменения только для докторов |
| `тест` | Сменить испытания |
| `хозяйственная работа` | Изменения, которые непосредственно не затрагивают кодекс, типа ударов версии или обновлений иждивенчества |

View file

@ -14,10 +14,6 @@ http://ядро.орг, http://*.ядро.орг {
# we don't want to flood the upstream from the same IP
mode bypass
ttl 30m
timeout {
backend 10m
}
}
import Caddyfile.yadro proxy:80
@ -27,24 +23,13 @@ http://ядро.орг, http://*.ядро.орг {
reverse_proxy {
dynamic a puppy 80
lb_policy least_conn
transport http {
response_header_timeout 10m
read_timeout 10m
write_timeout 10m
}
}
cache {
allowed_http_verbs POST
ttl 7d
key {
headers X-Translation-Direction
}
timeout {
backend 10m
backend 1m
}
}
}

View file

@ -75,6 +75,6 @@ handle @surely_static {
redir @known_host https://{kernel}{uri} permanent
}
# TODO: cache by path for 30 minutes
# TOOO: cache by path for 30 minutes
reverse_proxy {args[0]}

View file

@ -1,6 +1,8 @@
FROM caddy:builder AS builder
RUN --mount=type=cache,target=/go/pkg/mod xcaddy build \
--with github.com/caddyserver/cache-handler
FROM caddy:latest
COPY --from=builder /usr/bin/caddy /usr/bin/caddy

View file

@ -1,35 +1,33 @@
services:
puppies:
networks: [promty]
networks:
- promty
build: puppy
hostname: puppy
stop_signal: SIGINT
volumes:
- /dev/shm/puppy-temp:/tmpfs
- ./cache:/cache
deploy:
mode: replicated
replicas: 3
replicas: 1
endpoint_mode: vip
update_config:
order: start-first
proxy:
networks: [promty]
networks:
- promty
container_name: proxy
build: proxy
depends_on:
puppies:
condition: service_healthy
caddy:
networks: [promty]
networks:
- promty
container_name: caddy
build: caddy
volumes:
- ./caddy:/etc/caddy
depends_on: [proxy]
ports:
- 80:80
- 9000:9000
networks:
promty:

10
domains
View file

@ -25,7 +25,7 @@
линукс.ядро.орг linux.kernel.org
саял.ядро.орг lkml.kernel.org
уздечка.ядро.орг lore.kernel.org
кольчуга.ядро.орг mail.kernel.org
почта.ядро.орг mail.kernel.org
социальные.сми.ядро.орг media.social.kernel.org
край.зеркал.ядро.орг mirrors.edge.kernel.org
зеркала.ядро.орг mirrors.kernel.org
@ -33,7 +33,7 @@
уздечка.сппн.ядро.орг nntp.lore.kernel.org
нью-йоркские.зеркала.ядро.орг ny.mirrors.kernel.org
источник.нук.ядро.орг nyc.source.kernel.org
прокладка.ядро.орг pad.kernel.org
клавиатура.ядро.орг pad.kernel.org
доктора.париж.ядро.орг parisc.docs.kernel.org
путаница.ядро.орг patchwork.kernel.org
люди.ядро.орг people.kernel.org
@ -43,13 +43,13 @@
источник.греха.ядро.орг sin.source.kernel.org
пппп.ядро.орг smtp.kernel.org
уздечка.пппп.ядро.орг smtp.lore.kernel.org
подпространство.пппп.ядро.орг smtp.subspace.kernel.org
подместо.пппп.ядро.орг smtp.subspace.kernel.org
пппп1.ядро.орг smtp1.kernel.org
пппп2.ядро.орг smtp2.kernel.org
пппп3.ядро.орг smtp3.kernel.org
социальное.ядро.орг social.kernel.org
социальный.ядро.орг social.kernel.org
редкие.доктора.ядро.орг sparse.docs.kernel.org
подпространство.ядро.орг subspace.kernel.org
подместо.ядро.орг subspace.kernel.org
зеркала.резюме.ядро.орг sv.mirrors.kernel.org
сай.отражает.ядро.орг sy.mirrors.kernel.org
мпук.ядро.орг vger.kernel.org

View file

@ -1,15 +1,10 @@
FROM golang:1.23-alpine AS builder
WORKDIR /build
COPY . .
RUN --mount=type=cache,target=/go/pkg/mod go build;
RUN --mount=type=cache,target=/go/pkg/mod go build
FROM alpine AS runner
WORKDIR /app
COPY --from=builder /build/proxy .
EXPOSE 80/tcp
CMD ./proxy

View file

@ -23,7 +23,6 @@ func main() {
// We only support gzip decoding
r.Out.Header.Set("Accept-Encoding", "gzip")
r.Out.Header.Set("User-Agent", "ядро.орг/1.0")
},
ModifyResponse: func(r *http.Response) error {
// Disable security policy because of the domain restrictions.
@ -68,7 +67,7 @@ func main() {
return original_raw
}
return []byte("https://" + yadro + "/")
return []byte("http://" + yadro + "/") // TODO: https
})))
}
@ -88,15 +87,11 @@ func main() {
http.ListenAndServe("0.0.0.0:80", proxy)
}
func replaceDomains(response string) string {
func replaceDomains(response []byte) []byte {
re := regexp.MustCompile(`(?i)[A-Za-z\-\.]*\.?kernel\.org`)
response = strings.NewReplacer(
"%3F", "?",
"%26", "&",
).Replace(response)
response = re.ReplaceAllStringFunc(response, func(original_raw string) string {
kernel := strings.ToLower(original_raw)
response = re.ReplaceAllFunc(response, func(original_raw []byte) []byte {
kernel := strings.ToLower(string(original_raw))
// Strip `www.`
kernel = strings.TrimPrefix(kernel, "www.")
@ -108,46 +103,42 @@ func replaceDomains(response string) string {
return original_raw
}
return yadro
return []byte(yadro)
})
response = bytes.ReplaceAll(response, []byte("%3F"), []byte("?"))
response = bytes.ReplaceAll(response, []byte("%26"), []byte("&"))
response = bytes.ReplaceAll(response, []byte("https"), []byte("http")) // TODO: TEMP
return response
}
func translateWithPromtPuppies(response string) string {
func translateWithPromtPuppies(response []byte) []byte {
// Don't try to translate empty body (30x, etc)
if len(response) == 0 {
return response
}
req, _ := http.NewRequest("POST", "http://caddy:9000/translate", strings.NewReader(response))
req, _ := http.NewRequest("POST", "http://caddy:9000/translate", bytes.NewReader(response))
req.Header.Add("Content-Type", "text/html")
resp, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Fprintln(os.Stderr, "Error in while translating", err)
return ""
fmt.Fprintln(os.Stderr, "Error in first", err)
return []byte{0}
}
var translated strings.Builder
io.Copy(&translated, resp.Body)
response, _ = io.ReadAll(resp.Body)
resp.Body.Close()
return translated.String()
}
func enfunnify(response string) string {
return strings.NewReplacer(
"tarball", "tar ball",
).Replace(response)
return response
}
func modifyResponse(response []byte) []byte {
s := string(response)
s = enfunnify(s)
s = translateWithPromtPuppies(s)
s = replaceDomains(s)
return []byte(s)
response = translateWithPromtPuppies(response)
response = replaceDomains(response)
return response
}

View file

@ -1,47 +1,41 @@
#check=skip=JSONArgsRecommended
FROM debian:13-slim AS builder
FROM debian:12-slim AS builder
RUN apt-get update && DEBIAN_FRONTEND=noninteracive apt-get install -y \
--no-install-recommends cmake g++-mingw-w64-i686-posix g++ make && \
apt-get clean && rm -rf /var/lib/apt/lists/*;
apt-get clean && rm -rf /var/lib/apt/lists/*
WORKDIR /build
COPY app/healthcheck.cpp app/healthcheck.cpp
COPY include/http include/http
RUN g++ -o healthcheck -I./include ./app/healthcheck.cpp;
COPY app app
COPY include include
COPY src src
COPY CMakeLists.txt .
COPY . .
RUN g++ -o healthcheck -I./include ./app/healthcheck.cpp
RUN --mount=type=cache,target=cmake-build cmake -B cmake-build \
-DCMAKE_CXX_COMPILER=i686-w64-mingw32-g++ && cmake --build cmake-build -j$(nproc) && \
cp cmake-build/promt-puppy.exe .;
cp cmake-build/promt-puppy.exe .
FROM debian:13-slim AS runner
FROM debian:12-slim AS runner
ENV WINEPREFIX=/wineprefix \
XDG_RUNTIME_DIR=/tmp/ \
DEBIAN_FRONTEND=noninteracive \
WINEDEBUG=-all
DEBIAN_FRONTEND=noninteracive
RUN dpkg --add-architecture i386 && apt-get update && \
apt-get install -y --no-install-recommends \
wine wine64 wine32:i386 && \
apt-get clean && rm -rf /var/lib/apt/lists/* && \
mkdir -p /tmpfs $WINEPREFIX/drive_c && ln -sf /tmpfs $WINEPREFIX/drive_c/tmpfs;
wineboot -i && echo "Sleeping for 15 seconds..." && sleep 15 && \
mkdir /tmpfs && ln -sf /tmpfs $WINEPREFIX/drive_c/tmpfs
COPY build/ $WINEPREFIX/drive_c
RUN wine regedit $WINEPREFIX/drive_c/registry.reg && \
echo "Sleeping for 15 seconds" && sleep 15
WORKDIR /app
COPY --from=builder /build/promt-puppy.exe /build/healthcheck .
HEALTHCHECK --start-period=30s --start-interval=1s CMD ./healthcheck;
HEALTHCHECK CMD ./healthcheck
EXPOSE 80/tcp
VOLUME /cache
STOPSIGNAL SIGINT
COPY docker-entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
ENV WINEDEBUG=-all
CMD exec wine promt-puppy.exe

View file

@ -1,4 +1,4 @@
#include "http/httplib.h"
#include "httplib.hpp"
int main() {
auto res = httplib::Client("127.0.0.1", 80).Get("/health");

View file

@ -1,62 +1,18 @@
#include "http/httplib.h"
#include "httplib.hpp"
#include <csignal>
#include <cstdint>
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <functional>
#include <iostream>
#include <mutex>
#include <windows.h>
#include <winternl.h>
#include "PromtCtlDocument.hpp"
#include "PromtFTManager.hpp"
#define EPOCH_DIFF 116444736000000000LL
#define TICKS_PER_SEC 10000000LL
static LARGE_INTEGER fake_time;
static NTSTATUS WINAPI HookedNtQuerySystemTime(PLARGE_INTEGER time)
{
if (time)
time->QuadPart = fake_time.QuadPart;
fake_time.QuadPart += TICKS_PER_SEC;
return 0;
}
static void InstallTimeHook()
{
HMODULE ntdll = GetModuleHandleA("ntdll.dll");
if (!ntdll)
return;
auto target = (BYTE *)GetProcAddress(ntdll, "NtQuerySystemTime");
if (!target)
return;
DWORD old;
VirtualProtect(target, 5, PAGE_EXECUTE_READWRITE, &old);
intptr_t rel = (BYTE *)HookedNtQuerySystemTime - target - 5;
target[0] = 0xE9; // jmp rel32
*(int32_t *)(target + 1) = (int32_t)rel;
VirtualProtect(target, 5, old, &old);
const char *env = std::getenv("FAKETIME");
long long unix_ts = env ? std::strtoll(env, nullptr, 10) : 0;
fake_time.QuadPart = unix_ts * TICKS_PER_SEC + EPOCH_DIFF;
}
static inline std::string random_filename(int len = 65) {
static const char ASCII_PRINTABLE[] = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static std::random_device random_device;
static std::mt19937 generator(random_device());
static std::uniform_int_distribution distribution(0, static_cast<int>(strlen(ASCII_PRINTABLE) - 1));
std::random_device random_device;
std::mt19937 generator(random_device());
std::uniform_int_distribution distribution(0, static_cast<int>(strlen(ASCII_PRINTABLE) - 1));
std::string random_string;
random_string.reserve(len);
for (int i = 0; i < len; ++i)
@ -105,20 +61,11 @@ static inline auto read_file(const std::string &filename) {
size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, 0, 0);
std::string out;
out.resize(size - 1);
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, out.data(), size - 1, 0, 0);
out.resize(size);
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, out.data(), size, 0, 0);
delete[] wstr;
std::string out_lf;
out_lf.reserve(out.size());
for (auto c : out) {
if (c == '\r')
continue;
out_lf.push_back(c);
}
return out_lf;
return out;
}
class WebServer {
@ -195,8 +142,7 @@ class WebServer {
public:
WebServer() {
if (!std::filesystem::exists(TMP_FOLDER))
std::filesystem::create_directory(TMP_FOLDER);
if (!std::filesystem::exists(TMP_FOLDER)) std::filesystem::create_directory(TMP_FOLDER);
m_svr.Post("/translate", [this](const httplib::Request &req, httplib::Response &res) {
TranslateHandler(req, res);
@ -213,7 +159,6 @@ class WebServer {
}
void listen(const char *host = "0.0.0.0", unsigned short port = 80) {
print("started!");
m_svr.listen(host, port);
}
@ -224,23 +169,12 @@ class WebServer {
}
};
static std::function<void(int)> signal_action;
void signal_handler(int signal) {
signal_action(signal);
}
int main() {
InstallTimeHook();
print("Starting...");
CoInitializeEx(NULL, COINIT_MULTITHREADED);
CoInitializeSecurity(nullptr, -1, nullptr, nullptr, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IDENTIFY, nullptr, EOAC_NONE, nullptr);
WebServer ws;
signal_action = [&](int x) { ws.stop(); };
std::signal(SIGTERM, signal_handler);
std::signal(SIGINT, signal_handler);
ws.listen();
}

View file

@ -1,12 +0,0 @@
#!/bin/bash
# shellcheck disable=SC2155
echo 'initializing wine...'
wineboot -i
echo 'copying registy values...'
wine regedit "$WINEPREFIX"/drive_c/registry.reg
export FAKETIME="$(cat "$WINEPREFIX"/drive_c/build-date)"
echo "starting with date $(date -d @"$FAKETIME")..."
exec wine /app/promt-puppy.exe

@ -1 +0,0 @@
Subproject commit adf58bf474fac638160592d6c3f67da4ebc7df20

10243
puppy/include/httplib.hpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,25 +1,15 @@
#!/bin/bash -e
# shellcheck disable=SC1091
SCRIPT_DIR="$(dirname "$(dirname "$(readlink -e "$0")")")"
cd "$(basename "$(basename "$(readlink "$0")")")"
SSH_HOST="${1:?Missing SSH host}"
mkdir -p build/{"Program Files (x86)/Common Files",ProgramData}
scp "$SCRIPT_DIR/scripts/dump_registry.ps1" "$SSH_HOST:"
ssh "$SSH_HOST" "powershell .\dump_registry.ps1"
# scp ./scripts/dump_registry.ps1 "$SSH_HOST:"
# ssh "$SSH_HOST" "powershell .\dump_registry.ps1"
scp "$SSH_HOST:promt-registry.reg" build/registry.reg
ssh "$SSH_HOST" powershell -c 'rm promt-registry.reg'
scp -r "$SSH_HOST:/Program Files (x86)/Common Files/PROject MT" "$SCRIPT_DIR/build/Program Files (x86)/Common Files/PROject MT"
scp -r "$SSH_HOST:/Program Files (x86)/PRMT6" "$SCRIPT_DIR/build/Program Files (x86)/PRMT6"
scp -r "$SSH_HOST:/ProgramData/PROject MT" "$SCRIPT_DIR/build/ProgramData/PROject MT"
export WINETRICKS_LIB=1
. winetricks 2>/dev/null
winetricks_init
winetricks_vcrun6_helper
w_try_cabextract "${W_CACHE}"/vcrun6/vcredist.exe -d "$SCRIPT_DIR/build/windows/" -F "mfc42*.dll"
mkdir -p "$SCRIPT_DIR/build/windows/system32"
date +'%s' > "$SCRIPT_DIR/build/build-date"
scp -r "$SSH_HOST:/Program Files (x86)/Common Files/PROject MT" "./build/Program Files (x86)/Common Files/PROject MT"
scp -r "$SSH_HOST:/Program Files (x86)/PRMT6" "./build/Program Files (x86)/PRMT6"
scp -r "$SSH_HOST:/ProgramData/PROject MT" "./build/ProgramData/PROject MT"

View file

@ -1,16 +1,15 @@
#include "COMWrapper.hpp"
#include <cstdio>
#include <stdexcept>
#include <windows.h>
#include <comdef.h>
void COMWrapper::Raise(const HRESULT hr, const char *const ctx) const {
if (hr != 0) {
char msg[1024];
_com_error err(hr);
snprintf(msg, 1024, "[%s] Error: %s (0x%lx) at: %s\n", classname(), err.ErrorMessage(), hr, ctx);
printf("%s\n", msg);
exit(1);
char msg[128];
snprintf(msg, 128, "[%s] Non-zero HRESULT value: 0x%x at: %s\n", classname(), hr, ctx);
printf(msg);
throw std::runtime_error(msg);
}
}