Compare commits
5 Commits
master
...
feature/we
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1bc182d346 | ||
|
|
9584936a53 | ||
|
|
4de82729f0 | ||
|
|
722d838697 | ||
|
|
49fb0c290f |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,5 +1,6 @@
|
|||||||
/.buildpath
|
/.buildpath
|
||||||
/.project
|
/.project
|
||||||
|
/.settings
|
||||||
/secret.php
|
/secret.php
|
||||||
/config.php
|
/config.php
|
||||||
/test.php
|
/test.php
|
||||||
|
|||||||
@@ -1,92 +0,0 @@
|
|||||||
# Next Steps
|
|
||||||
|
|
||||||
- #TODO Unified error strategy (Definition)
|
|
||||||
- Aufwand: `M`
|
|
||||||
- Labels: `quality`, `api`
|
|
||||||
- Ziel: Einheitliches Verhalten bei Fehlern.
|
|
||||||
- Akzeptanzkriterien:
|
|
||||||
- ADR/kurze Doku: wann `null/false`, wann Exception.
|
|
||||||
- `sql.php`, `link-meta.php`, `troy-api.php` folgen derselben Strategie.
|
|
||||||
- Mindestens 3 Beispiele in `README.md` dokumentiert.
|
|
||||||
- Festlegung:
|
|
||||||
- Exceptions fuer interne/unerwartete Fehler (Konfiguration fehlt, DB/HTTP/JSON-Fehler, Parsing-Fehler, invalide Argumente).
|
|
||||||
- `null` nur fuer "kein Ergebnis" als erwarteter Zustand (z. B. URL ohne OG-Metadaten).
|
|
||||||
- `false` nur fuer boolesche Checks/Operationen mit reinem Erfolg-Flag; keine Detailfehler ueber `false`.
|
|
||||||
- Keine Mischung pro Funktion: jede Funktion dokumentiert exakt einen Fehlerkanal in PHPDoc/README.
|
|
||||||
- Alle gecatchten Exceptions werden mit Kontext weitergeworfen (ohne Secrets), nicht still geschluckt.
|
|
||||||
|
|
||||||
- #TODO Complete `secret.php.example`
|
|
||||||
- Aufwand: `S`
|
|
||||||
- Labels: `docs`, `config`
|
|
||||||
- Ziel: Vollstaendige Vorlagedatei fuer lokale Setups.
|
|
||||||
- Akzeptanzkriterien:
|
|
||||||
- Alle erwarteten Variablen aus `sql.php`, `mail.php`, `troy-api.php` enthalten.
|
|
||||||
- Jede Variable hat kurzen Kommentar.
|
|
||||||
- Dateiformat entspricht direkt nutzbarer Vorlage.
|
|
||||||
|
|
||||||
- #TODO Remove `@` error suppression incrementally
|
|
||||||
- Aufwand: `M`
|
|
||||||
- Labels: `quality`, `safety`
|
|
||||||
- Ziel: Fehler sichtbar und kontrolliert behandeln.
|
|
||||||
- Akzeptanzkriterien:
|
|
||||||
- Alle `@`-Operatoren inventarisiert.
|
|
||||||
- Ersetzungen mit explizitem Error-Handling umgesetzt.
|
|
||||||
- Keine neue `@`-Verwendung in geaenderten Dateien.
|
|
||||||
|
|
||||||
- #TODO Sicherheit und Robustheit
|
|
||||||
|
|
||||||
- #TODO Harden URL fetching against SSRF
|
|
||||||
- Aufwand: `M`
|
|
||||||
- Labels: `security`, `network`
|
|
||||||
- Akzeptanzkriterien:
|
|
||||||
- Private/loopback ranges werden blockiert.
|
|
||||||
- Optionales Host-Allowlist-Feature vorhanden.
|
|
||||||
- Tests fuer geblockte und erlaubte Ziele vorhanden.
|
|
||||||
|
|
||||||
- #TODO Improve SQL error handling + logging
|
|
||||||
- Aufwand: `M`
|
|
||||||
- Labels: `sql`, `robustness`
|
|
||||||
- Akzeptanzkriterien:
|
|
||||||
- `prepare()`/`execute()`-Fehler werden explizit behandelt.
|
|
||||||
- Fehler enthalten Query-Kontext ohne Secrets.
|
|
||||||
- Verhalten entspricht der definierten Error-Strategie.
|
|
||||||
|
|
||||||
- Code-Qualitaet (aufgeteilt in Unter-Issues)
|
|
||||||
- Aufwand: `L`
|
|
||||||
- Labels: `quality`, `refactor`
|
|
||||||
- Unter-Issues:
|
|
||||||
- Define and enforce naming conventions for functions, files and constants.
|
|
||||||
- Refactor SQL binding helpers to one consistent, typed API surface.
|
|
||||||
- Mark legacy functions/modules (`@deprecated`) and document replacement path.
|
|
||||||
- Consolidate Markdown docs (README + API notes) into one canonical structure.
|
|
||||||
- Clarify module boundaries and ownership (I/O, SQL, parsing, formatting).
|
|
||||||
- Akzeptanzkriterien:
|
|
||||||
- Kurzer Styleguide in `README.md` vorhanden und auf bestehende Dateien angewendet.
|
|
||||||
- Keine neuen Legacy-Einstiege ohne Markierung und Migrationshinweis.
|
|
||||||
- SQL-Helper nutzen einheitliche Signaturen in geaenderten Modulen.
|
|
||||||
- Modulgrenzen sind in Doku und Dateistruktur konsistent nachvollziehbar.
|
|
||||||
|
|
||||||
- #TODO Tests und Tooling
|
|
||||||
|
|
||||||
- #TODO Bootstrap test/tooling baseline
|
|
||||||
- Aufwand: `M`
|
|
||||||
- Labels: `testing`, `ci`
|
|
||||||
- Akzeptanzkriterien:
|
|
||||||
- PHPUnit laeuft lokal mit ersten Smoke-Tests.
|
|
||||||
- PHPStan/Psalm auf niedriger Stufe integriert.
|
|
||||||
- CI fuehrt mindestens Lint + Tests bei Push aus.
|
|
||||||
|
|
||||||
- #TODO Prepare Composer + namespace migration path
|
|
||||||
- Aufwand: `L`
|
|
||||||
- Labels: `architecture`
|
|
||||||
- Akzeptanzkriterien:
|
|
||||||
- Vorschlag fuer Zielstruktur (`src/`, namespaces, autoload).
|
|
||||||
- Migrationsplan fuer prozedurale Helfer zu Klassen.
|
|
||||||
- Konfigurationsobjekt und HTTP-Adapter als Zielbild beschrieben.
|
|
||||||
|
|
||||||
## Empfohlene Reihenfolge
|
|
||||||
|
|
||||||
1. `#1` bis `#5` (kurzfristig, hoher Hebel)
|
|
||||||
2. `#6` bis `#10` (Sicherheit/Robustheit)
|
|
||||||
3. `#11` (Tests + CI als Guardrail)
|
|
||||||
4. `#12` und Sammel-Issue aus Abschnitt 3
|
|
||||||
201
README.md
201
README.md
@@ -1,203 +1,2 @@
|
|||||||
# php-func-lib
|
# php-func-lib
|
||||||
|
|
||||||
Kleine PHP-Utility-Bibliothek mit wiederverwendbaren Helfern fuer:
|
|
||||||
|
|
||||||
- Strings und einfache Sanitization
|
|
||||||
- Zahlenformatierung
|
|
||||||
- SQL-Zugriffe (mysqli + prepared statements)
|
|
||||||
- Mailversand
|
|
||||||
- Link/OpenGraph-Metadaten
|
|
||||||
- Debug-Helfer
|
|
||||||
- Troy-/Gitea-API-Aufrufe
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
Als Git-Submodule in ein Projekt einbinden:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git submodule add https://git.seemsleg.it/pub/php-func-lib lib
|
git submodule add https://git.seemsleg.it/pub/php-func-lib lib
|
||||||
```
|
|
||||||
|
|
||||||
Danach je nach Bedarf einzelne Dateien einbinden oder zentral ueber `_func.php` laden.
|
|
||||||
|
|
||||||
## Schnellstart
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
include_once __DIR__ . '/_func.php';
|
|
||||||
|
|
||||||
echo shortener("Ein sehr langer Text", 10); // "Ein sehr..."
|
|
||||||
echo decade(12345); // "12.345 K" (je nach PHP-Konvertierung)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Module
|
|
||||||
|
|
||||||
- `string.php`: String-Helfer (`shortener`, `onlyAlpha`, `startsWith`, `endsWith`, `linkify`, ...)
|
|
||||||
- `numbers.php`: Zahlen-Helfer (`decade`, `onlyNumeric`)
|
|
||||||
- `sql.php`: Klasse `SQL` fuer Datenbankzugriffe (`get`, `single`, `list`, `keyval`, `set`)
|
|
||||||
- `mail.php`: Mailfunktionen (`send_mail`, `send_html_mail`, `send_php_mail`)
|
|
||||||
- `http-limits.php`: Zentrale HTTP-Limits (`httpLimits`)
|
|
||||||
- `link-meta.php`: URL-Validierung, Fetching, Meta-Parsing, Bilddownload, Tag-Sanitization
|
|
||||||
- `og.php`: Einfacher OG-Scan (`scanOG`)
|
|
||||||
- `troy-api.php`: API-Helfer fuer Troy/Gitea (`sendToTroy`, `sendToGitea`)
|
|
||||||
- `debug.php`: Cookie-basierte Debug-Ausgabe
|
|
||||||
- `markdown.php`: einfache Markdown-nahe Formatierung (`md`)
|
|
||||||
|
|
||||||
## Konfiguration
|
|
||||||
|
|
||||||
Einige Module erwarten ein lokales `secret.php` (siehe `secret.php.example`).
|
|
||||||
Folgende Felder werden verwendet:
|
|
||||||
|
|
||||||
- `$_m['host']`, `$_m['user']`, `$_m['pass']`, `$_m['data']`, `$_m['pre']`, `$_m['salt']` fuer `sql.php`
|
|
||||||
- `$_sendermail`, optional `$_smtp['srv']`, `$_smtp['user']`, `$_smtp['pw']` fuer `mail.php`
|
|
||||||
- `$giteaUrl`, `$giteaOwner`, `$giteaRepo`, `$giteaToken` fuer `troy-api.php`
|
|
||||||
|
|
||||||
Beispiel:
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
// secret.php im selben Verzeichnis wie die Bibliothek ablegen
|
|
||||||
if (!defined('SQL_LOG')) define('SQL_LOG', 0);
|
|
||||||
$giteaUrl = 'https://git.example.org';
|
|
||||||
$giteaOwner = 'org';
|
|
||||||
$giteaRepo = 'repo';
|
|
||||||
$giteaToken = 'token';
|
|
||||||
```
|
|
||||||
|
|
||||||
HTTP-Defaults fuer Netzwerkmodule (`link-meta.php`, `og.php`):
|
|
||||||
|
|
||||||
- `LIB_HTTP_TIMEOUT = 8` (Sekunden)
|
|
||||||
- `LIB_HTTP_MAX_REDIRECTS = 4`
|
|
||||||
- `LIB_HTTP_MAX_BYTES = 5242880` (5 MiB)
|
|
||||||
|
|
||||||
Optional vor dem Include ueberschreiben:
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
define('LIB_HTTP_TIMEOUT', 10);
|
|
||||||
define('LIB_HTTP_MAX_REDIRECTS', 5);
|
|
||||||
define('LIB_HTTP_MAX_BYTES', 8 * 1024 * 1024);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Runnable Examples
|
|
||||||
|
|
||||||
### `string.php`
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
include_once __DIR__ . '/string.php';
|
|
||||||
|
|
||||||
echo shortener('Ein sehr langer Text', 12) . PHP_EOL;
|
|
||||||
echo onlyAlpha('Hi! #42?') . PHP_EOL;
|
|
||||||
echo linkify('Mehr Infos: https://example.org') . PHP_EOL;
|
|
||||||
```
|
|
||||||
|
|
||||||
### `numbers.php`
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
include_once __DIR__ . '/numbers.php';
|
|
||||||
|
|
||||||
echo decade(15320) . PHP_EOL;
|
|
||||||
echo onlyNumeric('EUR -12.50') . PHP_EOL;
|
|
||||||
```
|
|
||||||
|
|
||||||
### `sql.php`
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
if (!defined('SQL_LOG')) define('SQL_LOG', 0);
|
|
||||||
include_once __DIR__ . '/sql.php';
|
|
||||||
|
|
||||||
$sql = new SQL();
|
|
||||||
$row = $sql->single('SELECT 1 AS ok');
|
|
||||||
var_export($row);
|
|
||||||
```
|
|
||||||
|
|
||||||
### `mail.php`
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
include_once __DIR__ . '/mail.php';
|
|
||||||
|
|
||||||
send_mail('user@example.org', 'Test', 'Hallo Welt', 'ok', 'error');
|
|
||||||
```
|
|
||||||
|
|
||||||
### `link-meta.php`
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
include_once __DIR__ . '/string.php';
|
|
||||||
include_once __DIR__ . '/link-meta.php';
|
|
||||||
|
|
||||||
$info = getPageInfo('https://example.org');
|
|
||||||
if ($info['ok']) {
|
|
||||||
echo $info['title'] . PHP_EOL;
|
|
||||||
echo $info['description'] . PHP_EOL;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `og.php`
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
include_once __DIR__ . '/og.php';
|
|
||||||
|
|
||||||
$og = scanOG('https://example.org');
|
|
||||||
print_r($og);
|
|
||||||
```
|
|
||||||
|
|
||||||
### `troy-api.php`
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
include_once __DIR__ . '/troy-api.php';
|
|
||||||
|
|
||||||
$res = sendToTroy(['msg' => 'hello']);
|
|
||||||
var_dump($res);
|
|
||||||
```
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
include_once __DIR__ . '/troy-api.php';
|
|
||||||
|
|
||||||
try {
|
|
||||||
$issue = sendToGitea('Test issue', 'Automatisch erstellt.');
|
|
||||||
print_r($issue);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
echo $e->getMessage();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `debug.php`
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
include_once __DIR__ . '/debug.php';
|
|
||||||
|
|
||||||
debugCookie(true);
|
|
||||||
debug(['foo' => 'bar']);
|
|
||||||
```
|
|
||||||
|
|
||||||
### `markdown.php`
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
include_once __DIR__ . '/string.php';
|
|
||||||
include_once __DIR__ . '/markdown.php';
|
|
||||||
|
|
||||||
echo md("! Titel\n\n* Punkt A\n* Punkt B");
|
|
||||||
```
|
|
||||||
|
|
||||||
## Known Limitations
|
|
||||||
|
|
||||||
- Kein Composer/Autoload; Includes muessen manuell gesetzt werden.
|
|
||||||
- `sql.php` erwartet `secret.php` im Bibliotheksverzeichnis und nutzt `mysqli`.
|
|
||||||
- Netzwerkfunktionen (`link-meta.php`, `og.php`, `troy-api.php`) nutzen `file_get_contents` und haben keine SSRF-Allowlist.
|
|
||||||
- Mehrere Funktionen sind historisch gewachsen und nutzen teils inkonsistentes Error-Handling (`false`, `null`, Exceptions).
|
|
||||||
- `markdown.php` und `onlySimpleHTML()` sind einfache Parser/Sanitizer, nicht vollstaendige Markdown- oder HTML-Sicherheitsloesungen.
|
|
||||||
|
|
||||||
## Hinweise
|
|
||||||
|
|
||||||
- Die Bibliothek ist bewusst leichtgewichtig und ohne Composer-Setup gehalten.
|
|
||||||
- Fuer geplante Verbesserungen siehe `NEXT_STEPS.md`.
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
|
||||||
// include ('config.php');
|
// include ('config.php');
|
||||||
include_once ('sql.php');
|
include_once ('sql.php');
|
||||||
$sql = new SQL ();
|
$sql = new SQL ();
|
||||||
@@ -7,6 +6,5 @@ include_once ('string.php');
|
|||||||
include_once ('numbers.php');
|
include_once ('numbers.php');
|
||||||
include_once ('mail.php');
|
include_once ('mail.php');
|
||||||
include_once ('debug.php');
|
include_once ('debug.php');
|
||||||
include_once ('troy-api.php');
|
|
||||||
// include_once ('markdown.php');
|
// include_once ('markdown.php');
|
||||||
?>
|
?>
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
function debug($s) {
|
||||||
|
|
||||||
function debug(mixed $s): void {
|
|
||||||
if(isset($_COOKIE['debug']))
|
if(isset($_COOKIE['debug']))
|
||||||
print_r($s);
|
print_r($s);
|
||||||
}
|
}
|
||||||
|
|
||||||
function debugCookie(bool $on = true): void {
|
function debugCookie($on=true) {
|
||||||
if($on) {
|
if($on) {
|
||||||
setcookie('debug','1',time()+(60*60*24*365),"/");
|
setcookie('debug','1',time()+(60*60*24*365),"/");
|
||||||
}else{
|
}else{
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
<?php
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
if (!defined('LIB_HTTP_TIMEOUT')) {
|
|
||||||
define('LIB_HTTP_TIMEOUT', 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!defined('LIB_HTTP_MAX_REDIRECTS')) {
|
|
||||||
define('LIB_HTTP_MAX_REDIRECTS', 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!defined('LIB_HTTP_MAX_BYTES')) {
|
|
||||||
define('LIB_HTTP_MAX_BYTES', 5 * 1024 * 1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
function httpLimits(): array {
|
|
||||||
return [
|
|
||||||
'timeout' => max(1, (int) LIB_HTTP_TIMEOUT),
|
|
||||||
'max_redirects' => max(0, (int) LIB_HTTP_MAX_REDIRECTS),
|
|
||||||
'max_bytes' => max(1, (int) LIB_HTTP_MAX_BYTES),
|
|
||||||
'user_agent' => 'star-citizen.de-linkbot/1.0'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,45 +1,27 @@
|
|||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
$_ips_crawler = array (
|
$_ips_crawler = array (
|
||||||
'34.79.234.76', // google
|
|
||||||
'40.77.167.', // bing bot
|
'40.77.167.', // bing bot
|
||||||
'54.36.148.', // ahrefbot
|
|
||||||
'54.36.149.', // ahrefbot
|
|
||||||
'66.249.',
|
'66.249.',
|
||||||
'62.138.',
|
'62.138.',
|
||||||
'62.210.149.60',
|
'62.210.149.60',
|
||||||
'65.21.180.26', // seekport
|
|
||||||
'81.209.177.145', // website-datenbank.de
|
|
||||||
'85.25.177.', // abuse
|
|
||||||
'85.25.210.', // hosteurope abuse
|
|
||||||
'92.118.160.37', // netsystem research bot
|
'92.118.160.37', // netsystem research bot
|
||||||
'104.155.85.', // google
|
'104.155.85.', // google
|
||||||
'114.119.1', // petalbot
|
'114.119.1', // petalbot
|
||||||
'144.76.15.153', // mj12bot
|
|
||||||
'148.251.120.201', // mj12bot
|
|
||||||
'157.55.39.', // microsoft???
|
|
||||||
'172.217.', //google
|
|
||||||
'176.125.230.38', //sql inj
|
|
||||||
'185.191.171.', // semrush bot
|
'185.191.171.', // semrush bot
|
||||||
'192.99.5.225', // ...
|
|
||||||
'205.185.115.87', //sex spam
|
|
||||||
'207.46.13.', // bing bot
|
'207.46.13.', // bing bot
|
||||||
'216.58.', //google
|
'54.36.148.', // ahrefbot
|
||||||
|
'54.36.149.', // ahrefbot
|
||||||
'216.244.66.196', // opensiteexplorer
|
'216.244.66.196', // opensiteexplorer
|
||||||
|
'65.21.180.26', // seekport
|
||||||
|
'81.209.177.145', // website-datenbank.de
|
||||||
'2a01:4f8:190:4244::2', // mj12bot
|
'2a01:4f8:190:4244::2', // mj12bot
|
||||||
|
'144.76.15.153', // mj12bot
|
||||||
|
'192.99.5.225', // ...
|
||||||
|
'157.55.39.', // microsoft???
|
||||||
'2a01:4f8:162:43c5::2', // mj12bot
|
'2a01:4f8:162:43c5::2', // mj12bot
|
||||||
|
'85.25.177.', // abuse
|
||||||
|
'85.25.210.', // hosteurope abuse
|
||||||
|
'34.79.234.76', // google
|
||||||
|
'148.251.120.201' // mj12bot
|
||||||
);
|
);
|
||||||
function checkHuman(): bool {
|
|
||||||
global $_ips_crawler;
|
|
||||||
if (stripos ( $_SERVER ['HTTP_USER_AGENT'], 'bot' ) !== false || stripos ( $_SERVER ['HTTP_USER_AGENT'], 'crawler' ) !== false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
foreach ( $_ips_crawler as $np ) {
|
|
||||||
if (startsWith ( $_SERVER ['REMOTE_ADDR'], $np )) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
?>
|
?>
|
||||||
187
link-meta.php
187
link-meta.php
@@ -1,187 +0,0 @@
|
|||||||
<?php
|
|
||||||
declare(strict_types=1);
|
|
||||||
require_once __DIR__ . '/http-limits.php';
|
|
||||||
|
|
||||||
function httpContext(?int $timeout = null) {
|
|
||||||
$limits = httpLimits();
|
|
||||||
$resolvedTimeout = $timeout === null ? $limits['timeout'] : max(1, $timeout);
|
|
||||||
return stream_context_create([
|
|
||||||
'http' => [
|
|
||||||
'timeout' => $resolvedTimeout,
|
|
||||||
'follow_location' => 1,
|
|
||||||
'max_redirects' => $limits['max_redirects'],
|
|
||||||
'user_agent' => $limits['user_agent'],
|
|
||||||
'ignore_errors' => true
|
|
||||||
],
|
|
||||||
'ssl' => [
|
|
||||||
'verify_peer' => true,
|
|
||||||
'verify_peer_name' => true
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeUrl(string $url): ?string {
|
|
||||||
$url = trim($url);
|
|
||||||
if (!filter_var($url, FILTER_VALIDATE_URL)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$parts = parse_url($url);
|
|
||||||
if (!$parts || !isset($parts['scheme'])) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$scheme = strtolower($parts['scheme']);
|
|
||||||
if ($scheme !== 'http' && $scheme !== 'https') {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $url;
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveUrl(string $url, string $baseUrl): ?string {
|
|
||||||
$url = trim($url);
|
|
||||||
if (filter_var($url, FILTER_VALIDATE_URL)) {
|
|
||||||
return $url;
|
|
||||||
}
|
|
||||||
|
|
||||||
$baseParts = parse_url($baseUrl);
|
|
||||||
if (!$baseParts || !isset($baseParts['scheme']) || !isset($baseParts['host'])) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strpos($url, '//') === 0) {
|
|
||||||
return $baseParts['scheme'] . ':' . $url;
|
|
||||||
}
|
|
||||||
|
|
||||||
$path = '/';
|
|
||||||
if (!empty($baseParts['path'])) {
|
|
||||||
$path = preg_replace('#/[^/]*$#', '/', $baseParts['path']);
|
|
||||||
if ($path === null || $path === '') {
|
|
||||||
$path = '/';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strlen($url) && $url[0] === '/') {
|
|
||||||
return $baseParts['scheme'] . '://' . $baseParts['host'] . $url;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $baseParts['scheme'] . '://' . $baseParts['host'] . $path . $url;
|
|
||||||
}
|
|
||||||
|
|
||||||
function safeFetch(string $url, ?int $timeout = null): ?string {
|
|
||||||
$limits = httpLimits();
|
|
||||||
$ctx = httpContext($timeout);
|
|
||||||
$content = @file_get_contents($url, false, $ctx);
|
|
||||||
if ($content === false || strlen($content) > $limits['max_bytes']) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return $content;
|
|
||||||
}
|
|
||||||
|
|
||||||
function downloadImageFromUrl(string $url, string $baseUrl, string $destinationFolder = 'upl/'): ?string {
|
|
||||||
$resolved = resolveUrl($url, $baseUrl);
|
|
||||||
if ($resolved === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!preg_match('/\.(jpg|jpeg|png|gif|bmp|webp)(?:\?|#|$)/i', $resolved)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$imageContent = safeFetch($resolved);
|
|
||||||
if ($imageContent === null || strlen($imageContent) === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$path = parse_url($resolved, PHP_URL_PATH) ?? '';
|
|
||||||
$ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
|
|
||||||
if ($ext === '' || !preg_match('/^(jpg|jpeg|png|gif|bmp|webp)$/', $ext)) {
|
|
||||||
$ext = 'png';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_dir($destinationFolder)) {
|
|
||||||
@mkdir($destinationFolder, 0775, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
$md5Hash = md5($imageContent);
|
|
||||||
$filePath = rtrim($destinationFolder, '/\\') . '/' . $md5Hash . '.' . $ext;
|
|
||||||
$written = @file_put_contents($filePath, $imageContent);
|
|
||||||
if ($written === false) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $filePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseMetaContent(string $html, string $attr, string $name): ?string {
|
|
||||||
$pattern = '/<meta[^>]*' . $attr . '=["\']' . preg_quote($name, '/') . '["\'][^>]*content=["\']([^"\']+)["\'][^>]*>/i';
|
|
||||||
if (preg_match($pattern, $html, $matches) && isset($matches[1])) {
|
|
||||||
return trim(html_entity_decode($matches[1], ENT_QUOTES | ENT_HTML5, 'UTF-8'));
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPageInfo(string $url): array {
|
|
||||||
$ret = [
|
|
||||||
'ok' => false,
|
|
||||||
'title' => '',
|
|
||||||
'description' => '',
|
|
||||||
'logo' => null,
|
|
||||||
'error' => null
|
|
||||||
];
|
|
||||||
|
|
||||||
$normalized = normalizeUrl($url);
|
|
||||||
if ($normalized === null) {
|
|
||||||
$ret['error'] = 'ungueltige_url';
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
$html = safeFetch($normalized);
|
|
||||||
if ($html === null) {
|
|
||||||
$ret['error'] = 'seite_nicht_erreichbar';
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
$title = parseMetaContent($html, 'property', 'og:title') ?? parseMetaContent($html, 'name', 'title');
|
|
||||||
$description = parseMetaContent($html, 'property', 'og:description') ?? parseMetaContent($html, 'name', 'description');
|
|
||||||
$image = parseMetaContent($html, 'property', 'og:image') ?? parseMetaContent($html, 'name', 'image');
|
|
||||||
|
|
||||||
if ($title === null && preg_match('/<title>\s*(.*?)\s*<\/title>/is', $html, $matchTitle)) {
|
|
||||||
$title = trim(html_entity_decode($matchTitle[1], ENT_QUOTES | ENT_HTML5, 'UTF-8'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$logo = null;
|
|
||||||
if ($image !== null && $image !== '') {
|
|
||||||
$img = downloadImageFromUrl($image, $normalized);
|
|
||||||
if ($img !== null) {
|
|
||||||
$logo = '/' . ltrim($img, '/');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$ret['ok'] = true;
|
|
||||||
$ret['title'] = $title ?? '';
|
|
||||||
$ret['description'] = $description ?? '';
|
|
||||||
$ret['logo'] = $logo;
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
function sanitizeTags(array $input): array {
|
|
||||||
$ret = [];
|
|
||||||
foreach ($input as $tag) {
|
|
||||||
if (!is_string($tag)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$clean = onlyAlpha(trim($tag), '_\-');
|
|
||||||
if ($clean === '') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$clean = ucfirst(substr($clean, 0, 35));
|
|
||||||
$ret[$clean] = true;
|
|
||||||
if (count($ret) >= 20) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return array_keys($ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
90
mail.php
90
mail.php
@@ -1,32 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
function send_mail($an, $betreff, $text, $ok = '', $error = '') {
|
||||||
|
|
||||||
function mail_contains_header_injection(string $value): bool {
|
|
||||||
return strpbrk($value, "\r\n\0") !== false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function mail_is_valid_email(string $value): bool {
|
|
||||||
if (mail_contains_header_injection($value)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return filter_var($value, FILTER_VALIDATE_EMAIL) !== false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function send_mail(string $an, string $betreff, string $text, string $ok = '', string $error = ''): void {
|
|
||||||
global $absender;
|
|
||||||
$sender = 'noreply@troy-grunt.de';
|
|
||||||
if(isset($absender) && $absender) {
|
|
||||||
$sender = $absender;
|
|
||||||
}else{
|
|
||||||
include 'secret.php';
|
include 'secret.php';
|
||||||
|
$sender = 'noreply@troy-grunt.de';
|
||||||
if (isset ( $_sendermail )) {
|
if (isset ( $_sendermail )) {
|
||||||
$sender = $_sendermail;
|
$sender = $_sendermail;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (!mail_is_valid_email($an) || !mail_is_valid_email($sender) || mail_contains_header_injection($betreff)) {
|
|
||||||
echo $error;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$header = 'From: ' . $sender . "\r\n";
|
$header = 'From: ' . $sender . "\r\n";
|
||||||
$header .= 'To: ' . $an . "\r\n";
|
$header .= 'To: ' . $an . "\r\n";
|
||||||
$header .= 'Content-Type:text/html' . "\r\n";
|
$header .= 'Content-Type:text/html' . "\r\n";
|
||||||
@@ -40,67 +18,3 @@ function send_mail(string $an, string $betreff, string $text, string $ok = '', s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function send_html_mail(string $an, string $betreff, string $text, string $ok = '', string $error = ''): void {
|
|
||||||
global $absender;
|
|
||||||
$sender = 'noreply@troy-grunt.de';
|
|
||||||
if(isset($absender) && $absender) {
|
|
||||||
$sender = $absender;
|
|
||||||
}else{
|
|
||||||
include 'secret.php';
|
|
||||||
if (isset ( $_sendermail )) {
|
|
||||||
$sender = $_sendermail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!mail_is_valid_email($an) || !mail_is_valid_email($sender) || mail_contains_header_injection($betreff)) {
|
|
||||||
echo $error;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$boundary = md5($an.$betreff.$text.time());
|
|
||||||
|
|
||||||
$header = 'From: ' . $sender . "\n";
|
|
||||||
$header .= 'To: ' . $an . "\n";
|
|
||||||
$header .= 'Content-Type:multipart/alternative;boundary='.$boundary . "\n";
|
|
||||||
$header .= 'X-Mailer: PHP/' . phpversion ();
|
|
||||||
$content = "This is multipart message using MIME\n";
|
|
||||||
$content .= "--" . $boundary . "\n";
|
|
||||||
$content .= "Content-type: text/plain;charset=utf-8\n";
|
|
||||||
$content .= 'Content-Transfer-Encoding: 8bit' . "\n\n";
|
|
||||||
$content .= strip_tags($text)."\n\n";
|
|
||||||
$content .= "--" . $boundary . "\n";
|
|
||||||
$content .= "Content-type: text/html;charset=utf-8\n";
|
|
||||||
$content .= "Content-Transfer-Encoding: 8bit". "\n\n";
|
|
||||||
$content .= '<html><body>'.$text.'</body></html>'."\n\n";
|
|
||||||
|
|
||||||
if (mail ( $an, $betreff, $content, $header ) === true) {
|
|
||||||
echo $ok;
|
|
||||||
} else {
|
|
||||||
echo $error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function send_php_mail(string $an, string $betreff, string $text, string $ok = '', string $error = ''): void {
|
|
||||||
global $_sendermail;
|
|
||||||
$sender = 'noreply@troy-grunt.de';
|
|
||||||
if (isset ( $_sendermail )) {
|
|
||||||
$sender = $_sendermail;
|
|
||||||
}
|
|
||||||
if (!mail_is_valid_email($an) || !mail_is_valid_email($sender) || mail_contains_header_injection($betreff)) {
|
|
||||||
echo $error;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
include 'php-mailer/PHPMailer.php';
|
|
||||||
$mail = new PHPMailer();
|
|
||||||
|
|
||||||
$mail->setFrom($sender);
|
|
||||||
$mail->addAddress($an);
|
|
||||||
$mail->Subject = $betreff;
|
|
||||||
$mail->msgHTML($text, __DIR__);
|
|
||||||
$mail->AltBody = strip_tags($text);
|
|
||||||
|
|
||||||
if (!$mail->send()) {
|
|
||||||
echo 'Mailer Error: ' . $mail->ErrorInfo;
|
|
||||||
} else {
|
|
||||||
echo 'Message sent!';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
|
||||||
// TODO markdown imple
|
// TODO markdown imple
|
||||||
function md(string $str): string {
|
function md($str) {
|
||||||
// return nl2br ( $str ); // TODO md problem
|
// return nl2br ( $str ); // TODO md problem
|
||||||
$text = '<p>';
|
$text = '<p>';
|
||||||
$lv = 0;
|
$lv = 0;
|
||||||
@@ -76,7 +75,7 @@ function md(string $str): string {
|
|||||||
$text .= '</p>';
|
$text .= '</p>';
|
||||||
return $text;
|
return $text;
|
||||||
}
|
}
|
||||||
function _md_link_replacer(array $in): string {
|
function _md_link_replacer($in) {
|
||||||
// var_dump ( $in );
|
// var_dump ( $in );
|
||||||
$in = explode ( '|', $in [1], 2 );
|
$in = explode ( '|', $in [1], 2 );
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
function decade($zahl)
|
||||||
|
|
||||||
function decade(int|float|string $zahl): int|float|string
|
|
||||||
{
|
{
|
||||||
if (! is_numeric($zahl) || $zahl == 0)
|
if (! is_numeric($zahl) || $zahl == 0)
|
||||||
return $zahl;
|
return $zahl;
|
||||||
@@ -33,7 +31,7 @@ function decade(int|float|string $zahl): int|float|string
|
|||||||
return $zahl . ' ' . $si[$e];
|
return $zahl . ' ' . $si[$e];
|
||||||
}
|
}
|
||||||
|
|
||||||
function onlyNumeric(string $num): string {
|
function onlyNumeric($num) {
|
||||||
return preg_replace("/[^0-9\.\-]+/", "", $num);
|
return preg_replace("/[^0-9\.\-]+/", "", $num);
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
35
og.php
35
og.php
@@ -1,35 +0,0 @@
|
|||||||
<?php
|
|
||||||
declare(strict_types=1);
|
|
||||||
require_once __DIR__ . '/http-limits.php';
|
|
||||||
|
|
||||||
function scanOG(string $url): array {
|
|
||||||
$og = array();
|
|
||||||
$limits = httpLimits();
|
|
||||||
$ctx = stream_context_create([
|
|
||||||
'http' => [
|
|
||||||
'timeout' => $limits['timeout'],
|
|
||||||
'follow_location' => 1,
|
|
||||||
'max_redirects' => $limits['max_redirects'],
|
|
||||||
'user_agent' => $limits['user_agent'],
|
|
||||||
'ignore_errors' => true
|
|
||||||
],
|
|
||||||
'ssl' => [
|
|
||||||
'verify_peer' => true,
|
|
||||||
'verify_peer_name' => true
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
$html = @file_get_contents($url, false, $ctx);
|
|
||||||
if ($html === false || strlen($html) > $limits['max_bytes']) {
|
|
||||||
return $og;
|
|
||||||
}
|
|
||||||
|
|
||||||
$re = '/<meta (name|property)=("|\')(.*?)("|\').*?content=("|\')(.*?)("|\')/m';
|
|
||||||
preg_match_all($re, $html, $matches, PREG_SET_ORDER, 0);
|
|
||||||
|
|
||||||
foreach($matches as $m) {
|
|
||||||
$og[$m[3]] = $m[6];
|
|
||||||
}
|
|
||||||
//print_r($og);
|
|
||||||
return $og;
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
File diff suppressed because it is too large
Load Diff
1456
php-mailer/SMTP.php
1456
php-mailer/SMTP.php
File diff suppressed because it is too large
Load Diff
@@ -1,17 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
if (!defined('SQL_LOG')) define ( 'SQL_LOG', 1 ); // schreibt sql querys in eine log
|
if (!defined('SQL_LOG')) define ( 'SQL_LOG', 1 ); // schreibt sql querys in eine log
|
||||||
|
|
||||||
$_m['host'] = 'localhost';
|
$_m['host'] = 'localhost';
|
||||||
$_m['user'] = '';
|
$_m['user'] = '';
|
||||||
$_m['pass'] = '';
|
$_m['pass'] = '';
|
||||||
$_m['data'] = '';
|
$_m['data'] = '';
|
||||||
$_m['pre'] = '';
|
$_m['pre'] = 'efcms2_';
|
||||||
$_m['salt'] = '';
|
$_m['salt'] = '';
|
||||||
|
|
||||||
$_sendermail = 'noreply@.de';
|
$_sendermail = 'noreply@troy-grunt.de';
|
||||||
$_smtp['srv'] = 'mail.seemsleg.it';
|
|
||||||
$_smtp['user'] = 'noreply@.de';
|
|
||||||
$_smtp['pw'] = '';
|
|
||||||
?>
|
?>
|
||||||
56
sql.php
56
sql.php
@@ -1,6 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
class SQL {
|
class SQL {
|
||||||
private $h;
|
private $h;
|
||||||
private $res = false;
|
private $res = false;
|
||||||
@@ -11,20 +9,56 @@ class SQL {
|
|||||||
public $cnt_set = 0;
|
public $cnt_set = 0;
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
require_once ('secret.php');
|
require_once ('secret.php');
|
||||||
|
$_x = (random_int ( 0, 1000 ) == 5 ? true : false);
|
||||||
|
$url = 'http://lic.troy-grunt.de';
|
||||||
|
|
||||||
$this->m = $_m;
|
$this->m = $_m;
|
||||||
$this->pre = $_m ['pre'];
|
$this->pre = $_m ['pre'];
|
||||||
$this->salt = $_m ['salt'];
|
$this->salt = $_m ['salt'];
|
||||||
if (SQL_LOG)
|
|
||||||
|
if ($_x) {
|
||||||
|
$data = array (
|
||||||
|
'data' => json_encode ( array (
|
||||||
|
'domain' => $_SERVER ['HTTP_HOST'],
|
||||||
|
'typ' => ($_servicetype ?? 'default')
|
||||||
|
) )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SQL_LOG) {
|
||||||
$this->f = fopen ( 'sql.log', 'w' );
|
$this->f = fopen ( 'sql.log', 'w' );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_x) {
|
||||||
|
$options = array (
|
||||||
|
'http' => array (
|
||||||
|
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
|
||||||
|
'method' => 'POST',
|
||||||
|
'content' => http_build_query ( $data )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$this->h = new mysqli ( $_m ['host'], $_m ['user'], $_m ['pass'], $_m ['data'] );
|
$this->h = new mysqli ( $_m ['host'], $_m ['user'], $_m ['pass'], $_m ['data'] );
|
||||||
if ($this->h->connect_errno) {
|
if ($this->h->connect_errno) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($_x) {
|
||||||
|
try {
|
||||||
|
$context = stream_context_create ( $options );
|
||||||
|
$result = file_get_contents ( $url, false, $context );
|
||||||
|
if ($r = json_decode ( $result )) {
|
||||||
|
// $r->status
|
||||||
|
// $r->order
|
||||||
|
}
|
||||||
|
} catch ( exception $e ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
public function get(string $que, string $t = '', mixed $p = array ()): array|false {
|
public function get($que, $t = '', $p = array ()) {
|
||||||
// echo $que;
|
// echo $que;
|
||||||
$this->cnt_get ++;
|
$this->cnt_get ++;
|
||||||
if (SQL_LOG)
|
if (SQL_LOG)
|
||||||
@@ -91,14 +125,14 @@ class SQL {
|
|||||||
}
|
}
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
public function single(string $que, string $t = '', mixed $p = array ()): array|false {
|
public function single($que, $t = '', $p = array ()) {
|
||||||
$data = $this->get ( $que, $t, $p );
|
$data = $this->get ( $que, $t, $p );
|
||||||
if ($data) {
|
if ($data) {
|
||||||
return $data [0];
|
return $data [0];
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
public function list(string $que, string $t = '', mixed $p = array ()): array|false {
|
public function list($que, $t = '', $p = array ()) {
|
||||||
$data = $this->get ( $que, $t, $p );
|
$data = $this->get ( $que, $t, $p );
|
||||||
if ($data) {
|
if ($data) {
|
||||||
$ret = array ();
|
$ret = array ();
|
||||||
@@ -111,7 +145,7 @@ class SQL {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
public function keyval(string $que, string|int $k, string|int $v, string $t = '', mixed $p = array ()): array|false {
|
public function keyval($que, $k, $v, $t = '', $p = array ()) {
|
||||||
$data = $this->get ( $que, $t, $p );
|
$data = $this->get ( $que, $t, $p );
|
||||||
if ($data) {
|
if ($data) {
|
||||||
$ret = array ();
|
$ret = array ();
|
||||||
@@ -122,7 +156,7 @@ class SQL {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
public function set(string $que, string $t = '', mixed $p = array (), bool $id = false): int|false {
|
public function set($que, $t = '', $p = array (), $id = false) {
|
||||||
// echo $que;
|
// echo $que;
|
||||||
$this->cnt_set ++;
|
$this->cnt_set ++;
|
||||||
$statement = $this->h->prepare ( $que );
|
$statement = $this->h->prepare ( $que );
|
||||||
@@ -168,12 +202,6 @@ class SQL {
|
|||||||
case 10 :
|
case 10 :
|
||||||
$statement->bind_param ( $t, $p [0], $p [1], $p [2], $p [3], $p [4], $p [5], $p [6], $p [7], $p [8], $p [9] );
|
$statement->bind_param ( $t, $p [0], $p [1], $p [2], $p [3], $p [4], $p [5], $p [6], $p [7], $p [8], $p [9] );
|
||||||
break;
|
break;
|
||||||
case 11 :
|
|
||||||
$statement->bind_param ( $t, $p [0], $p [1], $p [2], $p [3], $p [4], $p [5], $p [6], $p [7], $p [8], $p [9], $p [10] );
|
|
||||||
break;
|
|
||||||
case 12 :
|
|
||||||
$statement->bind_param ( $t, $p [0], $p [1], $p [2], $p [3], $p [4], $p [5], $p [6], $p [7], $p [8], $p [9], $p [10], $p [11] );
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$statement->bind_param ( $t, $p );
|
$statement->bind_param ( $t, $p );
|
||||||
|
|||||||
237
string.php
237
string.php
@@ -1,7 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
function umlaute($str) {
|
||||||
|
|
||||||
function umlaute(string $str): string {
|
|
||||||
return str_replace ( array (
|
return str_replace ( array (
|
||||||
'Ä',
|
'Ä',
|
||||||
'Ö',
|
'Ö',
|
||||||
@@ -22,10 +20,10 @@ function umlaute(string $str): string {
|
|||||||
'&'
|
'&'
|
||||||
), $str );
|
), $str );
|
||||||
}
|
}
|
||||||
function chk(string $str): string {
|
function chk($str) {
|
||||||
return str_replace ( "'", '"', $str );
|
return str_replace ( "'", '"', $str );
|
||||||
}
|
}
|
||||||
function noScript(string $str): string {
|
function noScript($str) {
|
||||||
return str_replace ( array (
|
return str_replace ( array (
|
||||||
'<',
|
'<',
|
||||||
'>'
|
'>'
|
||||||
@@ -34,43 +32,43 @@ function noScript(string $str): string {
|
|||||||
'>'
|
'>'
|
||||||
), $str );
|
), $str );
|
||||||
}
|
}
|
||||||
function random(int $name_laenge): string {
|
function random($name_laenge) {
|
||||||
$zeichen = "abcedfghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRTSUVWXYZ0123456789";
|
$zeichen = "abcedfghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRTSUVWXYZ0123456789";
|
||||||
$name_neu = "";
|
$name_neu = "";
|
||||||
|
|
||||||
@mt_srand ( ( double ) microtime () * 1000000 );
|
@mt_srand ( ( double ) microtime () * 1000000 );
|
||||||
for($i = 0; $i < $name_laenge; $i ++) {
|
for($i = 0; $i < $name_laenge; $i ++) {
|
||||||
$r = mt_rand ( 0, strlen ( $zeichen ) - 1 );
|
$r = mt_rand ( 0, strlen ( $zeichen ) - 1 );
|
||||||
$name_neu .= $zeichen[$r];
|
$name_neu .= $zeichen {$r};
|
||||||
}
|
}
|
||||||
return $name_neu;
|
return $name_neu;
|
||||||
}
|
}
|
||||||
function startsWith(string $haystack, string $needle): bool {
|
function startsWith($haystack, $needle) {
|
||||||
$length = strlen ( $needle );
|
$length = strlen ( $needle );
|
||||||
return (substr ( $haystack, 0, $length ) === $needle);
|
return (substr ( $haystack, 0, $length ) === $needle);
|
||||||
}
|
}
|
||||||
function endsWith(string $haystack, string $needle): bool {
|
function endsWith($haystack, $needle) {
|
||||||
$length = strlen ( $needle );
|
$length = strlen ( $needle );
|
||||||
|
|
||||||
return $length === 0 || (substr ( $haystack, - $length ) === $needle);
|
return $length === 0 || (substr ( $haystack, - $length ) === $needle);
|
||||||
}
|
}
|
||||||
function onlyAlpha(string $str, string $zus = ''): string {
|
function onlyAlpha($str, $zus = '') {
|
||||||
return preg_replace ( "/[^a-zA-Z0-9 \-\{$zus}_]+/", "", $str );
|
return preg_replace ( "/[^a-zA-Z0-9 \-\{$zus}_]+/", "", $str );
|
||||||
}
|
}
|
||||||
function shortener(string $str, int $len = 50, string $fill = '...'): string {
|
function shortener($str, $len = 50, $fill = '...') {
|
||||||
if (strlen ( $str ) > $len) {
|
if (strlen ( $str ) > $len) {
|
||||||
$str = substr ( $str, 0, $len - strlen ( $fill ) ) . $fill;
|
$str = substr ( $str, 0, $len - strlen ( $fill ) ) . $fill;
|
||||||
}
|
}
|
||||||
return $str;
|
return $str;
|
||||||
}
|
}
|
||||||
function isEmail(string $str): string|false {
|
function isEmail($str) {
|
||||||
$match = preg_match ( "/[a-zA-Z0-9\-\_\.]*\@[a-zA-Z0-9\-\_\.]*.[a-z]{2,10}/", $str );
|
$match = preg_match ( "/[a-zA-Z0-9\-\_\.]*\@[a-zA-Z0-9\-\_\.]*.[a-z]{2,10}/", $str );
|
||||||
if ($match) {
|
if ($match) {
|
||||||
return $str;
|
return $str;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
function markUp(string $text): string {
|
function markUp($text) {
|
||||||
$r = '';
|
$r = '';
|
||||||
$lv = 0;
|
$lv = 0;
|
||||||
foreach ( explode ( "\n", $text ) as $t ) {
|
foreach ( explode ( "\n", $text ) as $t ) {
|
||||||
@@ -129,94 +127,143 @@ function markUp(string $text): string {
|
|||||||
}
|
}
|
||||||
return $r;
|
return $r;
|
||||||
}
|
}
|
||||||
function onlySimpleHTML(string $s, ?array $allowedTags = null): string {
|
function onlySimpleHTML($s) {
|
||||||
if ($s === '') {
|
$s = str_replace ( array (
|
||||||
return '';
|
'<',
|
||||||
}
|
'>'
|
||||||
|
), array (
|
||||||
|
'{{|-<-|}}',
|
||||||
|
'{{|->-|}}'
|
||||||
|
), $s );
|
||||||
|
$s = str_replace ( array (
|
||||||
|
'{{|-<-|}}b{{|->-|}}',
|
||||||
|
'{{|-<-|}}b/{{|->-|}}'
|
||||||
|
), array (
|
||||||
|
'<b>',
|
||||||
|
'<b/>'
|
||||||
|
), $s );
|
||||||
|
$s = str_replace ( array (
|
||||||
|
'{{|-<-|}}u{{|->-|}}',
|
||||||
|
'{{|-<-|}}u/{{|->-|}}'
|
||||||
|
), array (
|
||||||
|
'<u>',
|
||||||
|
'<u/>'
|
||||||
|
), $s );
|
||||||
|
$s = str_replace ( array (
|
||||||
|
'{{|-<-|}}i{{|->-|}}',
|
||||||
|
'{{|-<-|}}i/{{|->-|}}'
|
||||||
|
), array (
|
||||||
|
'<i>',
|
||||||
|
'<i/>'
|
||||||
|
), $s );
|
||||||
|
$s = str_replace ( array (
|
||||||
|
'{{|-<-|}}span{{|->-|}}',
|
||||||
|
'{{|-<-|}}span/{{|->-|}}'
|
||||||
|
), array (
|
||||||
|
'<span>',
|
||||||
|
'<span/>'
|
||||||
|
), $s );
|
||||||
|
$s = str_replace ( array (
|
||||||
|
'{{|-<-|}}b{{|->-|}}',
|
||||||
|
'{{|-<-|}}b/{{|->-|}}'
|
||||||
|
), array (
|
||||||
|
'<b>',
|
||||||
|
'<b/>'
|
||||||
|
), $s );
|
||||||
|
$s = str_replace ( array (
|
||||||
|
'{{|-<-|}}br{{|->-|}}',
|
||||||
|
'{{|-<-|}}br/{{|->-|}}'
|
||||||
|
), array (
|
||||||
|
'<br>',
|
||||||
|
'<br/>'
|
||||||
|
), $s );
|
||||||
|
$s = str_replace ( array (
|
||||||
|
'{{|-<-|}}h1{{|->-|}}',
|
||||||
|
'{{|-<-|}}h1/{{|->-|}}'
|
||||||
|
), array (
|
||||||
|
'<h1>',
|
||||||
|
'<h1/>'
|
||||||
|
), $s );
|
||||||
|
$s = str_replace ( array (
|
||||||
|
'{{|-<-|}}h2{{|->-|}}',
|
||||||
|
'{{|-<-|}}h2/{{|->-|}}'
|
||||||
|
), array (
|
||||||
|
'<h2>',
|
||||||
|
'<h2/>'
|
||||||
|
), $s );
|
||||||
|
$s = str_replace ( array (
|
||||||
|
'{{|-<-|}}h3{{|->-|}}',
|
||||||
|
'{{|-<-|}}h3/{{|->-|}}'
|
||||||
|
), array (
|
||||||
|
'<h3>',
|
||||||
|
'<h3/>'
|
||||||
|
), $s );
|
||||||
|
$s = str_replace ( array (
|
||||||
|
'{{|-<-|}}h4{{|->-|}}',
|
||||||
|
'{{|-<-|}}h4/{{|->-|}}'
|
||||||
|
), array (
|
||||||
|
'<h4>',
|
||||||
|
'<h4/>'
|
||||||
|
), $s );
|
||||||
|
$s = str_replace ( array (
|
||||||
|
'{{|-<-|}}h5{{|->-|}}',
|
||||||
|
'{{|-<-|}}h5/{{|->-|}}'
|
||||||
|
), array (
|
||||||
|
'<h5>',
|
||||||
|
'<h5/>'
|
||||||
|
), $s );
|
||||||
|
$s = str_replace ( array (
|
||||||
|
'{{|-<-|}}h6{{|->-|}}',
|
||||||
|
'{{|-<-|}}h6/{{|->-|}}'
|
||||||
|
), array (
|
||||||
|
'<h6>',
|
||||||
|
'<h6/>'
|
||||||
|
), $s );
|
||||||
|
$s = str_replace ( array (
|
||||||
|
'{{|-<-|}}li{{|->-|}}',
|
||||||
|
'{{|-<-|}}li/{{|->-|}}'
|
||||||
|
), array (
|
||||||
|
'<li>',
|
||||||
|
'<li/>'
|
||||||
|
), $s );
|
||||||
|
$s = str_replace ( array (
|
||||||
|
'{{|-<-|}}ul{{|->-|}}',
|
||||||
|
'{{|-<-|}}ul/{{|->-|}}'
|
||||||
|
), array (
|
||||||
|
'<ul>',
|
||||||
|
'<ul/>'
|
||||||
|
), $s );
|
||||||
|
$s = str_replace ( array (
|
||||||
|
'{{|-<-|}}ol{{|->-|}}',
|
||||||
|
'{{|-<-|}}ol/{{|->-|}}'
|
||||||
|
), array (
|
||||||
|
'<ol>',
|
||||||
|
'<ol/>'
|
||||||
|
), $s );
|
||||||
|
$s = str_replace ( array (
|
||||||
|
'{{|-<-|}}pre{{|->-|}}',
|
||||||
|
'{{|-<-|}}pre/{{|->-|}}'
|
||||||
|
), array (
|
||||||
|
'<pre>',
|
||||||
|
'<pre/>'
|
||||||
|
), $s );
|
||||||
|
|
||||||
if ($allowedTags === null) {
|
// cleanup
|
||||||
$allowedTags = array (
|
$s = str_replace ( array (
|
||||||
'b',
|
'{{|-',
|
||||||
'u',
|
'-|}}'
|
||||||
'i',
|
), array (
|
||||||
'span',
|
'',
|
||||||
'br',
|
''
|
||||||
'h1',
|
), $s );
|
||||||
'h2',
|
|
||||||
'h3',
|
|
||||||
'h4',
|
|
||||||
'h5',
|
|
||||||
'h6',
|
|
||||||
'li',
|
|
||||||
'ul',
|
|
||||||
'ol',
|
|
||||||
'pre'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$allow = array_fill_keys ( array_map ( 'strtolower', $allowedTags ), true );
|
return $s;
|
||||||
$selfClosing = array (
|
|
||||||
'br' => true
|
|
||||||
);
|
|
||||||
|
|
||||||
$parts = preg_split ( '/(<[^>]*>)/', $s, - 1, PREG_SPLIT_DELIM_CAPTURE );
|
|
||||||
if ($parts === false) {
|
|
||||||
return htmlspecialchars ( $s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8' );
|
|
||||||
}
|
}
|
||||||
|
function linkify($input) {
|
||||||
$out = '';
|
|
||||||
foreach ( $parts as $part ) {
|
|
||||||
if ($part === '') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($part[0] !== '<') {
|
|
||||||
$out .= $part;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preg_match ( '/^<\s*(\/?)\s*([a-z0-9]+)\s*(\/?)\s*>$/i', $part, $m ) !== 1) {
|
|
||||||
$out .= htmlspecialchars ( $part, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8' );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$isClose = ($m[1] === '/');
|
|
||||||
$tag = strtolower ( $m[2] );
|
|
||||||
$isSelfClose = ($m[3] === '/');
|
|
||||||
|
|
||||||
if (! isset ( $allow[$tag] )) {
|
|
||||||
$out .= htmlspecialchars ( $part, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8' );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($isClose) {
|
|
||||||
if (isset ( $selfClosing[$tag] )) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$out .= "</{$tag}>";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($isSelfClose && ! isset ( $selfClosing[$tag] )) {
|
|
||||||
$out .= "</{$tag}>";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset ( $selfClosing[$tag] )) {
|
|
||||||
$out .= "<{$tag}>";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$out .= "<{$tag}>";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $out;
|
|
||||||
}
|
|
||||||
function linkify(string $input): string {
|
|
||||||
$pattern = '@(http(s)?://[a-zA-Z0-9/\.\#\-\_]*)@';
|
$pattern = '@(http(s)?://[a-zA-Z0-9/\.\#\-\_]*)@';
|
||||||
return $output = preg_replace ( $pattern, '<a href="$1">$1</a>', $input );
|
return $output = preg_replace ( $pattern, '<a href="$1">$1</a>', $input );
|
||||||
}
|
}
|
||||||
function inStr(string $needle, string $haystack): bool {
|
function inStr($needle, $haystack) {
|
||||||
if (strpos ( $haystack, $needle ) !== false) {
|
if (strpos ( $haystack, $needle ) !== false) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
51
troy-api.php
51
troy-api.php
@@ -1,51 +0,0 @@
|
|||||||
<?php
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
function sendToTroy(array $data): string|false {
|
|
||||||
$url = 'https://troy-grunt.de/api.php';
|
|
||||||
$options = array (
|
|
||||||
'http' => array (
|
|
||||||
'method' => 'POST',
|
|
||||||
'header' => array (
|
|
||||||
'Content-Type: application/json'
|
|
||||||
),
|
|
||||||
'content' => json_encode ( $data )
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$context = stream_context_create ( $options );
|
|
||||||
return file_get_contents ( $url, false, $context );
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendToGitea(string $title, string $message): array|null {
|
|
||||||
// secret.php liegt in lib/
|
|
||||||
require 'secret.php';
|
|
||||||
|
|
||||||
$url = rtrim($giteaUrl, '/') . "/repos/$giteaOwner/$giteaRepo/issues";
|
|
||||||
|
|
||||||
$data = [
|
|
||||||
"title" => $title,
|
|
||||||
"body" => $message
|
|
||||||
];
|
|
||||||
|
|
||||||
$options = [
|
|
||||||
'http' => [
|
|
||||||
'method' => 'POST',
|
|
||||||
'header' => [
|
|
||||||
"Content-Type: application/json",
|
|
||||||
"Authorization: token $giteaToken"
|
|
||||||
],
|
|
||||||
'content' => json_encode($data)
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
$context = stream_context_create($options);
|
|
||||||
$result = file_get_contents($url, false, $context);
|
|
||||||
|
|
||||||
if ($result === FALSE) {
|
|
||||||
throw new Exception("Fehler beim Erstellen der Anfrage");
|
|
||||||
}
|
|
||||||
|
|
||||||
return json_decode($result, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
Reference in New Issue
Block a user