Server connection and protocol negotiation working. Web site added to repository.

This commit is contained in:
Scott Duensing 2021-12-24 19:00:36 -06:00
parent f445a6ef57
commit 79edabef5f
189 changed files with 70874 additions and 109 deletions

1
.gitattributes vendored
View file

@ -1 +1,2 @@
*.png filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text

7
.gitignore vendored
View file

@ -7,3 +7,10 @@ bin/
obj/
retired/
test/
kanga.world/kirby/
kanga.world/.htaccess
kanga.world/README.md
kanga.world/composer.json
kanga.world/index.php

View file

@ -18,6 +18,10 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# This requires DJGPP for Linux in /opt/cross/djgpp
#
# See: https://github.com/andrewwutw/build-djgpp
mkdir -p \
bin/data \
obj/client/src/system \

View file

@ -69,6 +69,9 @@ HEADERS = \
src/config.h \
$$SHARED/util.h \
src/gui/msgbox.h \
src/login.h \
src/network.h \
src/runtime.h \
src/thirdparty/minicoro/minicoro.h \
src/system/comport.h \
src/settings.h \
@ -113,6 +116,8 @@ SOURCES = \
src/config.c \
$$SHARED/memory.c \
src/gui/msgbox.c \
src/login.c \
src/network.c \
src/settings.c \
src/system/comport.c \
src/system/surface.c \

View file

