function cmdline()
http://turusuke.hatenablog.com/entry/2012/10/17/php-routing
を見て、URLを使ったルーティング処理を
$requestDATA = cmdline();
print_r($requestDATA);
exit;
function cmdline() {
$str = str_replace("\0", "", $_SERVER['REQUEST_URI']);
$str = trim($str, "\/");
$data = explode("/", $str);
return $data;
}
ってPHPで作った。それで
Array ( [0] => category [1] => food )
となる
C++とかのコマンドライン引数の取得方法と同じですね。などなど、プログラムを作っている
Very Light Weight Frame work "Typon" proto type.
今、PHPでウェブのプログラムを作っているけど、作っているライブラリがコンパクト過ぎて。他の機能を仮組みで作って、テストもデバッグもしてないけれど、見せた方が面白そうなので見せてみる
動作テストもしてないので、このフレームワークを使わないで! 事故っても責任は取りませんよ
でも、これらの機能のみでもPHPのプログラムを動かせるよな、と実験的な試みです
ちゃんとテストできて確かめて動かせるなら、githubで上げ直しますので
とりあえず、ドメインなプログラミングなMVPパターンで組んでいて、HTMLテンプレートはSmartyで、パスワードのハッシュなどは別にLOGINドメインを作ってて、そこに置いてます
以上、暇潰し報告でした
------- 以下、ソースコード -------
<?php
// ヌルバイトアタック処理
function sanitizer($array) {
if (is_array($array)) {
return array_map('sanitizer', $array);
}
return str_replace("\0", "", $array);
}
$_POST = sanitizer($_POST);
$_COOKIE = sanitizer($_COOKIE);
$exec = str_replace("\0", "", $_GET['exec']);
$_GET = array(); // Delete gets.
// mb Setting.
mb_language("Japanese");
mb_internal_encoding("UTF-8");
// セッションIDリセット
session_start();
session_regenerate_id(true);
// プレゼンテーターネームチェック
if ($exec == "") {
// "/"なのでindexを実行
$exec = "index";
} elseif (!preg_match('/\A[a-zA-Z0-9\-\_]+\z/i', $exec)) {
// 不正アクセスなのでログアウト
STD::logout();
exit;
}
// プレゼンテーターがあるか?
if (! file_exists("frames/".$exec.".frame")) {
if ($exec == "index") {
// error.
echo("Error: No thing [index].");
exit;
} else {
// 不正アクセスなのでログアウト
STD::logout();
exit;
}
}
// 実行
require_once("frames/".$exec.".frame");
exit;
class STR {
// 全角トリム
function mbTrim($str) {
$str = self::toUtf8($str);
$str = preg_replace('/[\r\n]/u', '', $str);
return preg_replace('/\A[\p{C}\p{Z}]++|[\p{C}\p{Z}]++\z/u', '', $str);
}
// UTF変換
function toUtf8($str) {
return mb_convert_encoding($str, "UTF-8", "auto");
}
// Nullバイト削除
function nullDelete($str) {
return str_replace("\0", "", $str);
}
// <br>変換
function toBr($str) {
$str = preg_replace('/\n\r/u', '\r\n', $str);
$str = preg_replace('/\r\n/u', '\r', $str);
$str = preg_replace('/\n/u', '\r', $str);
$str = preg_replace('/\r/u', '<br>', $str);
return $str;
}
function toRn($str) {
$str = preg_replace('/<br>/u', '\r\n', $str);
return $str;
}
function len($str) {
return mb_strlen($str);
}
function empty($str) {
return empty($str);
}
function htmlConvert($str) {
return htmlspecialchars($str, ENT_QUOTES);
}
function checkUrl($str) {
return preg_match('/\Ahttps?(:\/\/[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+)\z/', $str);
}
function checkPassword($str) {
return preg_match('/\A[a-zA-Z0-9]+\z/i', $str);
}
function checkNumber($str) {
return preg_match('/\A[0-9]+\z/i', $str);
}
function checkMail($str) {
// https://gist.github.com/felds/864067
$regexp = '/^(?:[a-z0-9!#$%\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}'.
'~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\['.
'\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-'.
'9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-'.
'9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?'.
'|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-' .
'\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/';
return preg_match($regexp, $str);
}
}
class STD {
// Loginセーブ
function loginSave($userId) {
$_SESSION['id'] = $userId;
self::uidMake($userId);
}
// Loginチェック
function loginCheck() {
if (! uidCheck()) {
self::logout();
exit;
}
}
// ログアウト
function logout() {
$_SESSION = array();
session_destroy();
header("Location: ./index");
}
// uID.
function uidMake($user_id) {
$_SESSION['uid'] = self::uidGet($user_id);
return $_SESSION['uid'];
}
function uidCheck() {
if (empty($_SESSION['uid']) || empty($_SESSION['id'])) {
return false;
} elseif (self::uidGet($_SESSION['id']) == $_SESSION['uid']) {
return true;
}
return false;
}
function uidGet($user_id) {
$str = $user_id."nje4HDa"; // ジャミング
// ブラウザー情報など
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$str .= $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$str .= $_SERVER['REMOTE_ADDR'];
}
$str .= $_SERVER['HTTP_USER_AGENT'];
// ジャミング
$str .= "nje4HDa";
// 暗号化
$str = crypt($str, '$2y$07$ZvnOUqcYywVVmukaNHFVoP$');
$uId = hash_hmac("haval160,4", $str, "heJH6hfHIh4JNHJe");
return $uId;
}
// time.
function timeSectime($y, $mon, $d, $a, $m) {
return mktime($a, $m, 0, $mon, $d, $y);
}
function timeDateRss($sectime) {
return date(DATE_RFC822, $sectime);
}
function timeDate($sectime) {
return getdate($sectime);
}
}
class DB {
var $db;
// mysql
function make() {
if (empty($this->db)) {
$this->db = mysqli_connect('localhost', 'my_user', 'my_password', 'my_db');
}
return $this->db;
}
function get() {
return self::make();
}
function error() {
$str = "";
if($this->db->connect_errno) {
$str = $this->db->connect_errno . ' : ' . $this->db->connect_error;
}
return $str;
}
function close() {
mysqli_close($this->db);
}
// JSON.
function jsonWrite($data, $array) {
$file = "data/{$data}.data";
if (! file_exists($file)) {
return false;
}
if (file_put_contents($file, serialize($array)) == false) {
return false;
}
return true;
}
function jsonRead($data) {
$json = array();
$file = "data/{$data}.data";
if (! file_exists($file)) {
return $json;
}
$json = unserialize(file_get_contents($file));
return $json;
}
}
class MAIL {
function send($toAdrs, $fromAdrs, $subject, $body) {
if (!STR::checkMail($toAdrs)) {
return false;
} elseif (!STR::checkMail($fromAdrs)) {
return false;
}
$header = "From: $fromAdrs\nReply-To: $fromAdrs\n";
return mb_send_mail($toAdrs, $subject, $body, $header);
}
}
class SONOTA {
// Make Crypt's Salt.
function makeSalt() {
$char = array_merge(range('a', 'z'), range('A', 'Z'), array('.', '/'));
$salt = "";
for ($i = 0; $i < 22; $i++) {
$salt .= $char[mt_rand(0, count($char) - 1)];
}
return $salt;
}
}
?>
PHPでプログラムを作っている
最近、PHPでプログラムをしている
スマホのゲームのサーバーは、まだ、golangではなく、PHPで出来ているそうなので、久々、PHPでプログラムを作って、少しサーバーのプログラムの作り方を覚え直そうと思ったので
まぁ、それほどPHPのプログラムの作り方変化はなかったので、どこまでしょぼく、と言うかスマートに作ろうと思ってたのですけど、データのバリテーションの部分は、(バグが残っているかも知れない)仮組みの状態で
<?php
class STR {
// 全角トリム
function mbTrim($str) {
$str = self::toUtf8($str);
$str = preg_replace('/[\r\n]/u', '', $str);
return preg_replace('/\A[\p{C}\p{Z}]++|[\p{C}\p{Z}]++\z/u', '', $str);
}
// UTF変換
function toUtf8($str) {
return mb_convert_encoding($str, "UTF-8", "auto");
}
// <br>変換
function toBr($str) {
$str = preg_replace('/\n\r/u', '\r\n', $str);
$str = preg_replace('/\r\n/u', '\r', $str);
$str = preg_replace('/\n/u', '\r', $str);
$str = preg_replace('/\r/u', '<br>', $str);
return $str;
}
function toRn($str) {
$str = preg_replace('/<br>/u', '\r\n', $str);
return $str;
}
function len($str) {
return mb_strlen($str);
}
function empty($str) {
if ($str == "") {
return true;
}
return false;
}
function htmlConvert($str) {
return htmlspecialchars($str, ENT_QUOTES);
}
function url($str) {
return preg_match('/\Ahttps?(:\/\/[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+)\z/', $str);
}
function password($str) {
return preg_match('/\A[a-zA-Z0-9]+\z/i', $str);
}
function number($str) {
return preg_match('/\A[0-9]+\z/i', $str);
}
function mail($str) {
// https://gist.github.com/felds/864067
$regexp = '/^(?:[a-z0-9!#$%\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}'.
'~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\['.
'\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-'.
'9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-'.
'9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?'.
'|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-' .
'\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/';
return preg_match($regexp, $str);
}
}
?>
って、クラスをネームスペース的に組んで、
$str = STR::mbTrim($_POST['station']);
$str = STR::htmlConvert($str);
$data['station'] = $str;
if (STR::empty($str)) {
$error['error'] = 1;
$error['station'] = "ポッドキャストの名前がありません";
} elseif (STR::len($str) > 100) {
$error['error'] = 1;
$error['station'] = "ポッドキャストの名前が100文字以上です";
}
って、elseifでバリデーションを羅列するプログラムの作り方をしているけど、
バリデーションの条件で使う、文字列データのチェックの関数があればelseifを使ってバリデーションをチェック出来るので、PHPの標準関数でバリデーション関数があれば、普通にBASICな作り方でウェブのアプリが作れるのでは?
って思った
標準のfilter関数は使えないんですよね。URLのチェックでスペースや<を調べてないので、正規表現で調べないといけない。それらのバリデーションが標準であれば、普通にウェブのプラグラムが作れるのに
ウェブのプログラムは基本、データは文字列変数で、php5では型も無く、基本、文字列変数なので、ウェブのプログラムはほとんど文字列変数の処理を作るのが仕事になるよなと思いながら作っていた
あ、unsetの処理は$hoge==""はやめて、empty()へ変更しておこう
games.pdbrec.com業務用連絡20190504
games.pdbrec.com業務連絡20190414
games.pdbrec.com業務連絡 20190410
とりあえず、
-------
package gameos
import (
"fmt"
"os"
"github.com/veandco/go-sdl2/sdl"
"github.com/veandco/go-sdl2/img"
)
var texture []*sdl.Texture // スライス化
func ImageMake (no int) {
texture = make([]*sdl.Texture, no)
}
func ImageDelete() {
for i := range texture {
if texture[i] != nil {
texture[i].Destroy()
}
}
}
func ImageLoad (no int, imageName string) {
image, err := img.Load(imageName)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to load PNG: %s\n", err)
os.Exit(3)
}
defer image.Free()
if texture[no] != nil {
texture[no].Destroy()
}
texture[no], err = renderer.CreateTextureFromSurface(image)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to create texture: %s\n", err)
os.Exit(4)
}
}
func ImageCopy(no int, x int32, y int32, xx int32, yy int32,
mx int32, my int32, mxx int32, myy int32) {
renderer.Copy(texture[no], &sdl.Rect{x, y, xx, yy}, &sdl.Rect{mx, my, mxx, myy})
}
func ImageCopyFill(no int, x int32, y int32, xx int32, yy int32) {
renderer.Copy(texture[no], nil, &sdl.Rect{x, y, xx, yy})
}
-------
Go言語でSDLで画像処理を行うライブラリ
Go言語はメモリを押さえてから処理を行うのが普通なので、makeでtextureポインタのスライスのメモリを確保して、スライスへ読み込んで使っている
押さえているスライスのメモリを超えてPNG画像を読み込んでもGo言語ではエラーにはならないはず。でも、メモリの押さえ直しとガベージコレクタで処理速度が遅くなるはず
SDLの画像処理は基本的にはCopy処理のみなので、MSXのSCREEN5的な処理でゲームを作る。追加出来るとしたらスプライトシート処理だろうな
WASMの準備も少し進めた
games.pdbrec.com業務連絡 20190408
games.pdbrec.com業務連絡 20190405
とりあえず、Go言語でのFPS処理は
-------
package gameos
import "time"
var fpsTimeThen int64 = 0
var fpsTimeNow int64 = 0
func vsyncNowTime() int64 {
return time.Now().UnixNano()
}
func VsyncInit() {
fpsTimeThen = vsyncNowTime()
}
func Vsync() {
if fpsTimeThen == 0 {
VsyncInit()
} else {
// Fps Time.
var a int64
a = 0
if fpsCount % 3 == 0 {
a = 1
}
fpsTimeNow = vsyncNowTime()
var fpsWait int64
fpsWait = 16666667 - (fpsTimeNow - fpsTimeThen - a)
// Fps Wait.
if fpsWait > 0 {
time.Sleep(time.Duration(fpsWait))
}
// Reset.
fpsTimeThen = vsyncNowTime()
}
}
-------
な感じ
GolangのsleepはNano秒単位なので、それに合わせて数値も決めています
ゲームのパターンってのがあって、なるべく、packageなライブラリの形でゲームのプログラムのパターンをまとめたいので。プチコンのVsyncなライブラリを作ってみました
とりあえず、プログラムの実装は続いてます
games.pdbrec.com業務連絡 20190401
お久しぶりです
とりあえず、phaser3でのゲーム制作ですが、モード絡みのバグが残っていて動けない
ゲームのモードを移動しすぎるとゲームが動かなくなる
Phaser3のゲームの作り方のウェブなら、この人、「エマニエル先生」のウェブのプログラムでも、同じ状態を回避する技があって、動くには動くけど、タイトル画面には戻らないでリプレイする回避方法で、それだとモードが選べなくなるので、いろいろと不便なので
Go言語でのWindows版の制作を開始します
Phaser3のバグが無くなれば、そちらの方も平行作業で続けますが
とりあえず、Go言語、久々に使ってみたら
・npmなパッケージシステムが増えていた
・キャッシュを使った差分コンパイル対応でコンパイルが速い
と、使いやすい。で、とりあえず、XorShiftのライブラリを
-------
package gameos
import "time"
var gameosXorshiftSeed uint32 = 3141592653 // Dummy Seed.
func XorshiftSeed() {
gameosXorshiftSeed = 0
// Seedが0なら再設定
for gameosXorshiftSeed == 0 {
gameosXorshiftSeed = uint32(time.Now().UnixNano())
}
}
func Xorshift() int {
y := gameosXorshiftSeed
y = y ^ (y << 13)
y = y ^ (y >> 17)
y = y ^ (y << 5)
gameosXorshiftSeed = y
return int(y)
}
-------
と作り替え
簡単なテストを行って、ちゃんと動いているのを確認した
あ、Go言語でSDLを使うのに、変な構造体とかを使う人が多いけど、SDLを扱うpackageを作って、そのpackageでSDLなウインドウを作ったら、普通に、そのpackage内でSDLが使えるので
Go言語で普通にゲーム作れますよ!
とりあえず、嘘ではない業務連絡でした