@ -39,6 +39,7 @@
#define COM_BUFFER_SIZE 2048
#define MODEM_RESULT_OK 1
#define MODEM_RESULT_ERROR 2
#define MODEM_RESULT_NOTHING 3
static MouseT _mouse = { 0 };
@ -70,9 +71,11 @@ static char _buffer[COM_BUFFER_SIZE] = { 0 };
static uint16_t _bufferHead = 0;
static uint16_t _bufferTail = 0;
static uint8_t _connected = 0;
static char _command[COM_BUFFER_SIZE] = { 0 };
static void comAddToBuffer(char *data, uint16_t len);
static void comBufferShow(void);
static void comModem(uint8_t c);
static void processEvent(void);
static void processNetworkEvent(void);
@ -96,6 +99,19 @@ static void comAddToBuffer(char *data, uint16_t len) {
}
static void comBufferShow(void) {
uint16_t x = _bufferTail;
logWrite("={");
while (x != _bufferHead) {
if (_buffer[x] != '\r' && _buffer[x] != '\n') logWrite("%c ", _buffer[x]);
logWrite("%02x ", (uint8_t)_buffer[x++]);
if (x >= COM_BUFFER_SIZE) x = 0;
}
logWrite("}\n");
}
int comClose(int com) {
// We only pretend to support one COM port.
if (com != 0) return SER_ERR_UNKNOWN;
@ -117,42 +133,37 @@ int comClose(int com) {
static void comModem(uint8_t c) {
static char command[COM_BUFFER_SIZE] = { 0 };
uint16_t x;
uint16_t x = 0;
uint8_t result = 0;
uint8_t parsing = 1;
char *p = NULL;
if (c != 13) {
x = strlen(command);
x = strlen(_command);
// Room in buffer?
if (x > COM_BUFFER_SIZE - 1) {
// No. Error. Clear buffer.
snprintf(command, COM_BUFFER_SIZE, "%cERROR%c", 13, 13);
comAddToBuffer(command, strlen(command));
command[0] = 0;
// No. Clear buffer.
_command[0] = 0;
} else {
// Add to command buffer.
command[x] = toupper(c);
command[x+1] = 0;
_command[x] = toupper(c);
_command[x + 1] = 0;
}
} else {
// AT?
if (command[0] != 'A' || command[1] != 'T') result = MODEM_RESULT_ERROR;
if (_command[0] == 'A' || _command[1] == 'T') {
// Process command string.
x = 2;
while (parsing && !result && command[x]) {
switch (command[x]) {
while (!result && _command[x]) {
switch (_command[x]) {
// Vendor Commands
case '+':
x++;
// Select Socket Mode
if (strncmp(&command[x], "SOCK", 4) == 0) {
if (strncmp(&_command[x], "SOCK", 4) == 0) {
result = MODEM_RESULT_OK;
} else {
result = MODEM_RESULT_ERROR;
@ -163,15 +174,15 @@ static void comModem(uint8_t c) {
// Dial
case 'D':
x++;
if (command[x] == 'T' || command[x] == 'P') x++;
if (_command[x] == 'T' || _command[x] == 'P') x++;
// Find port, if any.
_address.port = 23;
if ((p = strstr(&command[x], ":"))) {
if ((p = strstr(&_command[x], ":"))) {
*p = 0;
p++;
_address.port = atoi(p);
}
if (enet_address_set_host(&_address, &command[x]) < 0) {
if (enet_address_set_host(&_address, &_command[x]) < 0) {
result = MODEM_RESULT_ERROR;
} else {
_host = enet_host_create(NULL, 1, 1, 0, 0);
@ -197,22 +208,30 @@ static void comModem(uint8_t c) {
break;
}
}
} else { // AT
// Not an AT command. Just gibberish sent to the modem.
result = MODEM_RESULT_NOTHING;
}
// Send result.
switch (result) {
case MODEM_RESULT_OK:
snprintf(command, COM_BUFFER_SIZE, "OK%c", 13);
comAddToBuffer(command, strlen(command));
snprintf(_command, COM_BUFFER_SIZE, "OK%c", 13);
comAddToBuffer(_command, strlen(_command));
break;
case MODEM_RESULT_ERROR:
snprintf(command, COM_BUFFER_SIZE, "ERROR%c", 13);
comAddToBuffer(command, strlen(command));
snprintf(_command, COM_BUFFER_SIZE, "ERROR%c", 13);
comAddToBuffer(_command, strlen(_command));
break;
case MODEM_RESULT_NOTHING:
// Nothing.
break;
}
// Clear buffer.
command[0] = 0;
_command[0] = 0;
}
}
@ -270,7 +289,9 @@ int comWrite(int com, const char *data, int len) {
if (!_comPortOpen) return SER_ERR_NOT_OPEN;
while (_modemCommandMode && x < len) {
// Echo to terminal.
comAddToBuffer((char *)&data[x], 1);
// Send to modem command mode.
comModem(data[x++]);
}

44
client/src/login.c Normal file
View file

@ -0,0 +1,44 @@
/*
* Kangaroo Punch MultiPlayer Game Server Mark II
* Copyright (C) 2020-2021 Scott Duensing
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "login.h"
#include "taglist.h"
#include "task.h"
static WindowT *_winLogin = NULL;
void taskLogin(void *data) {
(void)data;
TagItemT uiLogin[] = {
T_START,
T_WINDOW, O(_winLogin),
T_TITLE, P("Login"),
T_WIDTH, 500, T_HEIGHT, 225,
T_WINDOW, T_DONE,
T_END
};
tagListRun(uiLogin);
}

31
client/src/login.h Normal file
View file

@ -0,0 +1,31 @@
/*
* Kangaroo Punch MultiPlayer Game Server Mark II
* Copyright (C) 2020-2021 Scott Duensing
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef LOGIN_H
#define LOGIN_H
#include "os.h"
void taskLogin(void *data);
#endif // LOGIN_H

View file

@ -46,11 +46,13 @@
#include "timer.h"
#include "gui.h"
#include "config.h"
#include "runtime.h"
#include "welcome.h"
PacketThreadDataT *__packetThreadData = NULL; // Exported in os.h
RuntimeDataT __runtimeData; // Exported in runtime.h
static void taskComDebugLoop(void *data);

146
client/src/network.c Normal file
View file

@ -0,0 +1,146 @@
/*
* Kangaroo Punch MultiPlayer Game Server Mark II
* Copyright (C) 2020-2021 Scott Duensing
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "gui.h"
#include "task.h"
#include "comport.h"
#include "config.h"
#include "timer.h"
#include "network.h"
typedef struct NetworkPacketS {
uint8_t key;
PacketDecodeDataT **value;
} NetworkPacketT;
static NetworkPacketT *_packets = NULL;
static uint8_t _netRunning = 0;
uint8_t netGetChannelFree(void) {
uint8_t channel = 0; // We reserve 0 for system stuff. Returning 0 means no channel was found.
uint16_t x = 0;
for (x=1; x<255; x++) {
if (hmgeti(_packets, x) < 0) {
channel = x;
break;
}
}
return channel;
}
PacketDecodeDataT *netGetPacket(uint8_t channel) {
int32_t r = 0;
PacketDecodeDataT *packet = NULL;
r = hmgeti(_packets, channel);
if (r < 0) return NULL;
if (arrlen(_packets[r].value) == 0) return NULL;
packet = _packets[r].value[0];
arrdel(_packets[r].value, 0);
return packet;
}
void netStop(void) {
_netRunning = 0;
}
void taskNetwork(void *data) {
int32_t r = 0;
int8_t pingTimeout = 0;
char buffer[1024] = { 0 };
PacketDecodeDataT *packet = NULL;
PacketDecodeDataT decoded = { 0 };
PacketEncodeDataT encoded = { 0 };
(void)data;
_netRunning = 1;
do {
// Read pending bytes.
r = comRead(__configData.serialCom - 1, buffer, 1024);
if (r > 0) {
// Decode them into packets.
if (packetDecode(__packetThreadData, &decoded, buffer, r)) {
// Is this a PONG? If so, ignore it.
if (decoded.packetType == PACKET_TYPE_PONG) continue;
// Copy the packet out.
NEW(PacketDecodeDataT, packet);
packet->channel = decoded.channel;
packet->length = decoded.length;
packet->packetType = decoded.packetType;
packet->data = (char *)malloc(decoded.length);
memcpy(packet->data, decoded.data, decoded.length);
// Is there a list of packets for this channel already?
r = hmgeti(_packets, packet->channel);
if (r < 0) {
// No. Create dynamic array for this channel.
hmput(_packets, packet->channel, NULL);
r = hmgeti(_packets, packet->channel);
}
// Add new packet to existing list.
arrput(_packets[r].value, packet);
}
} else {
// No bytes pending, yield to UI.
taskYield();
}
// Send a ping to the server every 5 seconds, because, ping.
if (__timerSecondTick) {
pingTimeout++;
if (pingTimeout > 5) {
pingTimeout = 0;
encoded.control = PACKET_CONTROL_DAT;
encoded.packetType = PACKET_TYPE_PING;
encoded.channel = 0;
encoded.encrypt = 0;
packetEncode(__packetThreadData, &encoded, NULL, 0); // Must encode each packet - no reusing encoded data.
packetSend(__packetThreadData, &encoded);
}
}
} while (!guiHasStopped() && _netRunning);
// Free any unclaimed packets.
while (hmlenu(_packets) > 0) {
// Free any packets for this channel.
while (arrlenu(_packets[0].value) > 0) {
packetDecodeDataDestroy(&_packets[0].value[0]);
arrdel(_packets[0].value, 0);
}
arrfree(_packets[0].value);
hmdel(_packets, _packets[0].key);
}
hmfree(_packets);
}

35
client/src/network.h Normal file
View file

@ -0,0 +1,35 @@
/*
* Kangaroo Punch MultiPlayer Game Server Mark II
* Copyright (C) 2020-2021 Scott Duensing
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef NETWORK_H
#define NETWORK_H
#include "os.h"
uint8_t netGetChannelFree(void);
PacketDecodeDataT *netGetPacket(uint8_t channel);
void netStop(void);
void taskNetwork(void *data);
#endif // NETWORK_H

36
client/src/runtime.h Normal file
View file

@ -0,0 +1,36 @@
/*
* Kangaroo Punch MultiPlayer Game Server Mark II
* Copyright (C) 2020-2021 Scott Duensing
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef RUNTIME_H
#define RUNTIME_H
#include "os.h"
typedef struct RuntimeDataS {
uint32_t protocolVersion;
} RuntimeDataT;
extern RuntimeDataT __runtimeData;
#endif // RUNTIME_H

View file

@ -74,9 +74,7 @@ int comWaitWithTimeout(int com, char *buffer, int len, int quarterSeconds, char
}
} else {
taskYield();
}
if (__timerQuarterSecondTick) {
quarterTicks++;
if (__timerQuarterSecondTick) quarterTicks++;
}
}

View file

@ -20,12 +20,15 @@
#include "welcome.h"
#include "settings.h"
#include "login.h"
#include "taglist.h"
#include "task.h"
#include "config.h"
#include "comport.h"
#include "timer.h"
#include "network.h"
#include "runtime.h"
#include "window.h"
#include "picture.h"
@ -76,8 +79,10 @@ static void btnMsgBoxQuit(MsgBoxButtonT button) {
static void taskConnectClick(void *data) {
int32_t r;
char buffer[1024];
int32_t r = 0;
char buffer[1024] = { 0 };
PacketDecodeDataT *decoded = NULL;
int16_t timeout = 0;
(void)data;
@ -106,7 +111,7 @@ static void taskConnectClick(void *data) {
snprintf(buffer, 1023, "%s%c", "AT+SOCK1", 13);
comWrite(__configData.serialCom - 1, buffer, strlen(buffer));
// Wait roughly a second for "OK".
r = comWaitWithTimeout(__configData.serialCom - 1, buffer, 1023, 4, "\rOK\r");
r = comWaitWithTimeout(__configData.serialCom - 1, buffer, 1023, 4, "OK");
if (r <= 0) {
comClose(__configData.serialCom - 1);
msgBoxOne("Modem Problem", MSGBOX_ICON_ERROR, "Modem does not support ENET!\nPlease check settings.", "Okay", btnMsgBox);
@ -129,9 +134,48 @@ static void taskConnectClick(void *data) {
return;
}
// Connected! Show icon and negotiate session.
// Connected! Show icon.
widgetVisibleSet(W(_picConnect), 1);
taskYield();
// Start packet handler and negotiate encryption.
taskCreate(taskNetwork, NULL);
packetEncryptionSetup(__packetThreadData);
timeout = 5;
do {
if (packetEncryptionReady()) break;
taskYield();
if (__timerSecondTick) timeout--;
} while (!guiHasStopped() && timeout >= 0);
if (timeout < 0) {
comClose(__configData.serialCom - 1);
msgBoxOne("Negotiation Error", MSGBOX_ICON_INFORMATION, "Unable to negotiate encryption settings!", "Okay", btnMsgBox);
return;
}
// Wait for version packet to arrive.
timeout = 10;
do {
decoded = netGetPacket(0);
if (decoded) {
if (decoded->packetType == PACKET_TYPE_VERSION) {
__runtimeData.protocolVersion = *(uint32_t *)decoded->data;
packetDecodeDataDestroy(&decoded);
break;
}
}
taskYield();
if (__timerSecondTick) timeout--;
} while (!guiHasStopped() && timeout >= 0);
if (timeout < 0) {
comClose(__configData.serialCom - 1);
msgBoxOne("Negotiation Error", MSGBOX_ICON_INFORMATION, "Unable to fetch client settings!", "Okay", btnMsgBox);
return;
}
// Switch to Login window.
guiDelete(D(_winWelcome));
taskCreate(taskLogin, NULL);
}

22
kanga.world/.editorconfig Normal file
View file

@ -0,0 +1,22 @@
[*.{css,scss,less,js,json,ts,sass,html,hbs,mustache,phtml,html.twig,md,yml}]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
indent_size = 4
trim_trailing_whitespace = false
[site/templates/**.php]
indent_size = 2
[site/snippets/**.php]
indent_size = 2
[package.json,.{babelrc,editorconfig,eslintrc,lintstagedrc,stylelintrc}]
indent_style = space
indent_size = 2

50
kanga.world/.gitignore vendored Normal file
View file

@ -0,0 +1,50 @@
# System files
# ------------
Icon
.DS_Store
# Temporary files
# ---------------
/media/*
!/media/index.html
# Lock files
# ---------------
.lock
# Editors
# (sensitive workspace files)
# ---------------------------
*.sublime-workspace
/.vscode
/.idea
# -------------SECURITY-------------
# NEVER publish these files via Git!
# -------------SECURITY-------------
# Cache Files
# ---------------
/site/cache/*
!/site/cache/index.html
# Accounts
# ---------------
/site/accounts/*
!/site/accounts/index.html
# Sessions
# ---------------
/site/sessions/*
!/site/sessions/index.html
# License
# ---------------
/site/config/.license

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,485 @@
/*!
* Bootstrap Reboot v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
:root {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg-rgb: 255, 255, 255;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-bg: #fff;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
background-color: currentColor;
border: 0;
opacity: 0.25;
}
hr:not([size]) {
height: 1px;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-bs-original-title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-left: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.2em;
background-color: #fcf8e3;
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: #0d6efd;
text-decoration: underline;
}
a:hover {
color: #0a58ca;
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
direction: ltr /* rtl:ignore */;
unicode-bidi: bidi-override;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: #d63384;
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.2rem 0.4rem;
font-size: 0.875em;
color: #fff;
background-color: #212529;
border-radius: 0.2rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
font-weight: 700;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: #6c757d;
text-align: left;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]::-webkit-calendar-picker-indicator {
display: none;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: left;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: left;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
/* rtl:raw:
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
}
::file-selector-button {
font: inherit;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,482 @@
/*!
* Bootstrap Reboot v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
:root {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg-rgb: 255, 255, 255;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-bg: #fff;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
background-color: currentColor;
border: 0;
opacity: 0.25;
}
hr:not([size]) {
height: 1px;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-bs-original-title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-right: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-right: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.2em;
background-color: #fcf8e3;
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: #0d6efd;
text-decoration: underline;
}
a:hover {
color: #0a58ca;
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
direction: ltr ;
unicode-bidi: bidi-override;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: #d63384;
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.2rem 0.4rem;
font-size: 0.875em;
color: #fff;
background-color: #212529;
border-radius: 0.2rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
font-weight: 700;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: #6c757d;
text-align: right;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]::-webkit-calendar-picker-indicator {
display: none;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: right;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: right;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
}
::file-selector-button {
font: inherit;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,102 @@
a:link:not(.dropdown-item), a:visited:not(.dropdown-item), a:hover:not(.dropdown-item), a:active:not(.dropdown-item) {
color: #ff0000;
}
h3 {
color: #e64946;
font-weight: bold;
border-bottom: 2px solid #e64946;
margin-bottom: 25px;
}
.imagecenter {
display: block;
margin-left: auto;
margin-right: auto;
/* width: 50%; */
}
.imageright {
float: right;
clear: right;
margin-left: 20px;
margin-right: 20px;
}
.imagerightpadded {
float: right;
clear: right;
margin-left: 20px;
margin-right: 20px;
margin-bottom: 50px;
}
.imageleft {
float: left;
clear: left;
margin-left: 20px;
margin-right: 20px;
}
.logo {
margin-top: 10px;
margin-bottom: 10px;
}
.mainpage {
margin-top: 20px;
margin-bottom: 40px;
}
.news {
margin-bottom: 40px;
}
.newspublished {
font-style: italic;
}
.newsdate {
font-weight: bold;
}
.gallery {
display: block;
margin-left: auto;
margin-right: auto;
width: 690px;
}
.gallerycaption {
margin-top: 50px;
font-weight: bold;
}
.downloadlink {
}
.downloadlinkerror {
font-weight: bold;
}
.columns {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
margin-left: -1rem;
margin-right: -1rem;
}
.column {
flex: 0 1 100%;
margin-left: 1rem;
margin-right: 1rem;
max-width: 100%;
}
@media (min-width: 790px) {
.column {
flex: 1;
}
}

BIN
kanga.world/assets/images/Kanga-FavIcon.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
kanga.world/assets/images/Kangaroo-Punch-Logo.png (Stored with Git LFS) Normal file

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View file

@ -0,0 +1,10 @@
css_dir = "."
sass_dir = "."
images_dir = "."
fonts_dir = "fonts"
relative_assets = true
output_style = :compact
line_comments = false
preferred_syntax = :scss

Binary file not shown.

View file

@ -0,0 +1,14 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by Fontastic.me</metadata>
<defs>
<font id="slick" horiz-adv-x="512">
<font-face font-family="slick" units-per-em="512" ascent="480" descent="-32"/>
<missing-glyph horiz-adv-x="512" />
<glyph unicode="&#8594;" d="M241 113l130 130c4 4 6 8 6 13 0 5-2 9-6 13l-130 130c-3 3-7 5-12 5-5 0-10-2-13-5l-29-30c-4-3-6-7-6-12 0-5 2-10 6-13l87-88-87-88c-4-3-6-8-6-13 0-5 2-9 6-12l29-30c3-3 8-5 13-5 5 0 9 2 12 5z m234 143c0-40-9-77-29-110-20-34-46-60-80-80-33-20-70-29-110-29-40 0-77 9-110 29-34 20-60 46-80 80-20 33-29 70-29 110 0 40 9 77 29 110 20 34 46 60 80 80 33 20 70 29 110 29 40 0 77-9 110-29 34-20 60-46 80-80 20-33 29-70 29-110z"/>
<glyph unicode="&#8592;" d="M296 113l29 30c4 3 6 7 6 12 0 5-2 10-6 13l-87 88 87 88c4 3 6 8 6 13 0 5-2 9-6 12l-29 30c-3 3-8 5-13 5-5 0-9-2-12-5l-130-130c-4-4-6-8-6-13 0-5 2-9 6-13l130-130c3-3 7-5 12-5 5 0 10 2 13 5z m179 143c0-40-9-77-29-110-20-34-46-60-80-80-33-20-70-29-110-29-40 0-77 9-110 29-34 20-60 46-80 80-20 33-29 70-29 110 0 40 9 77 29 110 20 34 46 60 80 80 33 20 70 29 110 29 40 0 77-9 110-29 34-20 60-46 80-80 20-33 29-70 29-110z"/>
<glyph unicode="&#8226;" d="M475 256c0-40-9-77-29-110-20-34-46-60-80-80-33-20-70-29-110-29-40 0-77 9-110 29-34 20-60 46-80 80-20 33-29 70-29 110 0 40 9 77 29 110 20 34 46 60 80 80 33 20 70 29 110 29 40 0 77-9 110-29 34-20 60-46 80-80 20-33 29-70 29-110z"/>
<glyph unicode="&#97;" d="M475 439l0-128c0-5-1-9-5-13-4-4-8-5-13-5l-128 0c-8 0-13 3-17 11-3 7-2 14 4 20l40 39c-28 26-62 39-100 39-20 0-39-4-57-11-18-8-33-18-46-32-14-13-24-28-32-46-7-18-11-37-11-57 0-20 4-39 11-57 8-18 18-33 32-46 13-14 28-24 46-32 18-7 37-11 57-11 23 0 44 5 64 15 20 9 38 23 51 42 2 1 4 3 7 3 3 0 5-1 7-3l39-39c2-2 3-3 3-6 0-2-1-4-2-6-21-25-46-45-76-59-29-14-60-20-93-20-30 0-58 5-85 17-27 12-51 27-70 47-20 19-35 43-47 70-12 27-17 55-17 85 0 30 5 58 17 85 12 27 27 51 47 70 19 20 43 35 70 47 27 12 55 17 85 17 28 0 55-5 81-15 26-11 50-26 70-45l37 37c6 6 12 7 20 4 8-4 11-9 11-17z"/>
</font></defs></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,204 @@
@charset 'UTF-8';
/* Slider */
.slick-loading .slick-list
{
background: #fff url('./ajax-loader.gif') center center no-repeat;
}
/* Icons */
@font-face
{
font-family: 'slick';
font-weight: normal;
font-style: normal;
src: url('./fonts/slick.eot');
src: url('./fonts/slick.eot?#iefix') format('embedded-opentype'), url('./fonts/slick.woff') format('woff'), url('./fonts/slick.ttf') format('truetype'), url('./fonts/slick.svg#slick') format('svg');
}
/* Arrows */
.slick-prev,
.slick-next
{
font-size: 0;
line-height: 0;
position: absolute;
top: 50%;
display: block;
width: 20px;
height: 20px;
padding: 0;
-webkit-transform: translate(0, -50%);
-ms-transform: translate(0, -50%);
transform: translate(0, -50%);
cursor: pointer;
color: transparent;
border: none;
outline: none;
background: transparent;
}
.slick-prev:hover,
.slick-prev:focus,
.slick-next:hover,
.slick-next:focus
{
color: transparent;
outline: none;
background: transparent;
}
.slick-prev:hover:before,
.slick-prev:focus:before,
.slick-next:hover:before,
.slick-next:focus:before
{
opacity: 1;
}
.slick-prev.slick-disabled:before,
.slick-next.slick-disabled:before
{
opacity: .25;
}
.slick-prev:before,
.slick-next:before
{
font-family: 'slick';
font-size: 20px;
line-height: 1;
opacity: .75;
color: white;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.slick-prev
{
left: -25px;
}
[dir='rtl'] .slick-prev
{
right: -25px;
left: auto;
}
.slick-prev:before
{
content: '←';
}
[dir='rtl'] .slick-prev:before
{
content: '→';
}
.slick-next
{
right: -25px;
}
[dir='rtl'] .slick-next
{
right: auto;
left: -25px;
}
.slick-next:before
{
content: '→';
}
[dir='rtl'] .slick-next:before
{
content: '←';
}
/* Dots */
.slick-dotted.slick-slider
{
margin-bottom: 30px;
}
.slick-dots
{
position: absolute;
bottom: -25px;
display: block;
width: 100%;
padding: 0;
margin: 0;
list-style: none;
text-align: center;
}
.slick-dots li
{
position: relative;
display: inline-block;
width: 20px;
height: 20px;
margin: 0 5px;
padding: 0;
cursor: pointer;
}
.slick-dots li button
{
font-size: 0;
line-height: 0;
display: block;
width: 20px;
height: 20px;
padding: 5px;
cursor: pointer;
color: transparent;
border: 0;
outline: none;
background: transparent;
}
.slick-dots li button:hover,
.slick-dots li button:focus
{
outline: none;
}
.slick-dots li button:hover:before,
.slick-dots li button:focus:before
{
opacity: 1;
}
.slick-dots li button:before
{
font-family: 'slick';
font-size: 6px;
line-height: 20px;
position: absolute;
top: 0;
left: 0;
width: 20px;
height: 20px;
content: '•';
text-align: center;
opacity: .25;
color: black;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.slick-dots li.slick-active button:before
{
opacity: .75;
color: black;
}

View file

@ -0,0 +1,168 @@
@charset "UTF-8";
// Default Variables
@slick-font-path: "./fonts/";
@slick-font-family: "slick";
@slick-loader-path: "./";
@slick-arrow-color: white;
@slick-dot-color: black;
@slick-dot-color-active: @slick-dot-color;
@slick-prev-character: "←";
@slick-next-character: "→";
@slick-dot-character: "•";
@slick-dot-size: 6px;
@slick-opacity-default: 0.75;
@slick-opacity-on-hover: 1;
@slick-opacity-not-active: 0.25;
/* Slider */
.slick-loading .slick-list{
background: #fff url('@{slick-loader-path}ajax-loader.gif') center center no-repeat;
}
/* Arrows */
.slick-prev,
.slick-next {
position: absolute;
display: block;
height: 20px;
width: 20px;
line-height: 0px;
font-size: 0px;
cursor: pointer;
background: transparent;
color: transparent;
top: 50%;
-webkit-transform: translate(0, -50%);
-ms-transform: translate(0, -50%);
transform: translate(0, -50%);
padding: 0;
border: none;
outline: none;
&:hover, &:focus {
outline: none;
background: transparent;
color: transparent;
&:before {
opacity: @slick-opacity-on-hover;
}
}
&.slick-disabled:before {
opacity: @slick-opacity-not-active;
}
}
.slick-prev:before, .slick-next:before {
font-family: @slick-font-family;
font-size: 20px;
line-height: 1;
color: @slick-arrow-color;
opacity: @slick-opacity-default;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
& when ( @slick-font-family = 'slick' ) {
/* Icons */
@font-face {
font-family: 'slick';
font-weight: normal;
font-style: normal;
src: url('@{slick-font-path}slick.eot');
src: url('@{slick-font-path}slick.eot?#iefix') format('embedded-opentype'), url('@{slick-font-path}slick.woff') format('woff'), url('@{slick-font-path}slick.ttf') format('truetype'), url('@{slick-font-path}slick.svg#slick') format('svg');
}
}
}
.slick-prev {
left: -25px;
[dir="rtl"] & {
left: auto;
right: -25px;
}
&:before {
content: @slick-prev-character;
[dir="rtl"] & {
content: @slick-next-character;
}
}
}
.slick-next {
right: -25px;
[dir="rtl"] & {
left: -25px;
right: auto;
}
&:before {
content: @slick-next-character;
[dir="rtl"] & {
content: @slick-prev-character;
}
}
}
/* Dots */
.slick-dotted .slick-slider {
margin-bottom: 30px;
}
.slick-dots {
position: absolute;
bottom: -25px;
list-style: none;
display: block;
text-align: center;
padding: 0;
margin: 0;
width: 100%;
li {
position: relative;
display: inline-block;
height: 20px;
width: 20px;
margin: 0 5px;
padding: 0;
cursor: pointer;
button {
border: 0;
background: transparent;
display: block;
height: 20px;
width: 20px;
outline: none;
line-height: 0px;
font-size: 0px;
color: transparent;
padding: 5px;
cursor: pointer;
&:hover, &:focus {
outline: none;
&:before {
opacity: @slick-opacity-on-hover;
}
}
&:before {
position: absolute;
top: 0;
left: 0;
content: @slick-dot-character;
width: 20px;
height: 20px;
font-family: @slick-font-family;
font-size: @slick-dot-size;
line-height: 20px;
text-align: center;
color: @slick-dot-color;
opacity: @slick-opacity-not-active;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
}
&.slick-active button:before {
color: @slick-dot-color-active;
opacity: @slick-opacity-default;
}
}
}

View file

@ -0,0 +1,194 @@
@charset "UTF-8";
// Default Variables
// Slick icon entity codes outputs the following
// "\2190" outputs ascii character ""
// "\2192" outputs ascii character ""
// "\2022" outputs ascii character ""
$slick-font-path: "./fonts/" !default;
$slick-font-family: "slick" !default;
$slick-loader-path: "./" !default;
$slick-arrow-color: white !default;
$slick-dot-color: black !default;
$slick-dot-color-active: $slick-dot-color !default;
$slick-prev-character: "\2190" !default;
$slick-next-character: "\2192" !default;
$slick-dot-character: "\2022" !default;
$slick-dot-size: 6px !default;
$slick-opacity-default: 0.75 !default;
$slick-opacity-on-hover: 1 !default;
$slick-opacity-not-active: 0.25 !default;
@function slick-image-url($url) {
@if function-exists(image-url) {
@return image-url($url);
}
@else {
@return url($slick-loader-path + $url);
}
}
@function slick-font-url($url) {
@if function-exists(font-url) {
@return font-url($url);
}
@else {
@return url($slick-font-path + $url);
}
}
/* Slider */
.slick-list {
.slick-loading & {
background: #fff slick-image-url("ajax-loader.gif") center center no-repeat;
}
}
/* Icons */
@if $slick-font-family == "slick" {
@font-face {
font-family: "slick";
src: slick-font-url("slick.eot");
src: slick-font-url("slick.eot?#iefix") format("embedded-opentype"), slick-font-url("slick.woff") format("woff"), slick-font-url("slick.ttf") format("truetype"), slick-font-url("slick.svg#slick") format("svg");
font-weight: normal;
font-style: normal;
}
}
/* Arrows */
.slick-prev,
.slick-next {
position: absolute;
display: block;
height: 20px;
width: 20px;
line-height: 0px;
font-size: 0px;
cursor: pointer;
background: transparent;
color: transparent;
top: 50%;
-webkit-transform: translate(0, -50%);
-ms-transform: translate(0, -50%);
transform: translate(0, -50%);
padding: 0;
border: none;
outline: none;
&:hover, &:focus {
outline: none;
background: transparent;
color: transparent;
&:before {
opacity: $slick-opacity-on-hover;
}
}
&.slick-disabled:before {
opacity: $slick-opacity-not-active;
}
&:before {
font-family: $slick-font-family;
font-size: 20px;
line-height: 1;
color: $slick-arrow-color;
opacity: $slick-opacity-default;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
}
.slick-prev {
left: -25px;
[dir="rtl"] & {
left: auto;
right: -25px;
}
&:before {
content: $slick-prev-character;
[dir="rtl"] & {
content: $slick-next-character;
}
}
}
.slick-next {
right: -25px;
[dir="rtl"] & {
left: -25px;
right: auto;
}
&:before {
content: $slick-next-character;
[dir="rtl"] & {
content: $slick-prev-character;
}
}
}
/* Dots */
.slick-dotted.slick-slider {
margin-bottom: 30px;
}
.slick-dots {
position: absolute;
bottom: -25px;
list-style: none;
display: block;
text-align: center;
padding: 0;
margin: 0;
width: 100%;
li {
position: relative;
display: inline-block;
height: 20px;
width: 20px;
margin: 0 5px;
padding: 0;
cursor: pointer;
button {
border: 0;
background: transparent;
display: block;
height: 20px;
width: 20px;
outline: none;
line-height: 0px;
font-size: 0px;
color: transparent;
padding: 5px;
cursor: pointer;
&:hover, &:focus {
outline: none;
&:before {
opacity: $slick-opacity-on-hover;
}
}
&:before {
position: absolute;
top: 0;
left: 0;
content: $slick-dot-character;
width: 20px;
height: 20px;
font-family: $slick-font-family;
font-size: $slick-dot-size;
line-height: 20px;
text-align: center;
color: $slick-dot-color;
opacity: $slick-opacity-not-active;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
}
&.slick-active button:before {
color: $slick-dot-color-active;
opacity: $slick-opacity-default;
}
}
}

View file

@ -0,0 +1,119 @@
/* Slider */
.slick-slider
{
position: relative;
display: block;
box-sizing: border-box;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-touch-callout: none;
-khtml-user-select: none;
-ms-touch-action: pan-y;
touch-action: pan-y;
-webkit-tap-highlight-color: transparent;
}
.slick-list
{
position: relative;
display: block;
overflow: hidden;
margin: 0;
padding: 0;
}
.slick-list:focus
{
outline: none;
}
.slick-list.dragging
{
cursor: pointer;
cursor: hand;
}
.slick-slider .slick-track,
.slick-slider .slick-list
{
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
-o-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
.slick-track
{
position: relative;
top: 0;
left: 0;
display: block;
margin-left: auto;
margin-right: auto;
}
.slick-track:before,
.slick-track:after
{
display: table;
content: '';
}
.slick-track:after
{
clear: both;
}
.slick-loading .slick-track
{
visibility: hidden;
}
.slick-slide
{
display: none;
float: left;
height: 100%;
min-height: 1px;
}
[dir='rtl'] .slick-slide
{
float: right;
}
.slick-slide img
{
display: block;
}
.slick-slide.slick-loading img
{
display: none;
}
.slick-slide.dragging img
{
pointer-events: none;
}
.slick-initialized .slick-slide
{
display: block;
}
.slick-loading .slick-slide
{
visibility: hidden;
}
.slick-vertical .slick-slide
{
display: block;
height: auto;
border: 1px solid transparent;
}
.slick-arrow.slick-hidden {
display: none;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,100 @@
/* Slider */
.slick-slider {
position: relative;
display: block;
box-sizing: border-box;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-ms-touch-action: pan-y;
touch-action: pan-y;
-webkit-tap-highlight-color: transparent;
}
.slick-list {
position: relative;
overflow: hidden;
display: block;
margin: 0;
padding: 0;
&:focus {
outline: none;
}
&.dragging {
cursor: pointer;
cursor: hand;
}
}
.slick-slider .slick-track,
.slick-slider .slick-list {
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
-o-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
.slick-track {
position: relative;
left: 0;
top: 0;
display: block;
margin-left: auto;
margin-right: auto;
&:before,
&:after {
content: "";
display: table;
}
&:after {
clear: both;
}
.slick-loading & {
visibility: hidden;
}
}
.slick-slide {
float: left;
height: 100%;
min-height: 1px;
[dir="rtl"] & {
float: right;
}
img {
display: block;
}
&.slick-loading img {
display: none;
}
display: none;
&.dragging img {
pointer-events: none;
}
.slick-initialized & {
display: block;
}
.slick-loading & {
visibility: hidden;
}
.slick-vertical & {
display: block;
height: auto;
border: 1px solid transparent;
}
}
.slick-arrow.slick-hidden {
display: none;
}

1
kanga.world/assets/slick/slick.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,100 @@
/* Slider */
.slick-slider {
position: relative;
display: block;
box-sizing: border-box;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-ms-touch-action: pan-y;
touch-action: pan-y;
-webkit-tap-highlight-color: transparent;
}
.slick-list {
position: relative;
overflow: hidden;
display: block;
margin: 0;
padding: 0;
&:focus {
outline: none;
}
&.dragging {
cursor: pointer;
cursor: hand;
}
}
.slick-slider .slick-track,
.slick-slider .slick-list {
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
-o-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
.slick-track {
position: relative;
left: 0;
top: 0;
display: block;
margin-left: auto;
margin-right: auto;
&:before,
&:after {
content: "";
display: table;
}
&:after {
clear: both;
}
.slick-loading & {
visibility: hidden;
}
}
.slick-slide {
float: left;
height: 100%;
min-height: 1px;
[dir="rtl"] & {
float: right;
}
img {
display: block;
}
&.slick-loading img {
display: none;
}
display: none;
&.dragging img {
pointer-events: none;
}
.slick-initialized & {
display: block;
}
.slick-loading & {
visibility: hidden;
}
.slick-vertical & {
display: block;
height: auto;
border: 1px solid transparent;
}
}
.slick-arrow.slick-hidden {
display: none;
}

View file

@ -0,0 +1,9 @@
Title: Error
----
Redirect: /
----
Target: self

BIN
kanga.world/content/home/comingsoon.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1 @@
Sort: 2

View file

@ -0,0 +1,10 @@
Title: Welcome!
----
Text:
(image: kangaworld.png imgclass:imagecenter width: 400)
(image: onlinegamingnetwork.png imgclass:imagecenter width: 400)
(image: kangaworldlogo.png imgclass:imagecenter width: 400)
(image: comingsoon.png imgclass:imagecenter width: 400)

BIN
kanga.world/content/home/kanga-original.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1 @@
Sort: 1

BIN
kanga.world/content/home/kangaworld.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1 @@
Sort: 2

BIN
kanga.world/content/home/kangaworldlogo.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
kanga.world/content/home/onlinegamingnetwork.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1 @@
Sort: 2

View file

@ -0,0 +1 @@
Title: Kanga World

View file

View file

@ -0,0 +1,8 @@
title: Default Page
preset: page
fields:
text:
label: Text
type: textarea
size: large

View file

@ -0,0 +1,19 @@
title: Redirect
icon: url
options:
changeTemplate: redirect
sections:
content:
type: fields
fields:
redirect:
# Not using "url" below because we need to enter things like '/' for a URL.
type: text
# target:
# type: radio
# default: self
# options:
# self: Opens the linked document in the same frame as it was clicked
# blank: Opens the linked document in a new window or tab
# parent: Opens the linked document in the parent frame
# top: Opens the linked document in the full body of the window

View file

@ -0,0 +1,2 @@
preset: pages
unlisted: true

View file

@ -0,0 +1 @@
title: User

0
kanga.world/site/cache/index.html vendored Normal file
View file

View file

@ -0,0 +1,27 @@
<?php
return [
'debug' => true,
'markdown' => [
'extra' => false
],
// For: https://github.com/getkirby/kql
'api' => [
'basicAuth' => true,
'allowInsecure' => true
],
'hooks' => [
// See: https://getkirby.com/docs/cookbook/extensions/subpage-builder
'route:after' => function ($route, $path, $method) {
$uid = explode('/', $path);
$uid = end($uid);
$uid = str_replace('+', '/', $uid);
$page = kirby()->page($uid);
if ($page && $page->children()->isEmpty()) {
buildPageTree($page);
}
}
]
];

View file

@ -0,0 +1,25 @@
<?php
Kirby::plugin('kirby/columns', [
'hooks' => [
'kirbytags:before' => function ($text, array $data = []) {
$text = preg_replace_callback('!\(columns(…|\.{3})\)(.*?)\((…|\.{3})columns\)!is', function($matches) use($text, $data) {
$columns = preg_split('!(\n|\r\n)\+{4}\s+(\n|\r\n)!', $matches[2]);
$html = [];
$classItem = $this->option('kirby.columns.item', 'column');
$classContainer = $this->option('kirby.columns.container', 'columns');
foreach ($columns as $column) {
$html[] = '<div class="' . $classItem . '">' . $this->kirbytext($column, $data) . '</div>';
}
return '<div class="' . $classContainer . '">' . implode($html) . '</div>';
}, $text);
return $text;
}
]
]);

View file

@ -0,0 +1,75 @@
<?php
Kirby::plugin('kangaroopunch/download-kirbytag', [
'routes' => function() {
return [
[
'pattern' => 'download/(:any)/(:any)',
'action' => function($sourcepage, $filerequested) {
// Unmuddle the page ID that called us.
$slug = str_rot13(urldecode($sourcepage));
$slug = str_replace('|', '/', $slug);
// Get page object.
$page = kirby()->api()->page($slug);
// Find the current download count.
$file = $page->file($filerequested);
$content = $file->content();
if ($content->has('downloads')) {
$count = $content->get('downloads')->toInt();
} else {
// Initialize counter.
$count = 0;
}
// Update download count.
$count++;
$file->update([ 'downloads' => $count ]);
// Send file to user.
return $file;
}
]
];
},
'tags' => [
'download' => [
'attr' => [
'desc'
],
'html' => function($tag) {
// Did we get a valid file?
$file = $tag->file($tag->value());
if (!$file === true) {
return '<div class="downloadlinkerror">ERROR: Cannot locate "' . $tag->value() . '"!</div>';
}
// Ensure we're using the proper blueprint.
//$file->update([ 'template' => 'download' ]);
// Did they provide a description?
if (is_null($tag->desc) === true) {
// No. Does the file itself have one?
$desc = $file->content()->get('description')->value();
if (is_null($desc) || strlen($desc) == 0) {
// Nope. Use the filename.
$desc = $tag->value();
}
} else {
// Yep. Use the provided description.
$desc = $tag->desc;
}
// Find pretty file size.
$units = array('B', 'KB', 'MB', 'GB', 'TB');
$bytes = max($file->size(), 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= pow(1024, $pow);
$size = round($bytes, 2) . ' ' . $units[$pow];
// Muddle up the page slug a bit to discourage direct linking to the file.
$slug = str_replace('/', '|', $tag->parent()->id());
$slug = esc(str_rot13($slug), 'url');
// Send the link.
return '<a href="/download/' . $slug . '/' . esc($tag->value(), 'url') . '" class="downloadlink">' . $desc . ' (' . $size . ')</a>';
}
]
]
]);

View file

@ -0,0 +1,97 @@
<?php
Kirby::plugin('kangaroopunch/image-kirbytag', [
'tags' => [
'image' => [
'attr' => [
'alt',
'caption',
'class',
'height',
'imgclass',
'link',
'linkclass',
'rel',
'target',
'title',
'width'
],
'html' => function ($tag) {
if ($tag->file = $tag->file($tag->value)) {
$tag->src = $tag->file->url();
$tag->alt = $tag->alt ?? $tag->file->alt()->or(' ')->value();
$tag->title = $tag->title ?? $tag->file->title()->value();
$tag->caption = $tag->caption ?? $tag->file->caption()->value();
} else {
$tag->src = Url::to($tag->value);
}
$link = function ($img) use ($tag) {
if (empty($tag->link) === true) {
return $img;
}
if ($link = $tag->file($tag->link)) {
$link = $link->url();
} else {
$link = $tag->link === 'self' ? $tag->src : $tag->link;
}
return Html::a($link, [$img], [
'rel' => $tag->rel,
'class' => $tag->linkclass,
'target' => $tag->target
]);
};
// Both sizes provided.
if (is_null($tag->width) && is_null($tag->height)) {
// Update URL & generate proper sized image.
$tag->src = $tag->file($tag->value)->resize($tag->width, $tag->height)->url();
} else {
// Width provided.
if (is_null($tag->height)) {
// Scale height by ratio.
$tag->height = floor($tag->width() / $tag->file($tag->value)->dimensions()->ratio());
// Update URL & generate proper sized image.
$tag->src = $tag->file($tag->value)->resize($tag->width, $tag->height)->url();
} else {
// Height provided.
if (is_null($tag->width)) {
// Scale width by ratio.
$tag->width = floor($tag->height() * $tag->file($tag->value)->dimensions()->ratio());
// Update URL & generate proper sized image.
$tag->src = $tag->file($tag->value)->resize($tag->width, $tag->height)->url();
}
}
}
$image = Html::img($tag->src, [
'width' => $tag->width,
'height' => $tag->height,
'class' => $tag->imgclass,
'title' => $tag->title,
'alt' => $tag->alt ?? ' '
]);
if ($tag->kirby()->option('kirbytext.image.figure', true) === false) {
return $link($image);
}
// render KirbyText in caption
if ($tag->caption) {
$tag->caption = [$tag->kirby()->kirbytext($tag->caption, [], true)];
}
return Html::figure([ $link($image) ], $tag->caption, [
'class' => $tag->class
]);
}
]
]
]);

View file

@ -0,0 +1,62 @@
<?php
Kirby::plugin('kangaroopunch/kangaworld-integration', [
'api' => [
'routes' => [
[
'pattern' => 'kp/kangaworld/v1',
'method' => 'POST',
'action' => function() {
$response = array();
$response['result'] = 'false';
$response['reason'] = 'Unknown error.';
switch (get('command')) {
case 'USER_CREATE':
try {
kirby()->users()->create([
'name' => get('name'),
'email' => get('email'),
'password' => get('password'),
'language' => 'en',
'role' => 'user'
]);
$response['result'] = 'true';
$response['reason'] = 'User created.';
} catch(Exception $e) {
$response['reason'] = $e->getMessage();
}
break;
case 'USER_GET':
try {
$user = kirby()->users()->findByKey(get('email'));
//$response['userraw'] = dump($user);
$response['name'] = $user->username();
$response['email'] = $user->email();
$response['password'] = $user->password();
$response['language'] = $user->language();
$response['role'] = $user->role()->id();
$response['result'] = 'true';
$response['reason'] = 'User found.';
} catch(Exception $e) {
$response['reason'] = $e->getMessage();
}
break;
default:
$response['reason'] = 'Invalid command.';
break;
}
return $response;
}
]
]
]
]);

Some files were not shown because too many files have changed in this diff Show more