From 1c278f92cd061c4e59abcd1195dbf2575fc71642 Mon Sep 17 00:00:00 2001 From: Imam Syahid Hudzaifah Date: Tue, 12 Aug 2025 15:00:19 +0700 Subject: [PATCH] fix Aiko missing --- .gitignore | 26 + Aiko/Aiko/Framework/Core.php | 828 +++++++++++ Aiko/Aiko/Framework/Core.php:Zone.Identifier | 3 + Aiko/Aiko/Framework/Database.php | 184 +++ .../Framework/Database.php:Zone.Identifier | 3 + Aiko/Aiko/Framework/Error.php | 11 + Aiko/Aiko/Framework/Error.php:Zone.Identifier | 3 + Aiko/Aiko/Framework/Init.php | 126 ++ Aiko/Aiko/Framework/Init.php:Zone.Identifier | 3 + Aiko/Aiko/Framework/Model.php | 235 +++ Aiko/Aiko/Framework/Model.php:Zone.Identifier | 3 + Aiko/Aiko/Framework/Template.php | 107 ++ .../Framework/Template.php:Zone.Identifier | 3 + Aiko/Aiko/Framework/Token.php | 353 +++++ Aiko/Aiko/Framework/Token.php:Zone.Identifier | 3 + Aiko/Aiko/Includes/App.config.php | 33 + .../Includes/App.config.php:Zone.Identifier | 3 + Aiko/Aiko/Includes/config.php | 169 +++ Aiko/Aiko/Includes/config.php:Zone.Identifier | 3 + Aiko/Aiko/Includes/db.config.php | 99 ++ .../Includes/db.config.php:Zone.Identifier | 3 + Aiko/Aiko/Includes/db.config.php_encrypt | 2 + .../db.config.php_encrypt:Zone.Identifier | 3 + Aiko/Aiko/Includes/db.config__encryt.php_bck | 2 + .../db.config__encryt.php_bck:Zone.Identifier | 3 + Aiko/Aiko/Includes/index.html | 10 + Aiko/Aiko/Includes/index.html:Zone.Identifier | 3 + Aiko/Aiko/Includes/ipconfig.php | 11 + .../Includes/ipconfig.php:Zone.Identifier | 3 + Aiko/Aiko/Includes/jsonpath.php | 111 ++ .../Includes/jsonpath.php:Zone.Identifier | 3 + .../Libs/ApprovalRequest/ApprovalRequest.php | 384 +++++ .../ApprovalRequest.php:Zone.Identifier | 3 + .../ApprovalRequest/ApprovalRequestTrait.php | 648 ++++++++ .../ApprovalRequestTrait.php:Zone.Identifier | 3 + .../ApprovalRequest/HasApprovalRequest.php | 59 + .../HasApprovalRequest.php:Zone.Identifier | 3 + .../ApprovalRequest/WithApprovalRequest.php | 274 ++++ .../WithApprovalRequest.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/Debug.php | 105 ++ Aiko/Aiko/Libs/Debug.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/FCM.php | 104 ++ Aiko/Aiko/Libs/FCM.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/GeoTz.php | 89 ++ Aiko/Aiko/Libs/GeoTz.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/Http.php | 346 +++++ Aiko/Aiko/Libs/Http.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/Log.php | 143 ++ Aiko/Aiko/Libs/Log.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/LogAccess.php | 85 ++ Aiko/Aiko/Libs/LogAccess.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/Logdbtrait.php | 36 + Aiko/Aiko/Libs/Logdbtrait.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/MyFpdi.php | 16 + Aiko/Aiko/Libs/MyFpdi.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/MyPdf.php | 1302 +++++++++++++++++ Aiko/Aiko/Libs/MyPdf.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/Mycrypt.php | 35 + Aiko/Aiko/Libs/Mycrypt.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/Query.php | 35 + Aiko/Aiko/Libs/Query.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/QueryParam.php | 41 + Aiko/Aiko/Libs/QueryParam.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/QueryProcess.php | 24 + .../Libs/QueryProcess.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/Session.php | 176 +++ Aiko/Aiko/Libs/Session.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/Storage.php | 134 ++ Aiko/Aiko/Libs/Storage.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/Token.php | 349 +++++ Aiko/Aiko/Libs/Token.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/TokenSanitation.php | 87 ++ .../Libs/TokenSanitation.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/Trait.php | 50 + Aiko/Aiko/Libs/Trait.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/Validator.php | 110 ++ Aiko/Aiko/Libs/Validator.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/ValidatorRule.php | 101 ++ .../Libs/ValidatorRule.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/ValidatorRuleCollection.php | 136 ++ ...alidatorRuleCollection.php:Zone.Identifier | 3 + Aiko/Aiko/Libs/WhatsApp.php | 570 ++++++++ Aiko/Aiko/Libs/WhatsApp.php:Zone.Identifier | 3 + Aiko/Framework/Core.php | 831 +++++++++++ Aiko/Framework/Core.php:Zone.Identifier | 0 .../Core.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Framework/Database.php | 184 +++ Aiko/Framework/Database.php:Zone.Identifier | 0 ...tabase.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Framework/Error.php | 11 + Aiko/Framework/Error.php:Zone.Identifier | 0 .../Error.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Framework/Init.php | 126 ++ Aiko/Framework/Init.php:Zone.Identifier | 0 .../Init.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Framework/Model.php | 235 +++ Aiko/Framework/Model.php:Zone.Identifier | 0 .../Model.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Framework/Template.php | 107 ++ Aiko/Framework/Template.php:Zone.Identifier | 0 ...mplate.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Framework/Token.php | 351 +++++ Aiko/Framework/Token.php:Zone.Identifier | 0 .../Token.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Includes/.DS_Store:Zone.Identifier | 0 .../.DS_Store:Zone.Identifier:Zone.Identifier | 3 + Aiko/Includes/App.config.php | 33 + Aiko/Includes/App.config.php:Zone.Identifier | 0 ...config.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Includes/config.php | 169 +++ Aiko/Includes/config.php:Zone.Identifier | 0 ...config.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Includes/db.config.php | 34 + Aiko/Includes/db.config.php:Zone.Identifier | 0 ...config.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Includes/db.config.php_encrypt | 2 + .../db.config.php_encrypt:Zone.Identifier | 0 ...hp_encrypt:Zone.Identifier:Zone.Identifier | 3 + Aiko/Includes/db.config__encryt.php_bck | 2 + .../db.config__encryt.php_bck:Zone.Identifier | 0 ...yt.php_bck:Zone.Identifier:Zone.Identifier | 3 + Aiko/Includes/index.html | 10 + Aiko/Includes/index.html:Zone.Identifier | 0 ...index.html:Zone.Identifier:Zone.Identifier | 3 + Aiko/Includes/ipconfig.php | 11 + Aiko/Includes/ipconfig.php:Zone.Identifier | 0 ...config.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Includes/jsonpath.php | 111 ++ Aiko/Includes/jsonpath.php:Zone.Identifier | 0 ...onpath.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Libs/ApprovalRequest/ApprovalRequest.php | 384 +++++ .../ApprovalRequest.php:Zone.Identifier | 3 + .../ApprovalRequest/ApprovalRequestTrait.php | 648 ++++++++ .../ApprovalRequestTrait.php:Zone.Identifier | 3 + .../ApprovalRequest/HasApprovalRequest.php | 59 + .../HasApprovalRequest.php:Zone.Identifier | 3 + .../ApprovalRequest/WithApprovalRequest.php | 274 ++++ .../WithApprovalRequest.php:Zone.Identifier | 3 + Aiko/Libs/Debug.php | 105 ++ Aiko/Libs/Debug.php:Zone.Identifier | 0 .../Debug.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Libs/FCM.php | 104 ++ Aiko/Libs/FCM.php:Zone.Identifier | 0 .../FCM.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Libs/GeoTz.php | 89 ++ Aiko/Libs/GeoTz.php:Zone.Identifier | 0 .../GeoTz.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Libs/Http.php | 346 +++++ Aiko/Libs/Http.php:Zone.Identifier | 0 .../Http.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Libs/Log.php | 143 ++ Aiko/Libs/Log.php:Zone.Identifier | 0 .../Log.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Libs/LogAccess.php | 85 ++ Aiko/Libs/LogAccess.php:Zone.Identifier | 0 ...Access.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Libs/Logdbtrait.php | 36 + Aiko/Libs/Logdbtrait.php:Zone.Identifier | 0 ...btrait.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Libs/MyFpdi.php | 16 + Aiko/Libs/MyFpdi.php:Zone.Identifier | 0 ...MyFpdi.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Libs/MyPdf.php | 1302 +++++++++++++++++ Aiko/Libs/MyPdf.php:Zone.Identifier | 0 .../MyPdf.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Libs/Mycrypt.php | 35 + Aiko/Libs/Mycrypt.php:Zone.Identifier | 0 ...ycrypt.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Libs/Query.php | 35 + Aiko/Libs/Query.php:Zone.Identifier | 0 .../Query.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Libs/QueryParam.php | 41 + Aiko/Libs/QueryParam.php:Zone.Identifier | 0 ...yParam.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Libs/QueryProcess.php | 24 + Aiko/Libs/QueryProcess.php:Zone.Identifier | 0 ...rocess.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Libs/Session.php | 176 +++ Aiko/Libs/Session.php:Zone.Identifier | 0 ...ession.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Libs/Storage.php | 140 ++ Aiko/Libs/Storage.php:Zone.Identifier | 0 ...torage.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Libs/Token.php | 349 +++++ Aiko/Libs/Token.php:Zone.Identifier | 0 .../Token.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Libs/TokenSanitation.php | 87 ++ Aiko/Libs/TokenSanitation.php:Zone.Identifier | 0 ...tation.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Libs/Trait.php | 50 + Aiko/Libs/Trait.php:Zone.Identifier | 0 .../Trait.php:Zone.Identifier:Zone.Identifier | 3 + Aiko/Libs/Validator.php | 110 ++ Aiko/Libs/Validator.php:Zone.Identifier | 3 + Aiko/Libs/ValidatorRule.php | 101 ++ Aiko/Libs/ValidatorRule.php:Zone.Identifier | 3 + Aiko/Libs/ValidatorRuleCollection.php | 136 ++ ...alidatorRuleCollection.php:Zone.Identifier | 3 + Aiko/Libs/WhatsApp.php | 570 ++++++++ Aiko/Libs/WhatsApp.php:Zone.Identifier | 0 ...atsApp.php:Zone.Identifier:Zone.Identifier | 3 + Dockerfile.backend | 3 +- apache-config.conf | 6 + be | 2 +- docker-compose.yml | 2 + 205 files changed, 15668 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 Aiko/Aiko/Framework/Core.php create mode 100644 Aiko/Aiko/Framework/Core.php:Zone.Identifier create mode 100644 Aiko/Aiko/Framework/Database.php create mode 100644 Aiko/Aiko/Framework/Database.php:Zone.Identifier create mode 100644 Aiko/Aiko/Framework/Error.php create mode 100644 Aiko/Aiko/Framework/Error.php:Zone.Identifier create mode 100644 Aiko/Aiko/Framework/Init.php create mode 100644 Aiko/Aiko/Framework/Init.php:Zone.Identifier create mode 100644 Aiko/Aiko/Framework/Model.php create mode 100644 Aiko/Aiko/Framework/Model.php:Zone.Identifier create mode 100644 Aiko/Aiko/Framework/Template.php create mode 100644 Aiko/Aiko/Framework/Template.php:Zone.Identifier create mode 100644 Aiko/Aiko/Framework/Token.php create mode 100644 Aiko/Aiko/Framework/Token.php:Zone.Identifier create mode 100644 Aiko/Aiko/Includes/App.config.php create mode 100644 Aiko/Aiko/Includes/App.config.php:Zone.Identifier create mode 100644 Aiko/Aiko/Includes/config.php create mode 100644 Aiko/Aiko/Includes/config.php:Zone.Identifier create mode 100644 Aiko/Aiko/Includes/db.config.php create mode 100644 Aiko/Aiko/Includes/db.config.php:Zone.Identifier create mode 100644 Aiko/Aiko/Includes/db.config.php_encrypt create mode 100644 Aiko/Aiko/Includes/db.config.php_encrypt:Zone.Identifier create mode 100644 Aiko/Aiko/Includes/db.config__encryt.php_bck create mode 100644 Aiko/Aiko/Includes/db.config__encryt.php_bck:Zone.Identifier create mode 100644 Aiko/Aiko/Includes/index.html create mode 100644 Aiko/Aiko/Includes/index.html:Zone.Identifier create mode 100644 Aiko/Aiko/Includes/ipconfig.php create mode 100644 Aiko/Aiko/Includes/ipconfig.php:Zone.Identifier create mode 100644 Aiko/Aiko/Includes/jsonpath.php create mode 100644 Aiko/Aiko/Includes/jsonpath.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/ApprovalRequest/ApprovalRequest.php create mode 100644 Aiko/Aiko/Libs/ApprovalRequest/ApprovalRequest.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/ApprovalRequest/ApprovalRequestTrait.php create mode 100644 Aiko/Aiko/Libs/ApprovalRequest/ApprovalRequestTrait.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/ApprovalRequest/HasApprovalRequest.php create mode 100644 Aiko/Aiko/Libs/ApprovalRequest/HasApprovalRequest.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/ApprovalRequest/WithApprovalRequest.php create mode 100644 Aiko/Aiko/Libs/ApprovalRequest/WithApprovalRequest.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/Debug.php create mode 100644 Aiko/Aiko/Libs/Debug.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/FCM.php create mode 100644 Aiko/Aiko/Libs/FCM.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/GeoTz.php create mode 100644 Aiko/Aiko/Libs/GeoTz.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/Http.php create mode 100644 Aiko/Aiko/Libs/Http.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/Log.php create mode 100644 Aiko/Aiko/Libs/Log.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/LogAccess.php create mode 100644 Aiko/Aiko/Libs/LogAccess.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/Logdbtrait.php create mode 100644 Aiko/Aiko/Libs/Logdbtrait.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/MyFpdi.php create mode 100644 Aiko/Aiko/Libs/MyFpdi.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/MyPdf.php create mode 100644 Aiko/Aiko/Libs/MyPdf.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/Mycrypt.php create mode 100644 Aiko/Aiko/Libs/Mycrypt.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/Query.php create mode 100644 Aiko/Aiko/Libs/Query.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/QueryParam.php create mode 100644 Aiko/Aiko/Libs/QueryParam.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/QueryProcess.php create mode 100644 Aiko/Aiko/Libs/QueryProcess.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/Session.php create mode 100644 Aiko/Aiko/Libs/Session.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/Storage.php create mode 100644 Aiko/Aiko/Libs/Storage.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/Token.php create mode 100644 Aiko/Aiko/Libs/Token.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/TokenSanitation.php create mode 100644 Aiko/Aiko/Libs/TokenSanitation.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/Trait.php create mode 100644 Aiko/Aiko/Libs/Trait.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/Validator.php create mode 100644 Aiko/Aiko/Libs/Validator.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/ValidatorRule.php create mode 100644 Aiko/Aiko/Libs/ValidatorRule.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/ValidatorRuleCollection.php create mode 100644 Aiko/Aiko/Libs/ValidatorRuleCollection.php:Zone.Identifier create mode 100644 Aiko/Aiko/Libs/WhatsApp.php create mode 100644 Aiko/Aiko/Libs/WhatsApp.php:Zone.Identifier create mode 100644 Aiko/Framework/Core.php create mode 100644 Aiko/Framework/Core.php:Zone.Identifier create mode 100644 Aiko/Framework/Core.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Framework/Database.php create mode 100644 Aiko/Framework/Database.php:Zone.Identifier create mode 100644 Aiko/Framework/Database.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Framework/Error.php create mode 100644 Aiko/Framework/Error.php:Zone.Identifier create mode 100644 Aiko/Framework/Error.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Framework/Init.php create mode 100644 Aiko/Framework/Init.php:Zone.Identifier create mode 100644 Aiko/Framework/Init.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Framework/Model.php create mode 100644 Aiko/Framework/Model.php:Zone.Identifier create mode 100644 Aiko/Framework/Model.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Framework/Template.php create mode 100644 Aiko/Framework/Template.php:Zone.Identifier create mode 100644 Aiko/Framework/Template.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Framework/Token.php create mode 100644 Aiko/Framework/Token.php:Zone.Identifier create mode 100644 Aiko/Framework/Token.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Includes/.DS_Store:Zone.Identifier create mode 100644 Aiko/Includes/.DS_Store:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Includes/App.config.php create mode 100644 Aiko/Includes/App.config.php:Zone.Identifier create mode 100644 Aiko/Includes/App.config.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Includes/config.php create mode 100644 Aiko/Includes/config.php:Zone.Identifier create mode 100644 Aiko/Includes/config.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Includes/db.config.php create mode 100644 Aiko/Includes/db.config.php:Zone.Identifier create mode 100644 Aiko/Includes/db.config.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Includes/db.config.php_encrypt create mode 100644 Aiko/Includes/db.config.php_encrypt:Zone.Identifier create mode 100644 Aiko/Includes/db.config.php_encrypt:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Includes/db.config__encryt.php_bck create mode 100644 Aiko/Includes/db.config__encryt.php_bck:Zone.Identifier create mode 100644 Aiko/Includes/db.config__encryt.php_bck:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Includes/index.html create mode 100644 Aiko/Includes/index.html:Zone.Identifier create mode 100644 Aiko/Includes/index.html:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Includes/ipconfig.php create mode 100644 Aiko/Includes/ipconfig.php:Zone.Identifier create mode 100644 Aiko/Includes/ipconfig.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Includes/jsonpath.php create mode 100644 Aiko/Includes/jsonpath.php:Zone.Identifier create mode 100644 Aiko/Includes/jsonpath.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Libs/ApprovalRequest/ApprovalRequest.php create mode 100644 Aiko/Libs/ApprovalRequest/ApprovalRequest.php:Zone.Identifier create mode 100644 Aiko/Libs/ApprovalRequest/ApprovalRequestTrait.php create mode 100644 Aiko/Libs/ApprovalRequest/ApprovalRequestTrait.php:Zone.Identifier create mode 100644 Aiko/Libs/ApprovalRequest/HasApprovalRequest.php create mode 100644 Aiko/Libs/ApprovalRequest/HasApprovalRequest.php:Zone.Identifier create mode 100644 Aiko/Libs/ApprovalRequest/WithApprovalRequest.php create mode 100644 Aiko/Libs/ApprovalRequest/WithApprovalRequest.php:Zone.Identifier create mode 100644 Aiko/Libs/Debug.php create mode 100644 Aiko/Libs/Debug.php:Zone.Identifier create mode 100644 Aiko/Libs/Debug.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Libs/FCM.php create mode 100644 Aiko/Libs/FCM.php:Zone.Identifier create mode 100644 Aiko/Libs/FCM.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Libs/GeoTz.php create mode 100644 Aiko/Libs/GeoTz.php:Zone.Identifier create mode 100644 Aiko/Libs/GeoTz.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Libs/Http.php create mode 100644 Aiko/Libs/Http.php:Zone.Identifier create mode 100644 Aiko/Libs/Http.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Libs/Log.php create mode 100644 Aiko/Libs/Log.php:Zone.Identifier create mode 100644 Aiko/Libs/Log.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Libs/LogAccess.php create mode 100644 Aiko/Libs/LogAccess.php:Zone.Identifier create mode 100644 Aiko/Libs/LogAccess.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Libs/Logdbtrait.php create mode 100644 Aiko/Libs/Logdbtrait.php:Zone.Identifier create mode 100644 Aiko/Libs/Logdbtrait.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Libs/MyFpdi.php create mode 100644 Aiko/Libs/MyFpdi.php:Zone.Identifier create mode 100644 Aiko/Libs/MyFpdi.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Libs/MyPdf.php create mode 100644 Aiko/Libs/MyPdf.php:Zone.Identifier create mode 100644 Aiko/Libs/MyPdf.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Libs/Mycrypt.php create mode 100644 Aiko/Libs/Mycrypt.php:Zone.Identifier create mode 100644 Aiko/Libs/Mycrypt.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Libs/Query.php create mode 100644 Aiko/Libs/Query.php:Zone.Identifier create mode 100644 Aiko/Libs/Query.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Libs/QueryParam.php create mode 100644 Aiko/Libs/QueryParam.php:Zone.Identifier create mode 100644 Aiko/Libs/QueryParam.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Libs/QueryProcess.php create mode 100644 Aiko/Libs/QueryProcess.php:Zone.Identifier create mode 100644 Aiko/Libs/QueryProcess.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Libs/Session.php create mode 100644 Aiko/Libs/Session.php:Zone.Identifier create mode 100644 Aiko/Libs/Session.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Libs/Storage.php create mode 100644 Aiko/Libs/Storage.php:Zone.Identifier create mode 100644 Aiko/Libs/Storage.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Libs/Token.php create mode 100644 Aiko/Libs/Token.php:Zone.Identifier create mode 100644 Aiko/Libs/Token.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Libs/TokenSanitation.php create mode 100644 Aiko/Libs/TokenSanitation.php:Zone.Identifier create mode 100644 Aiko/Libs/TokenSanitation.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Libs/Trait.php create mode 100644 Aiko/Libs/Trait.php:Zone.Identifier create mode 100644 Aiko/Libs/Trait.php:Zone.Identifier:Zone.Identifier create mode 100644 Aiko/Libs/Validator.php create mode 100644 Aiko/Libs/Validator.php:Zone.Identifier create mode 100644 Aiko/Libs/ValidatorRule.php create mode 100644 Aiko/Libs/ValidatorRule.php:Zone.Identifier create mode 100644 Aiko/Libs/ValidatorRuleCollection.php create mode 100644 Aiko/Libs/ValidatorRuleCollection.php:Zone.Identifier create mode 100644 Aiko/Libs/WhatsApp.php create mode 100644 Aiko/Libs/WhatsApp.php:Zone.Identifier create mode 100644 Aiko/Libs/WhatsApp.php:Zone.Identifier:Zone.Identifier diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bc5225d --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# Aiko folder (local only) +be/src/api/Aiko/ + +# Node modules +node_modules/ + +# Vendor directories +vendor/ + +# Environment files +.env +.env.local + +# IDE files +.vscode/ +.idea/ + +# OS files +.DS_Store +Thumbs.db + +# Log files +*.log + +# Zone.Identifier files (Windows) +*.Zone.Identifier \ No newline at end of file diff --git a/Aiko/Aiko/Framework/Core.php b/Aiko/Aiko/Framework/Core.php new file mode 100644 index 0000000..125d361 --- /dev/null +++ b/Aiko/Aiko/Framework/Core.php @@ -0,0 +1,828 @@ +vars[$index] = $value; + } + public function __get($index) + { + return $this->vars[$index]; + } +} + +abstract class Controller +{ + protected $registry; + public $ActionAjaxOff; + protected $methodAccess; + protected $apiAction; + protected $apiParams; + protected $apiModule; + protected $publicAction = array(); + private $allowJwt = array(); + protected $appID; + protected $tokenID; + protected $generalActions=array(); + + protected $isFile=false; + + private $allowedMimeType = [ + 'image/jpeg', + 'image/png', + 'image/jpg', + 'video/mp4', + 'application/pdf', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheetapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'text/plain', + 'application/octet-stream', + 'application/zip', + 'application/msword', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'application/vnd.ms-word.document.macroEnabled.12', + 'application/vnd.ms-word.template.macroEnabled.12', + 'application/vnd.ms-excel', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'application/vnd.ms-excel.sheet.macroEnabled.12', + 'application/vnd.ms-excel.template.macroEnabled.12', + 'application/vnd.ms-excel.addin.macroEnabled.12', + 'application/vnd.ms-excel.sheet.binary.macroEnabled.12' + ]; + + public function __construct($registry) + { + // session_id('hcportal-session-id'); + // session_start(); + // Http::enabledCors(); + + $this->registry = $registry; + $this->methodAccess = $_SERVER['REQUEST_METHOD']; + $this->allowJwt = array('dologin', 'dologout', 'refreshToken', 'generateNewToken', 'loginauth'); + + + // connect main DB + // $this->registry = $registry; + // $this->registry->db = Connections::getInstance( + // $this->registry->config->host, + // $this->registry->config->db, + // $this->registry->config->socket, + // $this->registry->config->user, + // $this->registry->config->password, + // $this->registry->config->dbms + // ); + + if($this->registry->config->dbMainConType!=='local') + { + $this->registry->db = Connections::getInstance($this->registry->config->dbMainConType); + }else { + $this->registry->db = Connections::getInstance( + $this->registry->config->dbMainConType, + $this->registry->config->host, + $this->registry->config->socket, + $this->registry->config->user, + $this->registry->config->password + ); + } + + // $handler = new Session($registry); + // $result= session_set_save_handler($handler,true); + + // session_start(); + // session_start(); + + + // if (!interface_exists('SessionHandlerInterface')) { + // exit('ATTENTION: the session handler implemented by Predis requires PHP >= 5.4.0 ' . + // "or a polyfill for SessionHandlerInterface provided by an external package.\n"); + // } + // $single_server=[ + // 'scheme' => 'tcp', + // 'host' => '10.1.200.218', + // 'port' => 6388, + // ]; + // $client = new Client($single_server, ['prefix' => 'sessions:']); + + // // Set `gc_maxlifetime` to specify a time-to-live of 5 seconds for session keys. + // $handler = new Handler($client, ['gc_maxlifetime' => get_cfg_var("session.gc_maxlifetime")]); + + // // Register the session handler. + // $handler->register(); + + // // We just set a fixed session ID only for the sake of our example. + // session_id('hcportalsessionid'); + + if(!isset($_SESSION)) + { + session_start(); + } + // check mime_type + $this->checkContentFile(); + + + } + + abstract public function index(); + + protected function checkToken() + { + try { + $token = Http::getTokenJWT(); + + // get token ID + $tokenPart = explode('.', $token); + + if (count($tokenPart) != 4) { + throw new \ErrorException('token part invalid'); + } + + $stmt = $this->registry->db->prepare('select appID,tokenID,chipper,data,expired from jwt where id=:id'); + $stmt->bindValue(':id', $tokenPart[3], \PDO::PARAM_INT); + $stmt->execute(); + $rs = $stmt->fetchAll(\PDO::FETCH_ASSOC); + + if (count($rs) == 0) { + throw new \ErrorException('token jwt not exist'); + } + + $this->appID=$rs[0]['appID']; + $this->tokenID=$rs[0]['tokenID']; + + $now = time(); + if ($rs[0]['expired'] < $now) { + throw new \Exception('Time Token refresh Exceded'); + } + + // update expired + $stmt = $this->registry->db->prepare('update jwt set expired=:expired where id=:id'); + $stmt->bindValue(':id', $tokenPart[3], \PDO::PARAM_INT); + $stmt->bindValue(':expired', time() + __LIFETIMEJWT, \PDO::PARAM_INT); + $stmt->execute(); + + $newToken = $tokenPart[0] . '.' . $tokenPart[1] . '.' . $tokenPart[2]; + + $data = Token::decodeJWTNew($newToken, $rs[0]['chipper']); + if (is_numeric($data)) { + if ($data === 8) // expired token + { + $this->registry->log->customError('tokenError', 'Module Controller / check Token : expired token , token :' . $data); + Http::tokenExpired(array('message' => 'Token need refresh')); + } else { + throw new \ErrorException('decode Error token :' . $data); + } + } + $rData = json_decode(json_encode($data->data), true); + \Helper::setSession($rData); + return true; + } catch (\ErrorException $e) { + $this->registry->log->customError('tokenError', 'Module Controller / check Token :' . $e->getMessage()); + Http::UnauthorizedResponseJson(array('message' => 'Wrong Token')); + //return false; + } catch (\Exception $e) { + $this->registry->log->customError('tokenError', 'Module Controller / check Token :' . $e->getMessage()); + Http::UnauthorizedResponseJson(array('message' => $e->getMessage())); + } catch (\PDOException $e) { + $this->registry->log->customError('tokenError', 'Module Controller / check Token :' . $e->getMessage()); + Http::UnauthorizedResponseJson(array('message' => 'query error ')); + } + } + protected function checkTokenOld() + { + try { + $token = Http::getTokenJWT(); + + + + $data = Token::decodeJWTNew($token); + if (is_numeric($data)) { + if ($data === 8) // expired token + { + $this->registry->log->customError('tokenError', 'Module Controller / check Token : expired token , token :' . $data); + Http::tokenExpired(array('message' => 'Wrong Token')); + } else { + throw new \ErrorException('decode Error token :' . $data); + } + } + $rData = json_decode(json_encode($data->data), true); + \Helper::setSession($rData); + return true; + } catch (\ErrorException $e) { + $this->registry->log->customError('tokenError', 'Module Controller / check Token :' . $e->getMessage()); + Http::UnauthorizedResponseJson(array('message' => 'Wrong Token')); + //return false; + } catch (\Exception $e) { + $this->registry->log->customError('tokenError', 'Module Controller / check Token :' . $e->getMessage()); + Http::UnauthorizedResponseJson(array('message' => $e->getMessage())); + } catch (\PDOException $e) { + $this->registry->log->customError('tokenError', 'Module Controller / check Token :' . $e->getMessage()); + Http::UnauthorizedResponseJson(array('message' => 'query error ')); + } + } + + protected function checkRulesAccess() + { + $rule = new Rule($this->registry); + if (!in_array($this->apiAction, $this->publicAction)) { + $hasAccess = $rule->hasAccess($this->apiModule, $this->apiAction); + + if ($hasAccess == false) { + Http::ErrorQueryResponse('operation not permit', 'json'); + } + } + } + + protected function checkAPIAccess() + { + + /* check method access */ + $this->allowOptionMethod(); + + if (!in_array($this->methodAccess, array('POST', 'GET', 'DELETE'))) { + Http::UnauthorizedResponseJson(array('message' => 'Method Not allowed')); + } + $this->apiAction = ''; + switch ($this->methodAccess) { + case 'POST': + /* check and get action */ + $this->apiAction = Http::GetvarData('action'); + if (!isset($this->apiAction)) { + $jtext = Http::GetBodyRequest(); + $this->apiParams = \Firebase\JWT\JWT::jsonDecode($jtext); + if (!isset($this->apiParams->action)) { + Http::UnauthorizedResponseJson(array('message' => 'Action not set')); + } + $this->apiAction = $this->apiParams->action; + } + + break; + + default: + // GET // DELETE + $this->apiAction = Http::GetvarData('action'); + if (strlen($this->apiAction) === 0) { + Http::UnauthorizedResponseJson(array('message' => 'Action not set')); + } + break; + } + + /* check token */ + $isAllowed = $this->checkToken(); + if (!$isAllowed) { + Http::UnauthorizedResponseJson(array('message' => 'Wrong Token')); + } + + /* check rule */ + $this->checkRulesAccess(); + } + + protected function isAuthorized() + { + /* check method access */ + $this->allowOptionMethod(); + + if (!in_array($this->methodAccess, array('POST', 'GET', 'DELETE'))) { + Http::UnauthorizedResponseJson(array('message' => 'Method Not allowed')); + } + $this->apiAction = ''; + + switch ($this->methodAccess) { + case 'POST': + /* check and get action */ + if($this->isFile){ + $aText['action']=Http::GetVarData('action','post'); + $this->apiParams=\Firebase\JWT\JWT::jsonDecode(\Firebase\JWT\JWT::jsonEncode($aText)); + $this->apiAction = Http::GetVarData('action','post'); + }else{ + $jtext = Http::GetBodyRequest(); + $this->apiParams = \Firebase\JWT\JWT::jsonDecode($jtext); + + if (!isset($this->apiParams->action)) { + Http::UnauthorizedResponseJson(array('message' => 'Action not set')); + } + + $this->apiAction = $this->apiParams->action; + + } + + break; + + default: + // GET // DELETE + $this->apiAction = Http::GetvarData('action'); + $this->apiParams = json_decode(json_encode(Http::getAllRequest())); + if (strlen($this->apiAction) === 0) { + Http::UnauthorizedResponseJson(array('message' => 'Action not set')); + } + break; + } + + if (!in_array($this->apiAction, $this->allowJwt)) { + /* check token */ + $isAllowed = $this->checkToken(); + if (!$isAllowed) { + Http::UnauthorizedResponseJson(array('message' => 'Wrong Token')); + } + } + + + if (is_array($this->generalActions)) { + /* check rule */ + if(!in_array($this->apiAction,$this->generalActions)){ + $this->checkRulesAccess(); + } + } + + + /* process request */ + $this->prosesRequest(); + } + + protected function checkAPIAccessEvaluation() + { + if ($this->methodAccess == 'OPTIONS') { + if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) { + Http::ResponseJson('ok', '0', '1'); + } + } + $isAllowed = $this->checkTokenEvaluation(); + if (!$isAllowed) { + Http::UnauthorizedResponseJson(array('message' => 'Wrong Token')); + } + } + + protected function checkTokenEvaluation() + { + try { + + $token = Http::getTokenJWT(); + $data = Token::decodeJWT($token); + if (!isset($data->data)) { + throw new \ErrorException('decode Error token :' . $token); + } + + $_SESSION = array(); + session_destroy(); + + $_SESSION['group'] = $data->data->group; + $_SESSION['username'] = $data->data->username; + $_SESSION['name'] = isset($data->data->name) ? $data->data->name : $data->data->nama; + $_SESSION['section'] = isset($data->data->section) ? $data->data->section : $data->data->secion; + $_SESSION['userID'] = $data->data->userID; + $_SESSION['empNo'] = isset($data->data->empNo) ? $data->data->empNo : ''; + $_SESSION['empSite'] = $data->data->empSite; + $_SESSION['empSubArea'] = isset($data->data->empSubArea) ? $data->data->empSubArea : ''; + $_SESSION['flagApp'] = isset($data->data->flagApp) ? $data->data->flagApp : ''; + $_SESSION['nationality'] = isset($data->data->nationality) ? $data->data->nationality : ''; + $_SESSION['role'] = isset($data->data->role) ? $data->data->role : ''; + + // if jwt valid set session var + + return true; + } catch (\ErrorException $e) { + $this->registry->log->error('Module Controller / check Token Eval :' . $e->getMessage()); + return false; + } + } + + protected function allowOptionMethod() + { + if ($this->methodAccess == 'OPTIONS') { + if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) { + Http::ResponseJson(array('ok'), '0', '1'); + } + } + } + + private function prosesRequest() + { + switch ($this->methodAccess) { + case 'POST': + $this->executePost(); + break; + case 'GET': + $this->executeGet(); + break; + case 'DELETE': + $this->executeDelete(); + break; + default: + Http::ErrorQueryResponse('method not permit'); + break; + } + } + protected function executePost() + { + $act = $this->apiAction; + if (method_exists($this, $act)) { + $this->$act(); + } else { + Http::ErrorQueryResponse('Action not registered'); + } + } + private function executeGet() + { + $act = $this->apiAction; + if (method_exists($this, $act)) { + $this->$act(); + } else { + Http::ErrorQueryResponse('Action not registered'); + } + } + protected function executeDelete() + { + } + + protected function extendAllowJwt(array $extended) + { + foreach ($extended as $value) { + array_push($this->allowJwt, $value); + } + } + + + + /** + * fungsi ini untuk convert message dari api. + * untuk keperluan migrasi FE ke framework yang baru + * karena fokus utama migrasi FE dulu jadi BE yang menyesuaikan + * + * @param message + * @return $result : string + */ + protected function convertMessages($message) + { + $result = $message; + switch($message){ + case 'PAYROLL.MESSAGE.SUCCMESINS': + $result = 'MESSAGE.SUCCMESINS'; + break; + case 'PAYROLL.MESSAGE.FAILMESEXIST': + $result = 'MESSAGE.DATA_ALREADY_EXIST'; + break; + case 'PAYROLL.MESSAGE.FAILMESUNKNOWN': + $result = 'MESSAGE.FAILMESUNKNOWN'; + break; + case 'PAYROLL.MESSAGE.FAILMESERRREQ': + $result = 'MESSAGE.FAILMESERRREQ'; + break; + case 'PAYROLL.MESSAGE.SUCCMESDEL': + $result = 'MESSAGE.SUCCMESDEL'; + break; + case 'PAYROLL.MESSAGE.SUCCMESUPD': + $result = 'MESSAGE.SUCCMESUPD'; + break; + case 'PAYROLL.MESSAGE.FAILMESQUERY': + $result = 'MESSAGE.FAILMESQUERY'; + break; + case 'MENU.MASTER_DATA.ADMINISTRATIVE_AREA.MAIN.CANTDELETE': + $result = 'MESSAGE.CANTDELETE'; + break; + } + + return $result; + } + + /** + * fungsi ini untuk convert response menjadi format pagination. + * untuk keperluan migrasi FE ke framework yang baru + * karena fokus utama migrasi FE dulu jadi BE yang menyesuaikan + * + * @param array + * @return array + */ + protected function convertToPaginationFormat($array) + { + $total = count($array); + $aData['iTotalDisplayRecords'] = $total; + $aData['iTotalRecords'] = $total; + $aData['aData'] = $array; + + return $aData; + } + + private function checkContentFile(){ + $this->isFile=Http::isMultipartFormData(); + if($this->isFile){ + if (!empty($_FILES) && is_array($_FILES) && count($_FILES) > 0) { + foreach ($_FILES as $file) { + $filepath = $file['tmp_name']; + // $filesize = filesize($filepath); + $fileinfo = finfo_open(FILEINFO_MIME_TYPE); + $filetype = finfo_file($fileinfo, $filepath); + finfo_close($fileinfo); + if (!in_array($filetype, $this->allowedMimeType)) { + Http::ErrorQueryResponse(array('name' => $file['name'], 'message' =>'15220-failed'), 'json'); + } + } + } + } + } + + protected function setSession($token) + { + // get token ID + $tokenPart = explode('.', $token); + \Helper::dump($tokenPart); + if (count($tokenPart) != 4) { + throw new \ErrorException('token part invalid'); + } + + $stmt = $this->registry->db->prepare('select appID,tokenID,chipper,data,expired from jwt where id=:id'); + $stmt->bindValue(':id', $tokenPart[3], \PDO::PARAM_INT); + $stmt->execute(); + $rs = $stmt->fetchAll(\PDO::FETCH_ASSOC); + + if (count($rs) == 0) { + throw new \ErrorException('token jwt not exist'); + } + + $this->appID=$rs[0]['appID']; + $this->tokenID=$rs[0]['tokenID']; + + $now = time(); + if ($rs[0]['expired'] < $now) { + throw new \Exception('Time Token refresh Exceded'); + } + + // update expired + $stmt = $this->registry->db->prepare('update jwt set expired=:expired where id=:id'); + $stmt->bindValue(':id', $tokenPart[3], \PDO::PARAM_INT); + $stmt->bindValue(':expired', time() + __LIFETIMEJWT, \PDO::PARAM_INT); + $stmt->execute(); + + $newToken = $tokenPart[0] . '.' . $tokenPart[1] . '.' . $tokenPart[2]; + + $data = Token::decodeJWTNew($newToken, $rs[0]['chipper']); + if (is_numeric($data)) { + if ($data === 8) // expired token + { + $this->registry->log->customError('tokenError', 'Module Controller / check Token : expired token , token :' . $data); + Http::tokenExpired(array('message' => 'Token need refresh')); + } else { + throw new \ErrorException('decode Error token :' . $data); + } + } + $rData = json_decode(json_encode($data->data), true); + \Helper::setSession($rData); + } +} + +class Router +{ + private $registry; + private $path; + private $args = array(); + public $file; + public $controller; + public $action; + public $parts; + private $controllerPath; + + private $prefix; + public function __construct($registry,$prefix='') + { + $this->registry = $registry; + $this->prefix=$prefix; + } + + public function loader() + { + + try { + /*** a new controller class instance , pembuatan controller object***/ + $class = $this->controller; + $this->registry->controller = $class; + $this->registry->action = $this->action; + $ClassName = ucfirst($class); + $mod = strtolower($class); + + $aModules = explode('/', $this->controllerPath); + $jumModules = count($aModules); + //$mod1 = substr($this->controllerPath, 1); + $mod1 = $this->controllerPath; + $strslash = substr($this->controllerPath, 0, 1); + if ($strslash == '/' || $strslash == '\\') { + $mod1 = substr($this->controllerPath, 1); + } + + $newmod = str_replace('/', '\\', $mod1); + + $namespaces = "\\modules\\{$newmod}\\controller\\{$ClassName}Controller"; + + $this->registry->ContPath = $mod1; + + $controller = new $namespaces($this->registry); + + /*** check if the action is callable ***/ + if (is_callable(array($controller, $this->action)) == false) { + + $action = 'index'; + } else { + $action = $this->action; + } + + /*** run the action , ini sama kayak execute function yang ada pada controller pada mvc sebelumnya + * ***/ + if ($this->registry->config->ajax == 'on') { + if (!empty($controller->ActionAjaxOff)) { + if (!in_array($action, $controller->ActionAjaxOff)) { + // if true + + if (!$this->registry->isAjax) { + exit('ajax request required'); + } + } + } else { + if (!$this->registry->isAjax) { + exit('ajax request required'); + } + } + } else { + if ($this->registry->isAjax) { + exit('please set ajax config to "on" if request ajax required'); + } + } + $controller->$action(); + } catch (\Exception $e) { + $this->registry->log->error('Core / Loader :' . $e->getMessage() . ' Line :' . $e->getLine() . ' ' . $e->getFile()); + Http::InternalServerError('error loader'); + } + } + + private function getController() + { + + try { + /* get variable*/ + $this->controller = $this->getControllerName(); + $j = 0; + if (!(empty($this->parts[2]) or $this->parts[2] == '-')) { + for ($i = 2; $i < count($this->parts); $i++) { + $this->args[$j] = $this->parts[$i]; + $j++; + } + $this->registry->vars = $this->args; + } else { + $this->registry->vars = 'null'; + } + + /*** set the file path ***/ + return $this->controller; + } catch (\Exception $e) { + + $this->registry->log->error('Core / Loader :' . $e->getMessage() . ' Line :' . $e->getLine() . ' ' . $e->getFile()); + \Aiko\Http::InternalServerError('Error loader'); + } + } + public function getControllerName() + { + + try { + $restrict = ''; + if ($this->registry->config->restrict == 'yes') { + if (isset($this->registry->config->ipconfig)) { + $ip = $this->getRealIpAddr(); + $register = in_array($ip, $this->registry->config->ipconfig); + + if ($ip != '127.0.0.1') { + if (!$register) { + $restrict = 'restrict'; + } + } + } else { + $restrict = 'restrict'; + } + } + $this->getName($restrict); + $this->Request_check(); + + return $this->controller; + } catch (\Exception $e) { + + $this->registry->log->error('Core / Loader :' . $e->getMessage() . ' Line :' . $e->getLine()); + \Aiko\Http::InternalServerError('Error loader'); + } + } + + private function getName($restrict) + { + try { + if ($restrict == 'restrict') { + $this->controller = 'restrict'; + $this->controllerPath = 'restrict'; + } else { + $route = (empty($_GET['rt'])) ? '' : $_GET['rt']; + if (empty($route)) { + // jika route tidak ada / pada awal page + $route = 'index'; + } else { + // clean root with prefix + $route= $this->cleanRoute($route); + /*** get the parts of the route ***/ + $this->parts = explode('/', $route); + // set controller name + // cek apakan part yang pertama memiliki controller kalau tidak ditemukan return 404 + if (!is_dir(__SITE_PATH . '/src/modules/' . $this->parts[0])) { + $this->controller = 'error404'; + $this->controllerPath = 'error404'; + } else { + $i = 0; + $path = ''; + $found = false; + do { + $path .= '/' . $this->parts[$i]; + $dir = __SITE_PATH . '/src/modules' . $path; + if (file_exists($dir . '/controller')) { + $found = true; + break; + } + $i++; + } while ($i < count($this->parts)); + if ($found) { + $this->controller = $this->parts[$i]; + $this->controllerPath = $path; + } else { + $this->controller = 'error404'; + $this->controllerPath = 'error404'; + } + + if (isset($this->parts[$i + 1])) { + // set action name + $this->action = $this->parts[$i + 1]; + } + } + } + // cek apakah controller kosong, jika kosong set ke index + if (empty($this->controller)) { + $this->controller = 'index'; + $this->controllerPath = 'index'; + } + + /*** Get action ***/ + if (empty($this->action)) { + $this->action = 'index'; + } + } + } catch (\Exception $e) { + + $this->registry->log->error('Core / Loader :' . $e->getMessage() . ' Line :' . $e->getLine()); + \Aiko\Http::InternalServerError('Error loader'); + } + } + private function Request_check() + { + $this->registry->isAjax = isset($_SERVER['HTTP_X_REQUESTED_WITH']) and + strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'; + } + public function getControllerPath() + { + return $this->controllerPath; + } + private function getRealIpAddr() + { + if (!empty($_SERVER['HTTP_CLIENT_IP'])) { //check ip from share internet + $ip = $_SERVER['HTTP_CLIENT_IP']; + } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { //to check ip is pass from proxy + $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; + } else { + $ip = $_SERVER['REMOTE_ADDR']; + } + return $ip; + } + + private function cleanRoute($route):string{ + $prefixLength=strlen($this->prefix); + if ($prefixLength==0){ + return $route; + } + $routePrefix=substr($route,0,$prefixLength); + if($this->prefix!==$routePrefix){ + + Http::InternalServerError('failed route'); + } + $newRoute= substr($route,$prefixLength); + if(strlen($newRoute)==0 || $newRoute=='/'){ + $newRoute='index'; + } + + // check apakah string pertama route / ? + if(substr($newRoute,0,1)=='/'){ + $newRoute=substr($newRoute,1); + } + return $newRoute; + } + +} diff --git a/Aiko/Aiko/Framework/Core.php:Zone.Identifier b/Aiko/Aiko/Framework/Core.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Framework/Core.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Framework/Database.php b/Aiko/Aiko/Framework/Database.php new file mode 100644 index 0000000..b35e760 --- /dev/null +++ b/Aiko/Aiko/Framework/Database.php @@ -0,0 +1,184 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + self::$instance->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL); + // self::$instance->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); + + return self::$instance; + } catch (PDOException $e) { + self::showerror("Sorry, an error has occured. Please try your request \n" . $e->getMessage()); + die(); + } + } else { + return self::$instance; + } + + } + + public static function getInstancePMA() { + $config = getConfig('pma'); + $host = $config['host']; + $db = $config['db']; + $socket = $config['socket']; + $user = $config['user']; + $pass = $config['password']; + if (!self::$instancePMA) + { + try + { + self::$instancePMA = new PDO("mysql:host=$host;dbname=$db;unix_socket=$socket;", "$user","$pass"); + self::$instancePMA-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + self::$instancePMA->setAttribute(PDO::ATTR_CASE,PDO::CASE_NATURAL); + return self::$instancePMA; + }catch (PDOException $e) + { + self::showerror("Sorry, an error has occured. Please try your request \n".$e->getMessage()); + die(); + } + }else + { + return self::$instancePMA; + } + + } + + public static function getInstanceCartal($type) { + $config = getConfig($type); + $host = $config['host']; + $db = $config['db']; + $socket = $config['socket']; + $user = $config['user']; + $pass = $config['password']; + if (!self::$instanceCartal) + { + try + { + self::$instanceCartal = new PDO("mysql:host=$host;dbname=$db;unix_socket=$socket;", "$user","$pass"); + self::$instanceCartal-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + self::$instanceCartal->setAttribute(PDO::ATTR_CASE,PDO::CASE_NATURAL); + return self::$instanceCartal; + }catch (PDOException $e) + { + self::showerror("Sorry, an error has occured. Please try your request \n".$e->getMessage()); + die(); + } + }else + { + return self::$instanceCartal; + } + + } + + public static function getInstanceSCADA($type) { + $config = getConfig($type); + $host = $config['host']; + $db = $config['db']; + $user = $config['user']; + $pass = $config['password']; + $port = $config['port']; + if (!self::$scada) + { + try + { + self::$scada = new PDO("pgsql:host=$host;port=$port;dbname=$db;", "$user", "$pass"); + self::$scada-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + self::$scada->setAttribute(PDO::ATTR_CASE,PDO::CASE_NATURAL); + return self::$scada; + }catch (PDOException $e) + { + self::showerror("Sorry, an error has occured. Please try your request \n".$e->getMessage()); + die(); + } + }else + { + return self::$instanceCartal; + } + + } + + public static function exceptionHandler($e) + { + set_exception_handler('exceptionHandler'); + self::showerror("Sorry, the site under maintenance \n"); + } + public static function showerror($m) + { + echo "

Error

"; + echo nl2br(htmlspecialchars($m)); + } +/** + * + * + * Like the constructor, we make __clone private + * so nobody can clone the instance + * + */ + private function __clone() + {} + +} diff --git a/Aiko/Aiko/Framework/Database.php:Zone.Identifier b/Aiko/Aiko/Framework/Database.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Framework/Database.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Framework/Error.php b/Aiko/Aiko/Framework/Error.php new file mode 100644 index 0000000..76510c1 --- /dev/null +++ b/Aiko/Aiko/Framework/Error.php @@ -0,0 +1,11 @@ +config = json_decode(json_encode($config)); + +//$registry->config = json_decode(json_encode(parse_ini_file(__SITE_PATH . '/includes/' . 'config.ini'))); + + +// var_dump($registry->config); + +/* + * set server address dari file config + */ +define('__SERVERADDR', $registry->config->server_address); + +/* + * set time zone area application + */ +date_default_timezone_set($registry->config->time_zone); + +/* + Create object registry for carry object + */ + +$registry->router = new Aiko\Router($registry); + +/* + Set Controller Name + */ + +$registry->controller = $registry->router->getControllerName(); + +/* + Create object template + */ + +$registry->template = new \Aiko\Template\Template($registry); + +/* + Set Debugging + */ +/*set Aiko Debugging on developer mode*/ + +$registry->ab = new \Aiko\Debug($registry->config->environment); + +/* set log aplikasi */ +$registry->log = new \Aiko\Log($registry->config->log); + + +//$this->registry = $registry; +//$sessionHandler = new \Aiko\Session($registry); +// session_set_save_handler($sessionHandler, true); +// session_set_save_handler( +// array($sessionHandler, 'open'), +// array($sessionHandler, 'close'), +// array($sessionHandler, 'read'), +// array($sessionHandler, 'write'), +// array($sessionHandler, 'destroy'), +// array($sessionHandler, 'gc') +// ); +// the following prevents unexpected effects when using objects as save handlers +// register_shutdown_function('session_write_close'); + +// session_start(); +// proceed to set and retrieve values by key from $_SESSION + +/* turn of dompdf autoload because we use composer */ +define('DOMPDF_ENABLE_AUTOLOAD', false); + +// require_once __SITE_PATH.'/vendor/dompdf/dompdf/dompdf_config.inc.php'; + +/* + Run Controller + */ + +$registry->router->loader(); diff --git a/Aiko/Aiko/Framework/Init.php:Zone.Identifier b/Aiko/Aiko/Framework/Init.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Framework/Init.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Framework/Model.php b/Aiko/Aiko/Framework/Model.php new file mode 100644 index 0000000..e63614c --- /dev/null +++ b/Aiko/Aiko/Framework/Model.php @@ -0,0 +1,235 @@ +registry = $registry; + /* if($this->registry->config->dbMainConType!=='local') + { + $this->registry->db = Connections::getInstance($this->registry->config->dbMainConType); + }else { + $this->registry->db = Connections::getInstance( + $this->registry->config->dbMainConType, + $this->registry->config->host, + $this->registry->config->socket, + $this->registry->config->user, + $this->registry->config->password + ); + } */ + + + } + + public function ConnectToOracle() + { + try { + $host = $this->registry->config->hostOracle; + $db = $this->registry->config->dbOracle; + $user = $this->registry->config->userOracle; + $pass = $this->registry->config->passwordOracle; + // die($user.$pass); + $this->registry->dbOracle = new PDO("oci:dbname=//$host:1521/$db;", "$user", "$pass", array( + PDO::ATTR_TIMEOUT => 10, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + )); + $this->registry->dbOracle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $this->registry->dbOracle->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL); + + } catch (\PDOException $e) { + die("Sorry, an error has occured. Please try your request \n"); + } + + } + + public function connectToDBPMA() + { + $this->registry->dbpma = Connections::getInstancePMA(); + } + + protected function beginTransaction() + { + $this->registry->db->beginTransaction(); + } + protected function commit() + { + $this->registry->db->commit(); + } + protected function rollBack() + { + $this->registry->db->rollBack(); + } + + protected function sendResponse($moreInfo, $messages, $status) + { + return array( + "moreInfo" => $moreInfo, + "messages" => $messages, + "status" => $status, + ); + } + + public function connectToCarTal() + { + return Connections::getInstanceCartal($this->registry->config->dbCarTalType); + } + + public function connectToScada() + { + return Connections::getInstanceSCADA($this->registry->config->dbScadaType); + } + + protected function checkValidNikByEmpId($empId,$nik){ + try{ + $stmt=$this->registry->db->prepare('select nik from employement where nik=:nik and emp_profile_id=:emp_id'); + $stmt->bindValue(':nik',$nik,PDO::PARAM_STR); + $stmt->bindValue(':emp_id',$empId,PDO::PARAM_INT); + $stmt->execute(); + if($stmt->rowCount()>0){ + + return true; + } + return false; + }catch(\PDOException $e){ + return false; + }catch(\ErrorException $e){ + return false; + } + } + + private function serializeColumn($arr = [], $isBinding = false) + { + $serialize = ''; + for ($i = 0; $i < count($arr); $i++) { + if ($isBinding) { + $serialize .= ":$arr[$i],"; + } else { + if (is_numeric($arr[$i])) { + $serialize .= "$arr[$i],"; + } else { + $serialize .= "'$arr[$i]',"; + } + } + } + + return substr($serialize, 0, -1); + } + + public function prepareQuery($query) + { + if (isset($this->preparedStatements[$query])) { + $stmt = $this->preparedStatements[$query]; + } else { + // Call PDO::prepare. + $stmt = $this->registry->db->prepare($query); + $this->preparedStatements[$query] = $stmt; + } + return $stmt; + } + + private function checkDebugMode($stmt) + { + if ($this->enabledDebugMode) { + $stmt->debugDumpParams(); + die(); + } + } + + protected function error($e, $name="") + { + if(!empty($name)){ + $this->registry->log->customError($name, 'Message: '. $e->getMessage() . ' | Line: '. $e->getLine(). ' | File: '. $e->getFile()) . ' | User: ' . \Helper::getSessionVar('username'); + }else{ + $this->registry->log->error('Message: '. $e->getMessage() . ' | Line: '. $e->getLine(). ' | File: '. $e->getFile() . ' | User: ' . \Helper::getSessionVar('username')); + } + } + + protected function getColumnIndex($col) + { + $idx = \PHPExcel_Cell::columnIndexFromString($col); + return $idx - 1; + } + + protected function getWorkSheetData($fileName, $sheetIndex) + { + $objPHPExcel = new PHPExcel(); + $inputFileType = \PHPExcel_IOFactory::identify($fileName); + $objReader = \PHPExcel_IOFactory::createReader($inputFileType); + + $objPHPExcel = $objReader->load($fileName); + $objWorkSheet = $objPHPExcel->setActiveSheetIndex($sheetIndex); + + return $objWorkSheet; + } + + /** + * $type allowed + * - time untuk jam + * - date untuk tanggal + */ + protected function getColumnValue($objWorkSheet, $columnIndex, $row, $type='') + { + $result = $objWorkSheet->getCellByColumnAndRow($this->getColumnIndex($columnIndex), $row)->getValue(); + if(!empty($type)){ + $format = 'YYYY-MM-DD'; + $defValue = "1970-01-01"; + if($type=='time'){ + $defValue = "00:00:00"; + $format = 'hh:mm:ss'; + } + if(empty($result)){ + return $defValue; + } + return \PHPExcel_Style_NumberFormat::toFormattedString(trim($result), $format); + } + + return trim($result); + } + + protected function saveFileData($file, $path, $allowedMime = []) + { + $filename = $file->getClientOriginalName(); + $mimeType = $file->getClientMimeType(); + $mimeClientAlowed = array('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-excel'); + if(count($allowedMime)>0){ + $mimeClientAlowed = $allowedMime; + } + if (!in_array($mimeType, $mimeClientAlowed)) { + throw new Exception('error file type'); + } + $targetPath = $this->registry->config->base_storage. $path; + $targetFile = str_replace('//', '/', $targetPath); + $newfilename = $targetFile . '_' . time() . '_' . $filename; + // store data to storage + $file->move($targetFile, $newfilename); + + return array('filename' => $filename, 'newfilename' => $newfilename); + } + + protected function isEmpty($param) + { + if(is_null($param) || empty($param) || !$param){ + return true; + } + + return false; + } +} + diff --git a/Aiko/Aiko/Framework/Model.php:Zone.Identifier b/Aiko/Aiko/Framework/Model.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Framework/Model.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Framework/Template.php b/Aiko/Aiko/Framework/Template.php new file mode 100644 index 0000000..10e5838 --- /dev/null +++ b/Aiko/Aiko/Framework/Template.php @@ -0,0 +1,107 @@ +registry = $registry; // set registry object + +} + + + public function __set($index, $value) // magic method yang berfungsi untuk set variable untuk template saja + { + $this->vars[$index] = $value; + } + +// ini method yang berfungsi untuk menampilkan view +function show($name,$listJS= array(),$listCSS= array()) { + // variable path berfungsi menyimpan path file view + $path = __SITE_PATH .'/src/modules/'.$this->registry->ContPath. '/views' . '/' . $name . '.php'; + $pathJS= __SITE_PATH .'/src/modules/'.$this->registry->ContPath. '/js' . '/' . $name . '.js'; + $srcjs= __SERVERADDR.'/src/modules'.$this->registry->ContPath. '/js' . '/' . $name . '.js'; + $pathCSS= __SITE_PATH .'/src/modules/'.$this->registry->ContPath. '/css' . '/' . $name . '.css'; + $srccss= __SERVERADDR.'/src/modules'.$this->registry->ContPath. '/css' . '/' . $name . '.css'; + if (file_exists($path) == false) + { + throw new \Exception('Template not found in '. $path); + return false; + } + + + // Load variables, jadikan index array sebagai variable pada php + foreach ($this->vars as $key => $value) + { + //set variable php + $$key = $value; + } + + if(sizeof($listCSS)>0) + { + foreach ($listCSS as $val) { + echo ""; + } + + } + + // include file + if (file_exists($pathCSS) == true) + { + echo ""; + } + include ($path); // load view + if (file_exists($pathJS) == true) + { + echo ""; + } + if(sizeof($listJS)>0) + { + foreach ($listJS as $val) { + echo ""; + } + + } +} + +/** + * method ini digunakan untuk menampilkan data dalam PDF + * require dompdf + */ +public function getContentFile($name) +{ + $path = __SITE_PATH .'/src/modules/'.$this->registry->ContPath. '/pdf' . '/' . $name . '.php'; + + if (file_exists($path) == false) + { + throw new \Exception('Template not found in '. $path); + return false; + } + + // Load variables, jadikan index array sebagai variable pada php + foreach ($this->vars as $key => $value) + { + //set variable php + $$key = $value; + } + + $obstart=ob_start(); + if ($obstart == false) + { + throw new \Exception('output bueffering not start '); + return false; + } + + include ($path); // load view + $out = ob_get_clean(); + return $out; +} + +} + +?> diff --git a/Aiko/Aiko/Framework/Template.php:Zone.Identifier b/Aiko/Aiko/Framework/Template.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Framework/Template.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Framework/Token.php b/Aiko/Aiko/Framework/Token.php new file mode 100644 index 0000000..79c3f96 --- /dev/null +++ b/Aiko/Aiko/Framework/Token.php @@ -0,0 +1,353 @@ +get_token_from_session('token'); + // var_dump($sessiontoken); + // exit(); + + + + + $valid = strlen($sessiontoken) == 128 && strlen($token) == 128 && $sessiontoken == $token; + + $this->get_token($area); // refresh token + + return $valid; + } + public function get_token_from_url() + { + $token = isset($_GET['token']) ? $_GET['token'] : ''; + + return $token; + } + + public function get_token_from_session($key) + { + $token = isset($_SESSION[$key]) ? $_SESSION[$key] : ''; + + return $token; + } + public function getTokenAuthUser() + { + $token = hash('sha512', mt_rand(0, mt_getrandmax()) . microtime(true)); + $_SESSION['tokenAuth'] = $token; + + return $token; + } + public function check_tokenAuthUser($token) + { + $sessiontoken = $this->get_token_from_session('tokenAuth'); + $valid = strlen($sessiontoken) == 128 && strlen($token) == 128 && $sessiontoken == $token; + if ($valid) { + return true; + } else { + return false; + } + } + + public function set_cookie() + { + $result = password_hash('4pl1k4s1D1sd1K', PASSWORD_DEFAULT, array('cost' => 10)); + // $res = setcookie('XSRF-TOKEN', $result, time() + 86400, $_SERVER['REQUEST_URI'],'',false,false); + + $res = setcookie('XSRF-TOKEN', $result, time() + 86400, '/'); + if ($res) { + return true; + } else { + return false; + } + } + public function cek_cookie($clientCookie) + { + $result = false; + if (isset($_COOKIE['XSRF-TOKEN'])) { + $serverCookie = $_COOKIE['XSRF-TOKEN']; + $result = $this->cek_hash($clientCookie, $serverCookie); + } + + return $result; + } + + private function cek_hash($clientCookie, $serverCookie) + { + if ($clientCookie == $serverCookie) { + return $this->set_cookie(); + } else { + return false; + } + } + + private static function wrapToken($jwt, $chipper) + { + try { + if (strlen($chipper) <> 6) { + throw new \ErrorException('chipper failed'); + } + $headerPreffix = (int) substr($chipper, 0, 1); + $headerSuffix = (int) substr($chipper, 1, 1); + $payloadPreffix = (int) substr($chipper, 2, 1); + $payloadSuffix = (int) substr($chipper, 3, 1); + $signPreffix = (int) substr($chipper, 4, 1); + $signSuffix = (int) substr($chipper, 5, 1); + + $jwtPart = explode('.', $jwt); + + $newJwt = self::randomChars($headerPreffix) . $jwtPart[0] . self::randomChars($headerSuffix); + + $newJwt .= '.' . self::randomChars($payloadPreffix) . $jwtPart[1] . self::randomChars($payloadSuffix); + + $newJwt .= '.' . self::randomChars($signPreffix) . $jwtPart[2] . self::randomChars($signSuffix); + + return $newJwt; + } catch (\Exception $e) { + return false; + } + } + + private static function unWrapToken($jwt, $chipper) + { + try { + if (strlen($chipper) <> 6) { + throw new \ErrorException('chipper failed'); + } + + $headerPreffix = (int) substr($chipper, 0, 1); + $headerSuffix = (int) substr($chipper, 1, 1); + $payloadPreffix = (int) substr($chipper, 2, 1); + $payloadSuffix = (int) substr($chipper, 3, 1); + $signPreffix = (int) substr($chipper, 4, 1); + $signSuffix = (int) substr($chipper, 5, 1); + + $jwtPart = explode('.', $jwt); + + + $newString = self::removePreSuf($jwtPart[0], $headerPreffix, $headerSuffix); + if ($newString == false) { + throw new \ErrorException('failed clean wrapper header'); + } + $header = $newString; + + $newString = self::removePreSuf($jwtPart[1], $payloadPreffix, $payloadSuffix); + if ($newString == false) { + throw new \ErrorException('failed clean wrapper payload'); + } + $payload = $newString; + + $newString = self::removePreSuf($jwtPart[2], $signPreffix, $signSuffix); + if ($newString == false) { + throw new \ErrorException('failed clean wrapper sign'); + } + $sign = $newString; + + return $header . '.' . $payload . '.' . $sign; + } catch (\ErrorException $e) { + return false; + } + } + + private static function removePreSuf($string, $preffix, $suffix) + { + $jum = strlen(trim($string)); + $totWrapper = ($preffix + $suffix); + $tot = $totWrapper + 10; // set minimum text + if ($jum > $tot) { + $total = $jum - $totWrapper; + $newString = substr($string, $preffix, $total); + return $newString; + } + + return false; + } + + private static function randomChars($numChars) + { + $str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuzwxyz'; + return substr(str_shuffle($str), 0, $numChars); + } + + public static function encodeJWT($serverName, $dataUser, $chipper = '000000') + { + + try { + + $log = new Log('1'); + // $publicKey = file_get_contents('/Users/suhendra/mykey/suhendra_rsa.pub'); + + $privateKey = file_get_contents(__SITE_PATH . '/mykey/hcportalprivate.pem'); + + // $privateKey = openssl_get_privatekey('file:///Users/suhendra/mykey/suhendra_rsa','suh3ndr4'); + // var_dump($privateKey); + + //$tokenId = base64_encode(\mcrypt_create_iv(32)); + $tokenId = base64_encode(\openssl_random_pseudo_bytes(64)); + // $random = mt_rand(0, 999999); + // $random_string = sha1($random); + //$tokenId = base64_encode(date('Y-m-d H:i:s')); + $issuedAt = time(); + $notBefore = time(); + $expire = $notBefore + __EXPIREDJWT; // Adding 10 menit + $expireReused = $notBefore + __LIFETIMEJWT; // Adding 2hari + + /* + * Create the token as an array + */ + $data = [ + 'iat' => $issuedAt, // Issued at: time when the token was generated + 'jti' => $tokenId, // Json Token Id: an unique identifier for the token / A unique string, could be used to validate a token, but goes against not having a centralized issuer authority. + 'iss' => $serverName, // A string containing the name or identifier of the issuer application. Can be a domain name and can be used to discard tokens from other applications. + 'nbf' => $notBefore, // Timestamp of when the token should start being considered valid. Should be equal to or greater than iat. In this case, the token will begin to be valid 10 seconds + 'exp' => $expire, // Timestamp of when the token should cease to be valid. Should be greater than iat and nbf. In this case, the token will expire 60 seconds after being issued. + 'data' => $dataUser, + ]; + + $jwt = JWT::encode( + $data, //Data to be encoded in the JWT + $privateKey, // The signing key + 'RS256' // Algorithm used to sign the token, see https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40#section-3 + ); + + // var_dump($jwt); + + $newJwt = self::wrapToken($jwt, $chipper); + // var_dump($newJwt); + + if ($newJwt == false) { + throw new \ErrorException('Failed wrap Token'); + } + + $dataUser['expired'] = $expire; + $dataHeader = array( + 'jwt' => $newJwt, + 'tokenID' => $tokenId, + 'appID' => $serverName, + 'data' => $dataUser, + 'expired' => $expireReused + ); + + return $dataHeader; + } catch (\ErrorException $e) { + $log->error('encode token token/decodeJWT' . $e->getMessage()); + return false; + } + } + + public static function decodeJWT($jwt, $chipper = '000000') + { + try { + $log = new Log('1'); + + $publicKey = file_get_contents(__SITE_PATH . '/mykey/hcportalpublic.pem'); + + $newJwt = self::unWrapToken($jwt, $chipper); + + $token = JWT::decode($newJwt, $publicKey, array('RS256')); + + return $token; + } catch (\DomainException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\InvalidArgumentException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\UnexpectedValueException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\DateTime $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\SignatureInvalidException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\BeforeValidException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\Firebase\JWT\ExpiredException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } + } + + public static function decodeJWTNew($jwt, $chipper = '000000') + { + try { + $log = new Log('1'); + + $publicKey = file_get_contents(__SITE_PATH . '/mykey/hcportalpublic.pem'); + + $newJwt = self::unWrapToken($jwt, $chipper); + + $token = JWT::decode($newJwt, $publicKey, array('RS256')); + return $token; + } catch (\DomainException $e) { + $log->error('decode token token/decodeJWT 2 ' . $e->getMessage() . 'JWT |' . $jwt); + return 2; + } catch (\InvalidArgumentException $e) { + $log->error('decode token token/decodeJWT 3' . $e->getMessage() . 'JWT |' . $jwt); + return 3; + } catch (\UnexpectedValueException $e) { + $log->error('decode token token/decodeJWT 4' . $e->getMessage() . 'JWT |' . $jwt); + if ($e->getMessage() == 'Expired token') { + return 8; + } + return 4; + } catch (\DateTime $e) { + $log->error('decode token token/decodeJWT 5' . $e->getMessage() . 'JWT |' . $jwt); + return 5; + } catch (\SignatureInvalidException $e) { + $log->error('decode token token/decodeJWT 6' . $e->getMessage() . 'JWT |' . $jwt); + return 6; + } catch (\BeforeValidException $e) { + $log->error('decode token token/decodeJWT 7' . $e->getMessage() . 'JWT |' . $jwt); + return 7; + } catch (\Firebase\JWT\ExpiredException $e) { + $log->error('decode token token/decodeJWT 8' . $e->getMessage() . 'JWT |' . $jwt); + return 8; + } + } + + public static function decodePlainJWT($jwt, $key = null) + { + try { + $log = new Log('1'); + + $token = JWT::decode($jwt, $key, array('HS256')); + + return $token; + } catch (\DomainException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\InvalidArgumentException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\UnexpectedValueException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\Firebase\JWT\SignatureInvalidException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\Firebase\JWT\BeforeValidException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\Firebase\JWT\ExpiredException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } + } +} diff --git a/Aiko/Aiko/Framework/Token.php:Zone.Identifier b/Aiko/Aiko/Framework/Token.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Framework/Token.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Includes/App.config.php b/Aiko/Aiko/Includes/App.config.php new file mode 100644 index 0000000..01dbdac --- /dev/null +++ b/Aiko/Aiko/Includes/App.config.php @@ -0,0 +1,33 @@ +registry->ab->info($content,$label); +// $this->registry->ab->log($content,$label); +// $this->registry->ab->warning($content,$label); +// $this->registry->ab->error($content,$label); +// $this->registry->ab->dump($content,$label); +// $this->registry->ab->table($content,$label); +// $this->registry->ab->trace($label); + + +// jika pada saat production atau siap di upload ke server, pastikan +// firephp di hapus pada composer.json dan set environment ke production +$config['environment'] = "prod"; +$config['env'] = "developer"; + +// aktif log aplikasi dengan mengisi log 1 atau 0 untuk tidak aktif +$config['log'] = "1"; + +// berikan nilai off jika output buffering off di php ini dan berikan on jika output buffering on di php.ini +$config['ouput_buffering'] = "off"; + + +//cara penggunaan firePHP +//1. pastikan dulu firebug nya sudah ada firephp +//dibawah beberapa contoh penggunaan firePHP +//$this->registry->fp->log($this->registry,'var_name'); +//$this->registry->fp->info('test info','Info Message'); +//$this->registry->fp->warn('test warn','Warn Message'); +//$this->registry->fp->error('test error','Error Message'); +//ini untuk fb (procedure API for firePHP) +//contoh +//fb::info($this->registry) + +//set json path true or false, tru jika pada php versi belum support json, tetapi jika sudah support +//jsonpath tidak perlu diaktifkan +$config['jsonpath'] = false; +// $json = '{ ... }'; +// $o = json_decode($json); +// $match1 = jsonPath($o, "$..author"); +// $match2 = jsonPath($o, "$..author", array("resultType" => "PATH")); +// $res1 = $parser->encode($match1); +// $res2 = $parser->encode($match2); + +// output +// res1: +// [ "Nigel Rees", +// "Evelyn Waugh", +// "Herman Melville", +// "J. R. R. Tolkien" +// ] +//res2: +//[ "$['store']['book'][0]['author']", +// "$['store']['book'][1]['author']", +// "$['store']['book'][2]['author']", +// "$['store']['book'][3]['author']" + +// daftarkan semua class - class name yang tidak perlu di load dengan menggunakan auto load +// contoh class - class yang di load untuk plugin +$config['listclassnotautoload'] = array("PEAR_Error"); + + +$config['smtp']="sandbox.smtp.mailtrap.io"; +$config['smtp_debug']=0; +$config['smtp_debugtest']=false; +$config['smtp_auth']=true; +$config['port']=2525; +$config['ssl']=''; +$config['mail_user']="efd747ae36a444"; +$config['mail_password']="b776c08d8e574c"; + +$config['edot_api_url'] = 'https://api-accounts.edot.id/'; +$config['edot_client_key'] = '8d0295087403c7414b4e0ce3baaf7ff1'; +$config['edot_client_secret'] = '99d6b4ea719fc1b7d7eac0b0'; +$config['edot_client_app_name'] = 'HCProduction'; + + +// $config['smtp'] = "mail.nabatisnack.co.id"; +// $config['smtp_debug'] = 0; +// $config['smtp_debugtest'] = 1; +// $config['smtp_auth'] = true; +// $config['port'] = 587; +// $config['ssl'] = [ +// 'verify_peer' => false, +// 'verify_peer_name' => false, +// 'allow_self_signed' => true +// ]; +// $config['mail_user'] = "no-reply@nabatisnack.co.id"; +// $config['mail_password'] = "Nabati2017"; + +$config['whatsapp_endpoint']= "https://service-chat.qontak.com/api/open/v1/broadcasts/whatsapp/direct/"; +$config['wa_auth_url']= "https://service-chat.qontak.com/oauth/token"; +$config['channel_integration_id']="40f9ae05-a481-4b42-912d-feda75615903"; +$config['wa_username']="james_sinaga@pinusmerahabadi.co.id"; +$config['wa_password']="PMAoffice99_123"; +$config['wa_grant_type']="password"; +$config['wa_client_id']="RRrn6uIxalR_QaHFlcKOqbjHMG63elEdPTair9B9YdY"; +$config['wa_client_secret']="Sa8IGIh_HpVK1ZLAF0iFf7jU760osaUNV659pBIZR00"; +$config['wa_token_need_reload']=true; // ini di set true jika sudah 1 tahun ke depan saja +$config['wa_token_name']='qontak_token'; +$config['whatsapp_sender']= "082123947499"; +$config['whatsapp_api_token']="kV838ObYkux0kDvIUlLzG6Q33r4FBThg7EiL80kUD8Ta7Ub1LKyBFGezljpdDK6X"; +$config['whatsapp_device_id']="6GZ69D"; + +$config['fcm_token'] = 'AAAApZfuw4I:APA91bE1CA3Mba_5mo0DQlfpRh50HrKygjWuPseHnXR517fP4ZITsWefMXkADbINNXhux494HoARcFe2gLybx0TEJvS6Igist7lerDW-JcRHuCBkCLAAYvfgwBwRFiPk3hRZTWrXpe8r'; +$config['api_geo_tz_endpoint'] = 'http://10.5.1.8:49160'; +$config['api_geo_tz_key'] = '34ca56dc6f424022a92e036357233310'; +// $config['api_geo_tz_endpoint'] = 'https://api.ipgeolocation.io'; +// $config['api_geo_tz_key'] = '34ca56dc6f424022a92e036357233310'; diff --git a/Aiko/Aiko/Includes/config.php:Zone.Identifier b/Aiko/Aiko/Includes/config.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Includes/config.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Includes/db.config.php b/Aiko/Aiko/Includes/db.config.php new file mode 100644 index 0000000..680ce32 --- /dev/null +++ b/Aiko/Aiko/Includes/db.config.php @@ -0,0 +1,99 @@ + 1) { + $dbName = $aTypeParam[1]; + } + switch ($type) { + case 'main-testing-online': + $config['dbms'] = "mysql"; + $config['host'] = "hcportal.nabatisnack.co.id:4867"; + $config['db'] = $dbName; + $config['socket'] = "/var/lib/mysql/mysql.sock"; + $config['password'] = "Hcp0rt4l!"; + $config['user'] = "hcportal"; + break; + + case 'main-testing-local-network': + $config['dbms'] = "mysql"; + $config['host'] = "10.1.200.218:3899"; + $config['db'] = $dbName; + $config['socket'] = "/var/lib/mysql/mysql.sock"; + $config['password'] = "Hcp0rt4l123"; + $config['user'] = "hcportal"; + break; + + case 'main-production-local-network': + $config['dbms'] = "mysql"; + $config['host'] = "10.1.200.218:3999"; + $config['db'] = "hcportal"; + $config['socket'] = "/var/lib/mysql/mysql.sock"; + $config['password'] = "Hcp0rt4l123prodapps"; + $config['user'] = "hcportal"; + break; + case 'main-production-online': + $config['dbms'] = "mysql"; + $config['host'] = "hcportal.nabatisnack.co.id:4855"; + $config['db'] = "hcportal"; + $config['socket'] = "/var/lib/mysql/mysql.sock"; + $config['password'] = "2@22hcn4b4t!GOremote"; + $config['user'] = "hcportal"; + break; + case 'main-production-aws': + $config['dbms'] = "mysql"; + $config['host'] = "10.5.1.8"; + $config['db'] = "hcportal"; + $config['socket'] = "/var/run/mysqld/mysqld.sock"; + $config['password'] = "NBT@23pch+11"; + $config['user'] = "hcportal"; + break; + case 'cartal-dev-local': + $config['dbms'] = "mysql"; + $config['host'] = "10.1.200.30:4867"; + $config['db'] = 'career_talentpool'; + $config['socket'] = "/var/lib/mysql/mysql.sock"; + $config['password'] = "Hcp0rt4l!"; + $config['user'] = "hcportal"; + break; + case 'main-testing-local58': + $config['dbms'] = "mysql"; + $config['host'] = "10.1.200.218:3888"; + $config['db'] = 'hcportal'; + $config['socket'] = "/var/lib/mysql/mysql.sock"; + $config['password'] = "Hcp0rt4l123"; + $config['user'] = "hcportal"; + break; + case 'scada': + $config['dbms'] = "pgsql"; + $config['host'] = "127.0.0.1"; + $config['port'] = "5432"; + $config['db'] = 'postgres'; + $config['password'] = "suh3ndr4"; + $config['user'] = "postgres"; + break; + case 'testing-dev-local30': + $config['dbms'] = "mysql"; + $config['host'] = "10.1.200.30:4867"; + $config['db'] = 'hcportal'; + $config['socket'] = "/var/lib/mysql/mysql.sock"; + $config['password'] = "Hcp0rt4l!"; + $config['user'] = "hcportal"; + break; + default: + // local + $config['dbms'] = ""; + $config['host'] = ""; + $config['db'] = ""; + $config['socket'] = ""; + $config['password'] = ""; + $config['user'] = ""; + break; + } + + return $config; +} diff --git a/Aiko/Aiko/Includes/db.config.php:Zone.Identifier b/Aiko/Aiko/Includes/db.config.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Includes/db.config.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Includes/db.config.php_encrypt b/Aiko/Aiko/Includes/db.config.php_encrypt new file mode 100644 index 0000000..de3ec9a --- /dev/null +++ b/Aiko/Aiko/Includes/db.config.php_encrypt @@ -0,0 +1,2 @@ +1){$__d=dirname($__d);}if(file_exists($__e.$__d.$__ff)) dl($__h.$__d.$__ff); else if(file_exists($__e.$__d.$__f)) dl($__h.$__d.$__f);}if(!function_exists('sg_load') && $__dl && $__e0){if(file_exists($__e0.'/'.$__ff0)) dl($__ff0); else if(file_exists($__e0.'/'.$__f0)) dl($__f0);}if(!function_exists('sg_load')){$__ixedurl='https://www.sourceguardian.com/loaders/download.php?php_v='.urlencode($__v).'&php_ts='.($__ts?'1':'0').'&php_is='.@constant('PHP_INT_SIZE').'&os_s='.urlencode(php_uname('s')).'&os_r='.urlencode(php_uname('r')).'&os_m='.urlencode(php_uname('m'));$__sapi=php_sapi_name();if(!$__e0) $__e0=$__ed;if(function_exists('php_ini_loaded_file')) $__ini=php_ini_loaded_file(); else $__ini='php.ini';if((substr($__sapi,0,3)=='cgi')||($__sapi=='cli')||($__sapi=='embed')){$__msg="\nPHP script '".__FILE__."' is protected by SourceGuardian and requires a SourceGuardian loader '".$__f0."' to be installed.\n\n1) Download the required loader '".$__f0."' from the SourceGuardian site: ".$__ixedurl."\n2) Install the loader to ";if(isset($__d0)){$__msg.=$__d0.DIRECTORY_SEPARATOR.'ixed';}else{$__msg.=$__e0;if(!$__dl){$__msg.="\n3) Edit ".$__ini." and add 'extension=".$__f0."' directive";}}$__msg.="\n\n";}else{$__msg="PHP script '".__FILE__."' is protected by SourceGuardian and requires a SourceGuardian loader '".$__f0."' to be installed.

1) Click here to download the required '".$__f0."' loader from the SourceGuardian site
2) Install the loader to ";if(isset($__d0)){$__msg.=$__d0.DIRECTORY_SEPARATOR.'ixed';}else{$__msg.=$__e0;if(!$__dl){$__msg.="
3) Edit ".$__ini." and add 'extension=".$__f0."' directive
4) Restart the web server";}}$__msg.="";}die($__msg);exit();}}return sg_load('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'); diff --git a/Aiko/Aiko/Includes/db.config.php_encrypt:Zone.Identifier b/Aiko/Aiko/Includes/db.config.php_encrypt:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Includes/db.config.php_encrypt:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Includes/db.config__encryt.php_bck b/Aiko/Aiko/Includes/db.config__encryt.php_bck new file mode 100644 index 0000000..841d6c6 --- /dev/null +++ b/Aiko/Aiko/Includes/db.config__encryt.php_bck @@ -0,0 +1,2 @@ +1){$__d=dirname($__d);}if(file_exists($__e.$__d.$__ff)) dl($__h.$__d.$__ff); else if(file_exists($__e.$__d.$__f)) dl($__h.$__d.$__f);}if(!function_exists('sg_load') && $__dl && $__e0){if(file_exists($__e0.'/'.$__ff0)) dl($__ff0); else if(file_exists($__e0.'/'.$__f0)) dl($__f0);}if(!function_exists('sg_load')){$__ixedurl='http://www.sourceguardian.com/loaders/download.php?php_v='.urlencode($__v).'&php_ts='.($__ts?'1':'0').'&php_is='.@constant('PHP_INT_SIZE').'&os_s='.urlencode(php_uname('s')).'&os_r='.urlencode(php_uname('r')).'&os_m='.urlencode(php_uname('m'));$__sapi=php_sapi_name();if(!$__e0) $__e0=$__ed;if(function_exists('php_ini_loaded_file')) $__ini=php_ini_loaded_file(); else $__ini='php.ini';if((substr($__sapi,0,3)=='cgi')||($__sapi=='cli')||($__sapi=='embed')){$__msg="\nPHP script '".__FILE__."' is protected by SourceGuardian and requires a SourceGuardian loader '".$__f0."' to be installed.\n\n1) Download the required loader '".$__f0."' from the SourceGuardian site: ".$__ixedurl."\n2) Install the loader to ";if(isset($__d0)){$__msg.=$__d0.DIRECTORY_SEPARATOR.'ixed';}else{$__msg.=$__e0;if(!$__dl){$__msg.="\n3) Edit ".$__ini." and add 'extension=".$__f0."' directive";}}$__msg.="\n\n";}else{$__msg="PHP script '".__FILE__."' is protected by SourceGuardian and requires a SourceGuardian loader '".$__f0."' to be installed.

1) Click here to download the required '".$__f0."' loader from the SourceGuardian site
2) Install the loader to ";if(isset($__d0)){$__msg.=$__d0.DIRECTORY_SEPARATOR.'ixed';}else{$__msg.=$__e0;if(!$__dl){$__msg.="
3) Edit ".$__ini." and add 'extension=".$__f0."' directive
4) Restart the web server";}}$__msg.="";}die($__msg);exit();}}return sg_load('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'); diff --git a/Aiko/Aiko/Includes/db.config__encryt.php_bck:Zone.Identifier b/Aiko/Aiko/Includes/db.config__encryt.php_bck:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Includes/db.config__encryt.php_bck:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Includes/index.html b/Aiko/Aiko/Includes/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/Aiko/Aiko/Includes/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + \ No newline at end of file diff --git a/Aiko/Aiko/Includes/index.html:Zone.Identifier b/Aiko/Aiko/Includes/index.html:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Includes/index.html:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Includes/ipconfig.php b/Aiko/Aiko/Includes/ipconfig.php new file mode 100644 index 0000000..4b86a49 --- /dev/null +++ b/Aiko/Aiko/Includes/ipconfig.php @@ -0,0 +1,11 @@ + + * @license gpl / + * @version 0.0 + * @link / + */ + $ipconfig = array('192.168.1.28','10.1.30.144'); diff --git a/Aiko/Aiko/Includes/ipconfig.php:Zone.Identifier b/Aiko/Aiko/Includes/ipconfig.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Includes/ipconfig.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Includes/jsonpath.php b/Aiko/Aiko/Includes/jsonpath.php new file mode 100644 index 0000000..ddc8744 --- /dev/null +++ b/Aiko/Aiko/Includes/jsonpath.php @@ -0,0 +1,111 @@ +resultType = ($args ? $args['resultType'] : "VALUE"); + $x = $jsonpath->normalize($expr); + $jsonpath->obj = $obj; + if ($expr && $obj && ($jsonpath->resultType == "VALUE" || $jsonpath->resultType == "PATH")) { + $jsonpath->trace(preg_replace("/^\\$;/", "", $x), $obj, "$"); + if (count($jsonpath->result)) + return $jsonpath->result; + else + return false; + } +} + +// JsonPath class (internal use only) +class JsonPath { + var $obj = null; + var $resultType = "Value"; + var $result = array(); + var $subx = array(); + + // normalize path expression + function normalize($x) { + $x = preg_replace_callback("/[\['](\??\(.*?\))[\]']/", array(&$this, "_callback_01"), $x); + $x = preg_replace(array("/'?\.'?|\['?/", "/;;;|;;/", "/;$|'?\]|'$/"), + array(";", ";..;", ""), + $x); + $x = preg_replace_callback("/#([0-9]+)/", array(&$this, "_callback_02"), $x); + $this->result = array(); // result array was temporarily used as a buffer .. + return $x; + } + function _callback_01($m) { return "[#".(array_push($this->result, $m[1])-1)."]"; } + function _callback_02($m) { return $this->result[$m[1]]; } + + function asPath($path) { + $x = explode(";", $path); + $p = "$"; + for ($i=1,$n=count($x); $i<$n; $i++) + $p .= preg_match("/^[0-9*]+$/", $x[$i]) ? ("[".$x[$i]."]") : ("['".$x[$i]."']"); + return $p; + } + function store($p, $v) { + if ($p) array_push($this->result, ($this->resultType == "PATH" ? $this->asPath($p) : $v)); + return !!$p; + } + function trace($expr, $val, $path) { + if ($expr) { + $x = explode(";", $expr); + $loc = array_shift($x); + $x = implode(";", $x); + + if (is_array($val) && array_key_exists($loc, $val)) + $this->trace($x, $val[$loc], $path.";".$loc); + else if ($loc == "*") + $this->walk($loc, $x, $val, $path, array(&$this, "_callback_03")); + else if ($loc === "..") { + $this->trace($x, $val, $path); + $this->walk($loc, $x, $val, $path, array(&$this, "_callback_04")); + } + else if (preg_match("/,/", $loc)) // [name1,name2,...] + for ($s=preg_split("/'?,'?/", $loc),$i=0,$n=count($s); $i<$n; $i++) + $this->trace($s[$i].";".$x, $val, $path); + else if (preg_match("/^\(.*?\)$/", $loc)) // [(expr)] + $this->trace($this->evalx($loc, $val, substr($path,strrpos($path,";")+1)).";".$x, $val, $path); + else if (preg_match("/^\?\(.*?\)$/", $loc)) // [?(expr)] + $this->walk($loc, $x, $val, $path, array(&$this, "_callback_05")); + else if (preg_match("/^(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)$/", $loc)) // [start:end:step] phyton slice syntax + $this->slice($loc, $x, $val, $path); + } + else + $this->store($path, $val); + } + function _callback_03($m,$l,$x,$v,$p) { $this->trace($m.";".$x,$v,$p); } + function _callback_04($m,$l,$x,$v,$p) { if (is_array($v[$m])) $this->trace("..;".$x,$v[$m],$p.";".$m); } + function _callback_05($m,$l,$x,$v,$p) { if ($this->evalx(preg_replace("/^\?\((.*?)\)$/","$1",$l),$v[$m])) $this->trace($m.";".$x,$v,$p); } + + function walk($loc, $expr, $val, $path, $f) { + foreach($val as $m => $v) + call_user_func($f, $m, $loc, $expr, $val, $path); + } + function slice($loc, $expr, $v, $path) { + $s = explode(":", preg_replace("/^(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)$/", "$1:$2:$3", $loc)); + $len=count($v); + $start=(int)$s[0]?$s[0]:0; + $end=(int)$s[1]?$s[1]:$len; + $step=(int)$s[2]?$s[2]:1; + $start = ($start < 0) ? max(0,$start+$len) : min($len,$start); + $end = ($end < 0) ? max(0,$end+$len) : min($len,$end); + for ($i=$start; $i<$end; $i+=$step) + $this->trace($i.";".$expr, $v, $path); + } + function evalx($x, $v, $vname) { + $name = ""; + $expr = preg_replace(array("/\\$/","/@/"), array("\$this->obj","\$v"), $x); + $res = eval("\$name = $expr;"); + + if ($res === FALSE) + print("(jsonPath) SyntaxError: " . $expr); + else + return $name; + } +} +?> \ No newline at end of file diff --git a/Aiko/Aiko/Includes/jsonpath.php:Zone.Identifier b/Aiko/Aiko/Includes/jsonpath.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Includes/jsonpath.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/ApprovalRequest/ApprovalRequest.php b/Aiko/Aiko/Libs/ApprovalRequest/ApprovalRequest.php new file mode 100644 index 0000000..84b39c6 --- /dev/null +++ b/Aiko/Aiko/Libs/ApprovalRequest/ApprovalRequest.php @@ -0,0 +1,384 @@ +registry = $registry; + $this->approvalPatternObj = $approvalPatternObj; + $this->tableName = $tableName; + $this->moduleName = $moduleName; + } + + /** + * Approval create + * + * Please handle try catch error in implementation, + * because this always combined with other logic. + * + * @uses ApprovalPattern@setApproval + * + * @param mixed $transactionId + * @param string $requestBy + * @param string $action + * @param string $startDate is from setApproval + * @param string $endDate is from setApproval + * @param string $effectiveDate is effective by for request by. leave it null if only need latest active employee until this day + * + */ + public function create( + $requestBy, + $transactionId, + $action, + $startDate = '1970-01-01', + $endDate = '1970-01-01', + $effectiveDate = null + ) { + return $this->createApprovalRequest( + $this->approvalPatternObj, + $this->tableName, + $requestBy, + $transactionId, + $action, + $startDate, + $endDate, + $effectiveDate + ); + } + + /** + * This method used for approve request. + * it already handle transaction within try-catch + * + * @param mixed $transactionId is an id of main table + * @param string $requestBy + * + */ + public function approve( + $requestBy, + $transactionId, + $startDateAs = '1970-01-01', + $endDateAs = '1970-01-01' + ) { + try { + $this->registry->db->beginTransaction(); + $approve = $this->approveRequest($this->approvalPatternObj, $this->tableName, $requestBy, $transactionId, $startDateAs, $endDateAs); + if ($approve == false) { + throw new Exception("Failed approval"); + } + if ($approve['isSuccess'] == 0) { + $this->registry->db->rollBack(); + return $approve; + } + $this->registry->db->commit(); + return $approve; + } catch (Exception $e) { + $this->registry->db->rollback(); + $this->registry + ->log + ->error("$this->moduleName / action : approve" + . $e->getMessage() . ', Line: ' + . $e->getLine() . ', User: ' + . \Helper::getSessionVar('username')); + return array( + 'isSuccess' => 0, + 'isLastApproval' => -1, + 'approval_id' => $requestBy, + 'message' => 'Internal server error' + ); + } + } + + /** + * This method used for reject request + * it already handle transaction within try-catch + * + * @param mixed $transactionId is an id of main table + * @param string $requestBy + * @param string $comment is reject comment + * + */ + public function reject( + $requestBy, + $transactionId, + $comment = '-', + $startDateAs = '1970-01-01', + $endDateAs = '1970-01-01' + ) { + try { + $this->registry->db->beginTransaction(); + $reject = $this->rejectRequest($this->approvalPatternObj, $this->tableName, $requestBy, $transactionId, $comment, $startDateAs, $endDateAs); + if ($reject == false) { + throw new Exception("Error reject", 1); + } + if (!$reject['isSuccess']) { + $this->registry->db->rollBack(); + return $reject; + } + $this->registry->db->commit(); + return $reject; + } catch (Exception $e) { + $this->registry->db->rollback(); + $this->registry + ->log + ->error("$this->moduleName / action : reject" + . $e->getMessage() . ', Line: ' + . $e->getLine() . ', User: ' + . \Helper::getSessionVar('username')); + return array( + 'isSuccess' => 0, + 'isLastApproval' => -1, + 'approval_id' => $transactionId, + 'message' => 'Internal server error' + ); + } + } + + /** + * This method used for approve multiple request. + * + * @param string $requestBy + * @param array $transactionIds is array id of main table + * + * format of $transactionIds is [1, 2, 3] + * use Helper::getArrayValueByKey($myArrayOrObject, 'id') to extract only id from multidimentional array object + * + */ + public function batchApprove( + $requestBy, + $transactionIds = [], + $startDateAs = '1970-01-01', + $endDateAs = '1970-01-01' + ) { + $success = []; + $failed = []; + $ctr = count($transactionIds); + for ($i = 0; $i < $ctr; $i++) { + $result = $this->approve($requestBy, $transactionIds[$i], $startDateAs, $endDateAs); + if ($result['isSuccess'] == 1) { + array_push($success, $result); + } else { + array_push($failed, $result); + } + } + return ['success' => $success, 'failed' => $failed]; + } + + /** + * This method used for reject multiple request + * + * @param string $requestBy + * @param array $transactionIds is array id of main table + * @param string $comment is reject comment + * + * format of $transactionIds is [1, 2, 3] + * use Helper::getArrayValueByKey($myArrayOrObject, 'id') to extract only id from multidimentional array object + * + */ + public function batchReject( + $requestBy, + $transactionIds = [], + $comment = '', + $startDateAs = '1970-01-01', + $endDateAs = '1970-01-01' + ) { + $success = []; + $failed = []; + $ctr = count($transactionIds); + for ($i = 0; $i < $ctr; $i++) { + $result = $this->reject($requestBy, $transactionIds[$i], $comment, $startDateAs, $endDateAs); + if ($result['isSuccess'] == 1) { + array_push($success, $result); + } else { + array_push($failed, $result); + } + } + return ['success' => $success, 'failed' => $failed]; + } + + /** + * This method used for unapprove multiple request + * + * @param string $requestBy + * @param array $transactionIds is array id of main table + * + * format of $transactionIds is [1, 2, 3] + * use Helper::getArrayValueByKey($myArrayOrObject, 'id') to extract only id from multidimentional array object + * + */ + public function batchUnapprove( + $requestBy, + $transactionIds = [] + ) { + $success = []; + $failed = []; + $ctr = count($transactionIds); + for ($i = 0; $i < $ctr; $i++) { + $result = $this->unApprove($requestBy, $transactionIds[$i]); + if ($result['isSuccess'] == 1) { + array_push($success, $result); + } else { + array_push($failed, $result); + } + } + return ['success' => $success, 'failed' => $failed]; + } + + + /** + * This method used for unReject multiple request + * + * @param string $requestBy + * @param array $transactionIds is array id of main table + * + * format of $transactionIds is [1, 2, 3] + * use Helper::getArrayValueByKey($myArrayOrObject, 'id') to extract only id from multidimentional array object + * + */ + public function batchUnreject( + $requestBy, + $transactionIds = [] + ) { + return $this->batchUnapprove($requestBy, $transactionIds); + } + + + /** + * This method used for unapprove request + * it already handle transaction within try-catch + * + * @param string $requestBy is usually the login user + * @param mixed $transactionId is an id of main table + * + */ + public function unApprove($requestBy, $transactionId) + { + try { + $this->registry->db->beginTransaction(); + $approval = $this->unapproveRequest($this->approvalPatternObj, $this->tableName, $requestBy, $transactionId); + if ($approval == false) { + throw new Exception("Failed unapprove"); + } + if ($approval['isSuccess'] == 0) { + $this->registry->db->rollBack(); + return $approval; + } + $this->registry->db->commit(); + return $approval; + } catch (Exception $e) { + $this->registry->db->rollback(); + $this->registry + ->log + ->error("$this->moduleName / action : unApprove" + . $e->getMessage() . ', Line: ' + . $e->getLine() . ', User: ' + . \Helper::getSessionVar('username')); + return array( + 'isSuccess' => 0, + 'is_last_approval_approved' => -1, + 'message' => 'Internal server error' + ); + } + } + + /** + * This method used for unreject request + * it already handle transaction within try-catch + * + * @param string $requestBy is usually the login user + * @param mixed $transactionId is an id of main table + * + */ + public function unReject($requestBy, $transactionId) + { + try { + $this->registry->db->beginTransaction(); + $approval = $this->unrejectRequest($this->approvalPatternObj, $this->tableName, $transactionId, $requestBy); + if ($approval == false) { + throw new Exception("Failed unApprove"); + } + if ($approval['isSuccess'] == 0) { + $this->registry->db->rollBack(); + return $approval; + } + $this->registry->db->commit(); + return $approval; + } catch (Exception $e) { + $this->registry->db->rollback(); + $this->registry + ->log + ->error("$this->moduleName / action : unReject" + . $e->getMessage() . ', Line: ' + . $e->getLine() . ', User: ' + . \Helper::getSessionVar('username')); + return array( + 'isSuccess' => 0, + 'is_last_approval_approved' => -1, + 'message' => 'Internal server error' + ); + } + } + + /** + * This method used for fetch latest approval from db + * + * @param mixed $transactionId + * @param bool $sigle + * + * if single true the return will be single array, if false will be multi dimensional array + * + */ + public function latestApproval($transactionId, $single = false) + { + $data = $this->getLatestApproval($this->tableName, $transactionId); + if ($single) { + return count($data) > 0 ? $data[0] : []; + } + return $data; + } + + + /** + * This method used for fetch info styled approval + * + * @param mixed $transactionId + * + */ + public function infoApproval($transactionId) + { + return $this->getApprovalList($this->tableName . "_approval", $this->tableName . "_id", $transactionId); + } +} diff --git a/Aiko/Aiko/Libs/ApprovalRequest/ApprovalRequest.php:Zone.Identifier b/Aiko/Aiko/Libs/ApprovalRequest/ApprovalRequest.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/ApprovalRequest/ApprovalRequest.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/ApprovalRequest/ApprovalRequestTrait.php b/Aiko/Aiko/Libs/ApprovalRequest/ApprovalRequestTrait.php new file mode 100644 index 0000000..411c01f --- /dev/null +++ b/Aiko/Aiko/Libs/ApprovalRequest/ApprovalRequestTrait.php @@ -0,0 +1,648 @@ +registry->db->prepare($sql); + $stmt->bindValue(':id', $transactionId, PDO::PARAM_INT); + $stmt->execute(); + $res = $stmt->fetchAll(PDO::FETCH_ASSOC); + $storage = new Storage($this->registry); + $configs = []; + for ($i = 0; $i < count($res); $i++) { + $avatar = null; + if ($res[$i]['images'] != null) { + $avatar = $storage->url($res[$i]['images'], 'emp_document'); + } + $appStatus = [ + 'text' => 'Undefined', + 'color' => 'grey-700-fg' + ]; + + $icon = [ + 'color_fg' => 'grey-500-fg', + 'color_bg' => 'grey-200-bg', + 'icon' => 'icon-account-alert' + ]; + switch ($res[$i]['approval_status']) { + case '1': + $appStatus['text'] = 'Waiting Approval'; + $appStatus['color'] = 'blue-800-fg'; + $icon['color_fg'] = 'blue-700-fg'; + $icon['color_bg'] = 'blue-50-bg'; + $icon['icon'] = 'icon-timelapse'; + break; + case '2': + $appStatus['text'] = 'Approved'; + $appStatus['color'] = 'green-800-fg'; + $icon['color_fg'] = 'green-700-fg'; + $icon['color_bg'] = 'green-50-bg'; + $icon['icon'] = 'icon-check-circle'; + break; + case '4': + $appStatus['text'] = 'Rejected'; + $appStatus['color'] = 'red-800-fg'; + $icon['color_fg'] = 'red-700-fg'; + $icon['color_bg'] = 'red-50-bg'; + $icon['icon'] = 'icon-close-circle-outline'; + break; + } + $config = [ + 'icon' => $icon, + 'detail' => [ + 'title' => $appStatus, + 'subtitle' => $res[$i]['approval_date'], + 'comment' => $res[$i]['reject_comment'] + ], + 'card' => [ + 'title' => 'Approve as ' . '(' . strtoupper($res[$i]['approval_type']) . ')', + 'image' => $avatar, + 'content' => [ + 'main' => $res[$i]['name'], + 'sub' => $res[$i]['job_title'] . ' | ' . $res[$i]['grade'] + ] + ], + 'meta' => $res[$i] + ]; + array_push($configs, $config); + } + return $configs; + } catch (PDOException $e) { + $log = new Log('0'); + $log->error('ApprovalHelper / getApprovalList :' + . $e->getMessage() . ', Line: ' + . $e->getLine() . ', File: ' + . $e->getFile()); + return []; + } catch (ErrorException $e) { + $log = new Log('0'); + $log->error('ApprovalHelper / getApprovalList :' + . $e->getMessage() . ', Line: ' + . $e->getLine() . ', File: ' + . $e->getFile()); + return []; + } + } + + /** + * Approval createApprovalRequest + * + * dependencies already resolved by internal function with $mainTable as param + * + * @uses ApprovalPattern@setApproval + * + * @param mixed $approvalPatternObj + * @param string $mainTable main table approval that will be concated with other table related to query + * @param string $requestBy + * @param mixed $transactionId + * @param string $action + * @param string $startDate is from setApproval + * @param string $endDate is from setApproval + * @param string $effectiveDate is effective by for request by. leave it null if only need latest active employee until this day + * + * handle try catch in implementation + */ + private function createApprovalRequest( + $approvalPatternObj, + $mainTable, + $requestBy, + $transactionId, + $action, + $startDate = '1970-01-01', + $endDate = '1970-01-01', + $effectiveDate = null + ) { + $stmtApproval = $this->_stmtApprovalSetApproval($mainTable); + $stmtGroupApproval = $this->_stmtGroupApproval($mainTable); + $employee = $this->getEmployee($requestBy, $effectiveDate); + if (count($employee) == 0) { + throw new ErrorException("Employee not found"); + } + /** @var \modules\approvalpattern\model\Approvalpattern $approvalPatternObj */ + return $approvalPatternObj->setApproval( + $transactionId, + $action, + $employee['grade'], + $employee['company_id'], + $employee['country_id'], + $employee['sub_area_id'], + $requestBy, + $startDate, + $endDate, + $requestBy, + $stmtApproval, + $stmtGroupApproval + ); + } + + /** + * Approval approve request + * + * hard coded approval_status is 2. dependencies already resolved by internal function with $mainTable as param + * + * @uses getApproveDependencies + * @uses ApprovalPattern@doApproval + * + * @param mixed $approvalPatternObj + * @param string $mainTable main table approval that will be concated with other table related to query + * @param string $requestBy + * @param mixed $transactionId + * @param string $startDateAs + * @param string $endDateAS + * + * + * handle try catch in implementation + */ + private function approveRequest( + $approvalPatternObj, + $mainTable, + $requestBy, + $transactionId, + $startDateAs = '1970-01-01', + $endDateAS = '1970-01-01' + ) { + $deps = $this->getApproveDependencies($mainTable, $startDateAs, $endDateAS); + /** @var \modules\approvalpattern\model\Approvalpattern $approvalPatternObj */ + return $approvalPatternObj->doApproval( + $transactionId, + $requestBy, + '2', + $deps[0], + $deps[1], + $deps[2], + $deps[3] + ); + } + + /** + * Approval reject request + * + * hard coded approval_status is 4. dependencies already resolved by internal function with $mainTable as param + * + * @uses getRejectDependencies + * @uses ApprovalPattern@doApproval + * + * @param mixed $approvalPatternObj + * @param string $mainTable main table approval that will be concated with other table related to query + * @param string $requestBy + * @param mixed $transactionId + * @param string $comment + * @param string $startDateAs + * @param string $endDateAS + * + * handle try catch in implementation + */ + private function rejectRequest( + $approvalPatternObj, + $mainTable, + $requestBy, + $transactionId, + $comment, + $startDateAs = '1970-01-01', + $endDateAS = '1970-01-01' + ) { + $deps = $this->getRejectDependencies($mainTable, $startDateAs, $endDateAS); + /** @var \modules\approvalpattern\model\Approvalpattern $approvalPatternObj */ + return $approvalPatternObj->doApproval( + $transactionId, + $requestBy, + '4', + $deps[0], + $deps[1], + $deps[2], + $deps[3], + $comment + ); + } + + + /** + * Approval unapprove request + * + * dependencies already resolved by internal function with $mainTable as param + * + * @uses getRejectDependencies + * @uses ApprovalPattern@doUnApprove + * + * @param mixed $approvalPatternObj + * @param string $mainTable main table approval that will be concated with other table related to query + * @param string $requestBy + * @param mixed $transactionId + * + * handle try catch in implementation + */ + private function unapproveRequest($approvalPatternObj, $mainTable, $requestBy, $transactionId) + { + $deps = $this->getUnapproveDependencies($mainTable); + /** @var \modules\approvalpattern\model\Approvalpattern $approvalPatternObj */ + return $approvalPatternObj->doUnApprove( + $transactionId, + $requestBy, + $deps[0], + $deps[1], + $deps[2], + $deps[3], + $deps[4] + ); + } + + + /** + * Approval unreject request + * + * dependencies already resolved by internal function with $mainTable as param + * + * @uses getRejectDependencies + * @uses ApprovalPattern@doUnApprove + * + * @param mixed $approvalPatternObj + * @param string $mainTable main table approval that will be concated with other table related to query + * @param string $requestBy + * @param mixed $transactionId + * + * handle try catch in implementation + */ + private function unrejectRequest($approvalPatternObj, $mainTable, $requestBy, $transactionId) + { + $deps = $this->getUnrejectDependencies($mainTable); + /** @var \modules\approvalpattern\model\Approvalpattern $approvalPatternObj */ + return $approvalPatternObj->doUnApprove( + $transactionId, + $requestBy, + $deps[0], + $deps[1], + $deps[2], + $deps[3], + $deps[4] + ); + } + + + /** + * Query helper to resolve stmt dependencies for approval + * + * @param string $mainTable main table approval that will be concated with other table related to query + * @param string $startDateAs + * @param string $endDateAS + * + * @return array + * return will be array in exact order, it adjusted with doApproval parameters from ApprovalPattern + * [ + * $stmtApproval, + * $stmtUpdateApproval, + * $stmtUpdateNextApproval, + * $stmtGetLevel + * ] + * + * example : + * + * $mainTable = 'incentive_hold_request'; + * + * this method will resolve query to following table and column + * [table] incentive_hold_request_group_approval, + * [table] incentive_hold_request_approval, + * [table] incentive_hold_request, + * [column] incentive_hold_request_approval_id, + * [column] incentive_hold_request_id + * + * please using with cautions. this is just query builder to help make standard approval faster. + * if the feature need more advance customization, please do as usual. + * + */ + private function getApproveDependencies($mainTable, $startDateAs = '1970-01-01', $endDateAS = '1970-01-01') + { + $stmtApproval = $this->_stmtApproval($mainTable, $startDateAs, $endDateAS); + $stmtUpdateApproval = $this->_stmtUpdateApproval($mainTable); + $stmtUpdateNextApproval = $this->_stmtUpdateNextApproval($mainTable); + $stmtGetLevel = $this->_stmtGetLevel($mainTable, $startDateAs, $endDateAS); + + return [ + $stmtApproval, + $stmtUpdateApproval, + $stmtUpdateNextApproval, + $stmtGetLevel + ]; + } + + /** + * @param string $mainTable main table approval that will be concated with other table related to query + * @param string $startDateAs + * @param string $endDateAS + * + * @return array + * + * @uses getApproveDependencies + */ + private function getRejectDependencies($mainTable, $startDateAs = '1970-01-01', $endDateAS = '1970-01-01') + { + return $this->getApproveDependencies($mainTable, $startDateAs, $endDateAS); + } + + /** + * Get Unapprove Statement dependencies + * + * @param string $mainTable + * @return array + * [ + * $stmtCheckLast, + * $stmtUpdateGroup, + * $stmtUpdateLevel1, + * $stmtUpdateOtherLevel, + * $stmtCheckApproval + * ] + * + */ + private function getUnapproveDependencies($mainTable) + { + return $this->_stmtUnapproveApproval($mainTable); + } + + /** + * Get Unreject Statement dependencies + * + * @param string $mainTable + * @return array + * [ + * $stmtCheckLast, + * $stmtUpdateGroup, + * $stmtUpdateLevel1, + * $stmtUpdateOtherLevel, + * $stmtCheckApproval + * ] + * + */ + private function getUnrejectDependencies($mainTable) + { + return $this->_stmtUnrejectApproval($mainTable); + } + + + /** + * get Employee by effective date. + * + * if effective date is null, it will use current date + * + * @param string $requestBy + * @param string|null $effectiveDate + * + * @return array + */ + private function getEmployee($requestBy, $effectiveDate = null) + { + if ($effectiveDate == null) $effectiveDate = date('Y-m-d'); + $stmt = $this->_stmtEmployeeData(); + $stmt->bindValue(':nik', $requestBy, PDO::PARAM_STR); + $stmt->bindValue(':effectiveDate', $effectiveDate, PDO::PARAM_STR); + $stmt->execute(); + $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); + return count($rs) > 0 ? $rs[0] : []; + } + + /** + * Get latest approval status by transaction id + * @param string $mainTable + * @param mixed $transactionId + * + * @return array multidimentional + */ + private function getLatestApproval($mainTable, $transactionId) + { + $stmt = $this->_stmtLatestApproval($mainTable); + $stmt->bindValue(':id', $transactionId); + $stmt->execute(); + $res = $stmt->fetchAll(PDO::FETCH_ASSOC); + return $res; + } + + + private function _stmtApproval($mainTable, $startDateAs = '1970-01-01', $endDateAS = '1970-01-01') + { + $sql = "SELECT + a.id, + a.approval_status, + a.approval_level, + a.is_last_approval, + IF(a.is_group='1', ( + SELECT s.nik_app + FROM `{$mainTable}_group_approval` s + WHERE s.`{$mainTable}_approval_id`=a.id + AND s.nik_app=:approved_by), + a.approved_by + ) AS approved_by, + a.days_limit_approval, + a.is_limit_approval, + '$startDateAs' AS start_date, + '$endDateAS' AS end_date + FROM `{$mainTable}_approval` a + LEFT JOIN `{$mainTable}` b ON a.`{$mainTable}_id` = b.id + WHERE a.`{$mainTable}_id` = :transaction_id + ORDER BY a.approval_level ASC"; + return $this->registry->db->prepare($sql); + } + + private function _stmtUpdateApproval($mainTable) + { + $sql = "UPDATE {$mainTable}_approval + SET approval_status = :approval_status, + approval_date = CURRENT_TIMESTAMP(), + `approved_by` = :approved_by, + reject_comment= :reject_comment + WHERE id = :id"; + return $this->registry->db->prepare($sql); + } + + private function _stmtUpdateNextApproval($mainTable) + { + $sql = "UPDATE {$mainTable}_approval SET approval_status='1' WHERE id=:id"; + return $this->registry->db->prepare($sql); + } + + private function _stmtGetLevel($mainTable, $startDateAs = '1970-01-01', $endDateAS = '1970-01-01') + { + $sql = "SELECT approval_level FROM ( + SELECT + a.id, + a.approval_status, + a.approval_level, + a.is_last_approval, + IF(a.is_group='1',( + SELECT s.nik_app + FROM `{$mainTable}_group_approval` s + WHERE s.`{$mainTable}_approval_id`=a.id + AND s.nik_app = :approved_by), + a.approved_by + ) AS approved_by, + a.days_limit_approval, + a.is_limit_approval, + '$startDateAs' AS start_date, + '$endDateAS' AS end_date + FROM `{$mainTable}_approval` a + LEFT JOIN `{$mainTable}` b ON a.`{$mainTable}_id` = b.id + WHERE a.`{$mainTable}_id`=:transaction_id + ) AS t + WHERE t.approved_by = :approved_by + ORDER BY t.approval_level ASC"; + return $this->registry->db->prepare($sql); + } + + + private function _stmtUnrejectApproval($mainTable) + { + return $this->_stmtUnapproveApproval($mainTable); + } + + private function _stmtUnapproveApproval($mainTable) + { + $sqlIsLastApproval = "SELECT COUNT(id) AS total FROM {$mainTable}_approval + WHERE {$mainTable}_id=:transaction_id + AND is_last_approval='1' + AND approval_status='2'"; + + $sqlCheck = "SELECT COUNT(a.id) AS total FROM {$mainTable}_approval a + WHERE a.{$mainTable}_id=:transaction_id + AND (a.approved_by=:approved_by OR :approved_by IN ( + SELECT s.nik_app FROM {$mainTable}_group_approval s + WHERE s.{$mainTable}_approval_id=a.id + ) + )"; + $sqlUpdateGroup = "UPDATE {$mainTable}_approval SET approved_by='-' WHERE {$mainTable}_id=:transaction_id AND is_group='1'"; + $sqlUpdateLevel1 = "UPDATE {$mainTable}_approval SET approval_status='1' WHERE {$mainTable}_id=:transaction_id AND approval_level=1 "; + $sqlUpdateOther = "UPDATE {$mainTable}_approval SET approval_status='0' WHERE {$mainTable}_id=:transaction_id AND approval_level>1 "; + + $stmtCheckLast = $this->registry->db->prepare($sqlIsLastApproval); + $stmtUpdateGroup = $this->registry->db->prepare($sqlUpdateGroup); + $stmtUpdateLevel1 = $this->registry->db->prepare($sqlUpdateLevel1); + $stmtUpdateOtherLevel = $this->registry->db->prepare($sqlUpdateOther); + $stmtCheckApproval = $this->registry->db->prepare($sqlCheck); + + return array( + $stmtCheckLast, + $stmtUpdateGroup, + $stmtUpdateLevel1, + $stmtUpdateOtherLevel, + $stmtCheckApproval + ); + } + + + private function _stmtApprovalSetApproval($mainTable) + { + $sql = "INSERT INTO `{$mainTable}_approval` ( + `approval_level`, + `approval_status`, + `approval_type`, + `approved_by`, + `{$mainTable}_id`, + `is_group`, + `is_last_approval`, + `is_limit_approval`, + `days_limit_approval`) + VALUES ( + :approval_level, + :approval_status, + :approval_type, + :approved_by, + :transaction_id, + :is_group, + :is_last_approval, + :is_limit_approval, + :days_limit_approval + );"; + return $this->registry->db->prepare($sql); + } + + private function _stmtGroupApproval($mainTable) + { + $sql = "INSERT INTO {$mainTable}_group_approval ({$mainTable}_approval_id, nik_app) + VALUES (:emp_absence_approval_id, :nik_app )"; + return $this->registry->db->prepare($sql); + } + + private function _stmtEmployeeData() + { + $sql = "SELECT + SUBSTRING(a.grade,1,1) AS grade, + b.sub_area_id, + c.company_id, + c.country_id, + ol.`bt_code`, + ol.abreviation as positionID, + getEmpJobtitle(a.nik,:effectiveDate) as job_title_name + FROM employement a + LEFT JOIN `emp_job` ej ON a.nik=ej.nik + AND ej.`effective_date`=(SELECT ej1.`effective_date` FROM `emp_job` ej1 WHERE ej1.nik=a.nik AND ej1.`effective_date` <=:effectiveDate ORDER BY ej1.`effective_date` DESC LIMIT 1) + INNER JOIN `mpp_detail` md on ej.`mpp_detail_id`=md.id + INNER JOIN org_layer ol on md.org_layer_id=ol.id + INNER JOIN emp_personal_sub_area b ON a.nik=b.nik + AND b.effective_date=(SELECT s.effective_date FROM emp_personal_sub_area s + WHERE s.nik=a.nik AND s.`effective_date` <=:effectiveDate ORDER BY s.`effective_date` DESC LIMIT 1) + INNER JOIN sub_area c ON b.sub_area_id=c.id + WHERE a.`nik`=:nik"; + + return $this->registry->db->prepare($sql); + } + + + private function _stmtLatestApproval($mainTable) + { + $sql = "SELECT a.id, + getEmpName(a.approved_by) AS name, + CASE WHEN approval_status='1' THEN + CONCAT_WS(' ','Waiting Approval', a.approved_by,'-',getEmpName(a.approved_by),'(',UPPER(a.approval_type),')') + WHEN approval_status='2' THEN + CONCAT_WS(' ','Approved By', a.approved_by,'-',getEmpName(a.approved_by),'(',UPPER(a.approval_type),')') + WHEN approval_status='4' THEN + CONCAT_WS(' ','Rejected By', a.approved_by,'-',getEmpName(a.approved_by),'(',UPPER(a.approval_type),')') + END AS types, + reject_comment AS rejected_comment, + approval_status + FROM {$mainTable}_approval a + WHERE a.{$mainTable}_id=:id AND approval_status != '0' + ORDER BY a.id DESC LIMIT 1"; + return $this->registry->db->prepare($sql); + } +} diff --git a/Aiko/Aiko/Libs/ApprovalRequest/ApprovalRequestTrait.php:Zone.Identifier b/Aiko/Aiko/Libs/ApprovalRequest/ApprovalRequestTrait.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/ApprovalRequest/ApprovalRequestTrait.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/ApprovalRequest/HasApprovalRequest.php b/Aiko/Aiko/Libs/ApprovalRequest/HasApprovalRequest.php new file mode 100644 index 0000000..dd7fb3a --- /dev/null +++ b/Aiko/Aiko/Libs/ApprovalRequest/HasApprovalRequest.php @@ -0,0 +1,59 @@ +approvalRequest->batchApprove($requestBy, $transactionIds); + } + + public function batchReject($requestBy, $transactionIds = [], $comment = '') + { + return $this->approvalRequest->batchReject($requestBy, $transactionIds, $comment); + } + + public function batchUnapprove($requestBy, $transactionIds = []) + { + return $this->approvalRequest->batchUnapprove($requestBy, $transactionIds); + } + + public function batchUnreject($requestBy, $transactionIds = []) + { + return $this->approvalRequest->batchUnreject($requestBy, $transactionIds); + } + + public function approve($requestBy, $transactionId) + { + return $this->approvalRequest->approve($requestBy, $transactionId); + } + + public function reject($requestBy, $transactionId, $notes = '') + { + return $this->approvalRequest->reject($requestBy, $transactionId, $notes); + } + + public function unapprove($requestBy, $transactionId) + { + return $this->approvalRequest->unApprove($requestBy, $transactionId); + } + + public function unreject($requestBy, $transactionId) + { + return $this->unapprove($requestBy, $transactionId); + } + + public function latestApproval($transactionId) + { + return $this->approvalRequest->latestApproval($transactionId); + } + + public function infoApproval($transactionId) + { + return $this->approvalRequest->infoApproval($transactionId); + } +} diff --git a/Aiko/Aiko/Libs/ApprovalRequest/HasApprovalRequest.php:Zone.Identifier b/Aiko/Aiko/Libs/ApprovalRequest/HasApprovalRequest.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/ApprovalRequest/HasApprovalRequest.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/ApprovalRequest/WithApprovalRequest.php b/Aiko/Aiko/Libs/ApprovalRequest/WithApprovalRequest.php new file mode 100644 index 0000000..1330257 --- /dev/null +++ b/Aiko/Aiko/Libs/ApprovalRequest/WithApprovalRequest.php @@ -0,0 +1,274 @@ +data payload needed + * [ + * ['id' => 1] + * ] + * + **/ + private function approve($oJson) + { + $requestBy = \Helper::getSessionVar('username'); + $transactionIds = \Helper::getArrayValueByKey($oJson->data); + if (count($transactionIds) == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Data is empty', + 'token' => $_SESSION['token'] + ], 'json'); + } + $result = $this->obj->approve($requestBy, $transactionIds[0]); + if ($result['isSuccess'] == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Failed Approve Request', + 'token' => $_SESSION['token'] + ], 'json'); + } + Http::ResponseJson(array( + 'pesan' => 'Success Approve Request', + 'token' => $_SESSION['token'] + ), '1'); + } + + + /** + * reject + * + * @param Object $oJson + * + * expected data property exist in object + * $oJson->data payload needed + * [ + * ['id' => 1] + * ] + * + **/ + private function reject($oJson) + { + $requestBy = \Helper::getSessionVar('username'); + $transactionIds = \Helper::getArrayValueByKey($oJson->data); + if (count($transactionIds) == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Data is empty', + 'token' => $_SESSION['token'] + ], 'json'); + } + $result = $this->obj->reject($requestBy, $transactionIds[0]); + if ($result['isSuccess'] == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Failed Reject Request', + 'token' => $_SESSION['token'] + ], 'json'); + } + Http::ResponseJson(array( + 'pesan' => 'Success Reject Request', + 'token' => $_SESSION['token'] + ), '1'); + } + + /** + * unapprove + * + * @param Object $oJson + * + * expected data property exist in object + * $oJson->data payload needed + * [ + * ['id' => 1] + * ] + * + **/ + private function unapprove($oJson) + { + $requestBy = \Helper::getSessionVar('username'); + $transactionIds = \Helper::getArrayValueByKey($oJson->data); + if (count($transactionIds) == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Data is empty', + 'token' => $_SESSION['token'] + ], 'json'); + } + $result = $this->obj->unapprove($requestBy, $transactionIds[0]); + if ($result['isSuccess'] == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Failed Un-Approve Request', + 'token' => $_SESSION['token'] + ], 'json'); + } + Http::ResponseJson(array( + 'pesan' => 'Success Un-Approve Request', + 'token' => $_SESSION['token'] + ), '1'); + } + + /** + * unreject + * + * @param Object $oJson + * + * expected data property exist in object + * $oJson->data payload needed + * [ + * ['id' => 1] + * ] + * + **/ + private function unreject($oJson) + { + $requestBy = \Helper::getSessionVar('username'); + $transactionIds = \Helper::getArrayValueByKey($oJson->data); + if (count($transactionIds) == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Data is empty', + 'token' => $_SESSION['token'] + ], 'json'); + } + $result = $this->obj->unreject($requestBy, $transactionIds[0]); + if ($result['isSuccess'] == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Failed Un-Reject Request', + 'token' => $_SESSION['token'] + ], 'json'); + } + Http::ResponseJson(array( + 'pesan' => 'Success Un-Reject Request', + 'token' => $_SESSION['token'] + ), '1'); + } + + /** + * Batch approve + * + * Undocumented function long description + * + * @param Object $oJson + * + * expected data property exist in object + * $oJson->data payload needed + * [ + * ['id' => 1] + * ] + * + **/ + private function batchApprove($oJson) + { + $requestBy = \Helper::getSessionVar('username'); + $transactionIds = \Helper::getArrayValueByKey($oJson->data); + if (count($transactionIds) == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Data is empty', + 'token' => $_SESSION['token'] + ], 'json'); + } + $result = $this->obj->batchApprove($requestBy, $transactionIds); + $response = array( + 'pesan' => 'Approve data completed, Success: ' . count($result['success']) . ', Failed: ' . count($result['failed']), + 'moreInfo' => $result, + 'token' => $_SESSION['token'] + ); + Http::ResponseJson($response); + } + + /** + * Batch unapprove + * + * @param Object $oJson + * + * expected data property exist in object + * $oJson->data payload needed + * [ + * ['id' => 1] + * ] + * + **/ + private function batchUnapprove($oJson) + { + $requestBy = \Helper::getSessionVar('username'); + $transactionIds = \Helper::getArrayValueByKey($oJson->data); + if (count($transactionIds) == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Data is empty', + 'token' => $_SESSION['token'] + ], 'json'); + } + $result = $this->obj->batchUnapprove($requestBy, $transactionIds); + $response = array( + 'pesan' => 'Un-Approve data completed, Success: ' . count($result['success']) . ', Failed: ' . count($result['failed']), + 'moreInfo' => $result, + 'token' => $_SESSION['token'] + ); + Http::ResponseJson($response); + } + + /** + * Batch reject + * + * @param Object $oJson + * + * expected data property exist in object + * $oJson->data payload needed + * [ + * ['id' => 1] + * ] + * + **/ + private function batchReject($oJson) + { + $requestBy = \Helper::getSessionVar('username'); + $transactionIds = \Helper::getArrayValueByKey($oJson->data); + if (count($transactionIds) == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Data is empty', + 'token' => $_SESSION['token'] + ], 'json'); + } + $result = $this->obj->batchReject($requestBy, $transactionIds, $oJson->comment); + $response = array( + 'pesan' => 'Reject data completed, Success: ' . count($result['success']) . ', Failed: ' . count($result['failed']), + 'moreInfo' => $result, + 'token' => $_SESSION['token'] + ); + Http::ResponseJson($response, '1'); + } + + /** + * Batch unreject + * + * @param Object $oJson + * + * expected data property exist in object + * $oJson->data payload needed + * [ + * ['id' => 1] + * ] + * + **/ + private function batchUnreject($oJson) + { + $requestBy = \Helper::getSessionVar('username'); + $transactionIds = \Helper::getArrayValueByKey($oJson->data); + if (count($transactionIds) == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Data is empty', + 'token' => $_SESSION['token'] + ], 'json'); + } + $result = $this->obj->batchUnapprove($requestBy, $transactionIds); + $response = array( + 'pesan' => 'Approve data completed, Success: ' . count($result['success']) . ', Failed: ' . count($result['failed']), + 'moreInfo' => $result, + 'token' => $_SESSION['token'] + ); + Http::ResponseJson($response); + } +} diff --git a/Aiko/Aiko/Libs/ApprovalRequest/WithApprovalRequest.php:Zone.Identifier b/Aiko/Aiko/Libs/ApprovalRequest/WithApprovalRequest.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/ApprovalRequest/WithApprovalRequest.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/Debug.php b/Aiko/Aiko/Libs/Debug.php new file mode 100644 index 0000000..e729e6b --- /dev/null +++ b/Aiko/Aiko/Libs/Debug.php @@ -0,0 +1,105 @@ +fb($content,\FirePHP::INFO); + }else + { + self::$firephp->fb($content,$label,\FirePHP::INFO); + } + } + + } + public function log($content,$label='') + { + if(self::$env==='developer') + { + if($label=='') + { + self::$firephp->fb($content,\FirePHP::LOG); + }else + { + self::$firephp->fb($content,$label,\FirePHP::LOG); + } + } + + } + public function warning($content,$label='') + { + if(self::$env==='developer') + { + if($label=='') + { + self::$firephp->fb($content,\FirePHP::WARN); + }else + { + self::$firephp->fb($content,$label,\FirePHP::WARN); + } + } + + } + public function error($content,$label='') + { + if(self::$env==='developer') + { + if($label=='') + { + self::$firephp->fb($content,\FirePHP::ERROR); + }else + { + self::$firephp->fb($content,$label,\FirePHP::ERROR); + } + } + } + public function trace($label) + { + if(self::$env==='developer') + { + self::$firephp->fb($label,\FirePHP::TRACE); + } + } + + public function table($content,$label='') + { + if(self::$env==='developer') + { + if($label=='') + { + self::$firephp->fb($content,\FirePHP::TABLE); + }else + { + self::$firephp->fb($content,$label,\FirePHP::TABLE); + } + } + + } + public function dump($content,$label='') + { + if(self::$env==='developer') + { + if($label=='') + { + self::$firephp->fb($content,\FirePHP::DUMP); + }else + { + self::$firephp->fb($content,$label,\FirePHP::DUMP); + } + } + + } + private function __clone(){} +} \ No newline at end of file diff --git a/Aiko/Aiko/Libs/Debug.php:Zone.Identifier b/Aiko/Aiko/Libs/Debug.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/Debug.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/FCM.php b/Aiko/Aiko/Libs/FCM.php new file mode 100644 index 0000000..8390eee --- /dev/null +++ b/Aiko/Aiko/Libs/FCM.php @@ -0,0 +1,104 @@ +registry = $registry; + } + + private $fcmUrl = "https://fcm.googleapis.com/fcm/send"; + + public function sendPushNotificationByEmpId($empId, $title, $message, $screen = '/dashboard') + { + $sqlCheck = "SELECT id, token FROM fcm_token WHERE emp_id = :emp_id"; + $stmtCheck = $this->registry->db->prepare($sqlCheck); + $stmtCheck->bindValue(':emp_id', $empId, PDO::PARAM_INT); + $stmtCheck->execute(); + $rsCheck = $stmtCheck->fetchAll(PDO::FETCH_ASSOC); + $ctr = count($rsCheck); + + if ($ctr === 0) { + return []; + } + + $response = []; + $toTokens = []; + + for ($i = 0; $i < $ctr; $i++) { + array_push($toTokens, $rsCheck[$i]['token']); + } + + $stmtDelete = $this->registry->db->prepare('delete from fcm_token where id = :id'); + $temp = $this->sendPushNotification($toTokens, $title, $message, $empId, $screen); + $dcode = json_decode($temp, true); + for ($i = 0; $i < count($dcode['results']); $i++) { + $status = [ + 'is_send' => true, + 'is_deleted' => false, + 'fcm_token_id' => $rsCheck[$i]['id'], + 'emp_id' => $empId + ]; + if (isset($dcode['results'][$i]['error']) && $dcode['results'][$i]['error'] === 'NotRegistered') { + $stmtDelete->bindValue(':id', $rsCheck[$i]['id'], PDO::PARAM_INT); + $stmtDelete->execute(); + $status['is_send'] = false; + $status['is_deleted'] = true; + } + array_push($response, $status); + } + + return $response; + } + + public function sendPushNotification($toToken = [], $title, $message, $userId = null, $screen = '/dashboard') + { + $header = [ + 'authorization: key=' . $this->registry->config->fcm_token, + 'content-type: application/json', + ]; + + $notification = [ + 'title' => $title, + 'body' => $message, + "click_action" => 'FLUTTER_NOTIFICATION_CLICK', + ]; + $extraNotificationData = [ + 'screen' => $screen, + "message" => $notification, + "id" => $userId, + ]; + $fcmNotification = [ + 'registration_ids' => $toToken, + 'notification' => $notification, + 'data' => $extraNotificationData, + ]; + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $this->fcmUrl); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fcmNotification)); + curl_setopt($ch, CURLOPT_HTTPHEADER, $header); + + $result = curl_exec($ch); + curl_close($ch); + + return $result; + } +} diff --git a/Aiko/Aiko/Libs/FCM.php:Zone.Identifier b/Aiko/Aiko/Libs/FCM.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/FCM.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/GeoTz.php b/Aiko/Aiko/Libs/GeoTz.php new file mode 100644 index 0000000..2e01b7d --- /dev/null +++ b/Aiko/Aiko/Libs/GeoTz.php @@ -0,0 +1,89 @@ +registry = $registry; + $this->endpoint = $this->registry->config->api_geo_tz_endpoint; + $this->apiKey = $this->registry->config->api_geo_tz_key; + $this->client = new Client([ + 'base_uri' => $this->endpoint, + 'http_errors ' => false, + 'headers' => [ + 'Content-Type' => 'application/json', + 'Accept' => 'application/json', + ] + ]); + } + + public function getCoordinateTimezone($lat, $lon) + { + return $this->getTimezoneApi($lat, $lon); + } + + public function getTimezoneLocally($hourOffset) + { + $sign = $hourOffset < 0 ? '-' : '+'; + $date = new DateTime('now', new DateTimeZone($sign . abs($hourOffset))); + return array( + 'date' => $date->format('Y-m-d'), + 'time' => $date->format('H:i:s'), + 'date_time' => $date->format('Y-m-d H:i:s'), + 'api' => [] + ); + } + + private function getTimezoneApi($lat, $lon) + { + try { + + $response = $this->client->get('/timezone', [ + 'query' => [ + 'apiKey' => $this->apiKey, + 'lat' => $lat, + 'long' => $lon + ] + ]); + + if ($response->getStatusCode() !== 200) { + throw new ErrorException((string) $response->getBody()->getContents()); + } + + $data = $response->getBody()->getContents(); + $tz = json_decode($data, true); + $date = new DateTime('now', new DateTimeZone($tz['timezone'])); + + return array( + 'date' => $date->format('Y-m-d'), + 'time' => $date->format('H:i:s'), + 'date_time' => $date->format('Y-m-d H:i:s') + ); + } catch (ErrorException $e) { + $this->registry + ->log + ->error('Geolocation / getTimezoneApi :' + . $e->getMessage() . ', Line: ' + . $e->getLine() . ', File: ' + . $e->getFile()); + return []; + } + } +} diff --git a/Aiko/Aiko/Libs/GeoTz.php:Zone.Identifier b/Aiko/Aiko/Libs/GeoTz.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/GeoTz.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/Http.php b/Aiko/Aiko/Libs/Http.php new file mode 100644 index 0000000..4cd08b4 --- /dev/null +++ b/Aiko/Aiko/Libs/Http.php @@ -0,0 +1,346 @@ +getContent(); + } + + public static function enabledCors() + { + // // Allow from any origin + if (isset($_SERVER['HTTP_ORIGIN'])) { + // Decide if the origin in $_SERVER['HTTP_ORIGIN'] is one + // you want to allow, and if so: + header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}"); + header('Access-Control-Allow-Credentials: true'); + header('Access-Control-Max-Age: 86400'); // cache for 1 day + } + + // Access-Control headers are received during OPTIONS requests + if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { + + if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) + // may also be using PUT, PATCH, HEAD etc + { + header("Access-Control-Allow-Methods: GET, POST, OPTIONS"); + } + + if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) { + header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"); + } + + exit(0); + } + } + + public static function UnauthorizedResponse($content) + { + self::$response = new Response( + $content, + Response::HTTP_UNAUTHORIZED, + array('content-type' => 'text/html') + ); + self::$response->headers->set('Access-Control-Allow-Origin', '*'); + self::$response->send(); + exit(); + } + + public static function InternalServerError($content) + { + self::$response = new Response( + $content, + Response::HTTP_INTERNAL_SERVER_ERROR, + array('content-type' => 'text/html') + ); + self::$response->send(); + exit(); + } + + public static function UnauthorizedResponseJson($content) + { + self::$response = new Response( + JWT::jsonEncode($content), + Response::HTTP_UNAUTHORIZED, + array('content-type' => 'application/json') + ); + self::$response->headers->set('Access-Control-Allow-Origin', '*'); + self::$response->headers->set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE'); + self::$response->headers->set('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With,x-firephp,x-firephp-version,x-wf-max-combined-size'); + self::$response->send(); + exit(); + } + public static function PageNotFound($content) + { + self::$response = new Response( + $content, + Response::HTTP_NOT_FOUND, + array('content-type' => 'text/html') + ); + self::$response->headers->set('Access-Control-Allow-Origin', '*'); + self::$response->headers->set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE'); + self::$response->headers->set('Access-Control-Allow-Headers', 'Content-Type,Authorization,X-Requested-With,x-firephp,x-firephp-version,x-wf-max-combined-size'); + self::$response->send(); + + exit(); + } + + public static function GetXsrfHeader() + { + self::$request = Request::CreateFromGlobals(); + $token = self::$request->headers->get('X-XSRF-TOKEN'); + + return $token; + } + + public static function GetTokenHeader() + { + self::$request = Request::CreateFromGlobals(); + $token = self::$request->headers->get('token'); + + return $token; + } + + public static function ErrorQueryResponse($content, $type = 'text') + { + if ($type == 'text') { + self::$response = new Response( + $content, + Response::HTTP_BAD_REQUEST, + array('content-type' => 'text/html') + ); + self::$response->send(); + } else { + self::$response = new JsonResponse(); + self::$response->setData($content); + self::$response->headers->set('Access-Control-Allow-Origin', '*'); + self::$response->setStatusCode(Response::HTTP_BAD_REQUEST); + self::$response->send(); + } + + exit(); + } + + public static function Forbidden($content, $type = 'text') + { + if ($type == 'text') { + self::$response = new Response( + $content, + Response::HTTP_FORBIDDEN, + array('content-type' => 'text/html') + ); + self::$response->send(); + } else { + self::$response = new JsonResponse(); + self::$response->setData($content); + self::$response->headers->set('Access-Control-Allow-Origin', '*'); + self::$response->setStatusCode(Response::HTTP_FORBIDDEN); + self::$response->send(); + } + + exit(); + } + + public static function responseJson($array, $secure = '0', $cors = '0') + { + if ($secure == '0') { + self::$response = new JsonResponse(); + self::$response->setData($array); + if ($cors == '1') { + self::$response->headers->set('Access-Control-Allow-Origin', '*'); + self::$response->headers->set('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With,x-firephp-version,x-firephp,x-firephp-version,x-wf-max-combined-size'); + self::$response->headers->set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE'); + } + self::$response->send(); + } else { + self::$response = new Response(); + $jtext = ")]}',\n" . JWT::jsonEncode($array, JSON_UNESCAPED_SLASHES); + self::$response->setContent($jtext); + self::$response->headers->set('Content-Type', 'application/json'); + if ($cors == '1') { + self::$response->headers->set('Access-Control-Allow-Origin', '*'); + } + self::$response->send(); + } + + exit(); + } + + public static function GetVarData($key, $method = 'get') + { + self::$request = Request::createFromGlobals(); + if ($method == 'get') { + $result = self::$request->query->get($key); + } else { + + $result = self::$request->request->get($key); + } + + return $result; + } + + public static function Error404($content) + { + self::$response = new Response( + $content, + Response::HTTP_NOT_FOUND, + array('content-type' => 'text/html') + ); + self::$response->send(); + exit(); + } + + public static function GetFile($key) + { + + + self::$request = Request::createFromGlobals(); + // var_dump(self::$request); + $result = self::$request->files->get($key); + + + return $result; + } + + public static function CekTokenHeader() + { + self::$request = Request::CreateFromGlobals(); + $token = self::$request->headers->get('token'); + + return $token; + } + + public static function CekTokenAuthHeader() + { + self::$request = Request::CreateFromGlobals(); + $token = self::$request->headers->get('tokenAuth'); + + return $token; + } + + public static function getTokenJWT() + { + self::$request = Request::CreateFromGlobals(); + $authHeader = self::$request->headers->get('Authorization'); + list($jwt) = sscanf($authHeader, 'Bearer %s'); + // var_dump($jwt); + return $jwt; + } + + public static function getBasicAuth() + { + self::$request = Request::CreateFromGlobals(); + $authHeader = self::$request->headers->get('Authorization'); + list($code) = sscanf($authHeader, 'Basic %s'); + // var_dump($code); + return $code; + } + + public static function requestServer($key) + { + if (is_null(self::$request)) { + self::$request = Request::CreateFromGlobals(); + } + + return self::$request->server->get($key); + } + public static function tokenExpired($content) + { + $response = new Response( + JWT::jsonEncode($content), + Response::HTTP_NOT_ACCEPTABLE, + array('content-type' => 'application/json') + ); + $response->headers->set('Access-Control-Allow-Origin', '*'); + $response->headers->set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE'); + $response->headers->set('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With,x-firephp,x-firephp-version,x-wf-max-combined-size'); + $response->send(); + exit(); + } + + public static function responseFile($params) + { + $path_to_zip=$params['file_path']; + + + // if( file_exists( $path_to_zip ) ) + // { + // die(); + // header( 'Cache-Control: public' ); + // header( 'Content-Description: File Transfer' ); + // header( "Content-Disposition: attachment; filename={$path_to_zip}" ); + // header( 'Content-Type: application/zip' ); + // header( 'Content-Transfer-Encoding: binary' ); + // readfile( $path_to_zip ); + // exit; + // } + + // die( "ERROR: invalid song or you don't have permissions to download it." ); + $extension = pathinfo(parse_url($path_to_zip, PHP_URL_PATH), PATHINFO_EXTENSION); + $file_info = new finfo(FILEINFO_MIME_TYPE); + $mime_type = $file_info->buffer(file_get_contents($path_to_zip)); + $file=file_get_contents($path_to_zip); + + $response = new Response( + $file, + Response::HTTP_OK, + array('content-type' => $mime_type) + ); + $response->send(); + + // var_dump($file);die(); + } + + + public static function getHeaderValue($key, $default = null) + { + self::$request = Request::CreateFromGlobals(); + if (!self::$request->headers->has($key)) { + return $default; + } + $value = self::$request->headers->has($key); + return $value; + } + + public static function getAllRequest($method = 'get') + { + self::$request = Request::createFromGlobals(); + if ($method == 'get') { + $result = self::$request->query->all(); + } else { + $result = self::$request->request->all(); + } + return $result; + } + + public static function isMultipartFormData() + { + $req = Request::CreateFromGlobals(); + $multipart=$req->headers->has('Content-Type'); + if($multipart) + { + $contentType=$req->headers->get('Content-Type'); + if(strpos($contentType,'multipart/form-data')!==false) + { + return true; + } + } + return false; + } +} diff --git a/Aiko/Aiko/Libs/Http.php:Zone.Identifier b/Aiko/Aiko/Libs/Http.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/Http.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/Log.php b/Aiko/Aiko/Libs/Log.php new file mode 100644 index 0000000..54424c2 --- /dev/null +++ b/Aiko/Aiko/Libs/Log.php @@ -0,0 +1,143 @@ +pushHandler(new StreamHandler(__SITE_PATH.'/log/Error-'.date('Y-m-d').'.log', Logger::ERROR)); + + self::$accessLog = new Logger('accessLog'); + self::$accessLog->pushHandler(new StreamHandler(__SITE_PATH.'/log/Access-'.date('Y-m-d').'.log', Logger::INFO)); + + self::$mobileAccessLog = new Logger('mobile_accessLog'); + self::$mobileAccessLog->pushHandler(new StreamHandler(__SITE_PATH.'/log/MobileAccess-'.date('Y-m-d').'.log', Logger::INFO)); + self::$commitAttendance = new Logger('commit_attendance'); + self::$commitAttendance->pushHandler(new StreamHandler(__SITE_PATH.'/log/commitAttendance-'.date('Y-m-d').'.log', Logger::INFO)); + + } + + public function error($message, $data = array()) + { + $data = $this->convertToArray($data); + $ip = $this->getIp(); + $message = $ip.' '.$message; + if (count($data) > 0) { + self::$errorLog->addError($message, $data); + } else { + self::$errorLog->addError($message); + } + } + + public function access($message, $data = array()) + { + $data = $this->convertToArray($data); + $ip = $this->getIp(); + $message = $ip.' '.$message; + if (self::$env === '1') { + if (count($data) > 0) { + self::$accessLog->addInfo($message, $data); + } else { + self::$accessLog->addInfo($message); + } + } + } + + public function customAccess($fileName,$message, $data = array()) + { + + $ip = $this->getIp(); + $message = $ip.' '.$message; + if (count($data) > 0) { + $newLog= new Logger('custom-success-log'); + $newLog->pushHandler(new StreamHandler(__SITE_PATH.'/log/'.$fileName.'-'.date('Y-m-d').'.log', Logger::INFO)); + $data = $this->convertToArray($data); + $newLog->addInfo($message, $data); + } else { + $newLog->addInfo($message); + } + + } + + public function customError($fileName,$message,$data=array()) + + { + $newLog= new Logger('custom-error-log'); + $newLog->pushHandler(new StreamHandler(__SITE_PATH.'/log/'.$fileName.'-'.date('Y-m-d').'.log', Logger::ERROR)); + $data = $this->convertToArray($data); + $ip = $this->getIp(); + $message = $ip.' '.$message; + if (count($data) > 0) { + $newLog->addError($message, $data); + } else { + $newLog->addError($message); + } + + } + + private function getIp() + { + if (!empty($_SERVER['HTTP_CLIENT_IP'])) { + $ip = $_SERVER['HTTP_CLIENT_IP']; + } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { + $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; + } else { + $ip = $_SERVER['REMOTE_ADDR']; + } + + return $ip; + } + + private function convertToArray($data) + { + if (is_object($data)) { + $jtext = json_encode($data); + $arr = json_decode($jtext, true); + + return $arr; + } else { + if (is_array($data)) { + return $data; + } else { + return array(); + } + } + } + + public function mobileAccess($message, $data = array()) + { + $data = $this->convertToArray($data); + $ip = $this->getIp(); + $message = $ip.' '.$message; + if (count($data) > 0) { + self::$mobileAccessLog->addInfo($message, $data); + } else { + self::$mobileAccessLog->addInfo($message); + } + } + + public function commitAttendance($message, $data = array()) + { + $data = $this->convertToArray($data); + $ip = $this->getIp(); + $message = $ip.' '.$message; + if (count($data) > 0) { + self::$mobileAccessLog->addInfo($message, $data); + } else { + self::$mobileAccessLog->addInfo($message); + } + } +} diff --git a/Aiko/Aiko/Libs/Log.php:Zone.Identifier b/Aiko/Aiko/Libs/Log.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/Log.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/LogAccess.php b/Aiko/Aiko/Libs/LogAccess.php new file mode 100644 index 0000000..67660d2 --- /dev/null +++ b/Aiko/Aiko/Libs/LogAccess.php @@ -0,0 +1,85 @@ +registry->db->prepare($sql); + $stmt->bindValue(':service_name',$serviceName, PDO::PARAM_STR); + $stmt->bindValue(':username',\Helper::getSessionVar('username'), PDO::PARAM_STR); + $stmt->execute(); + return true; + } catch (PDOException $e) { + + $this->registry->log->error('Action : Insert data LogAcccess/saveLog :'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + + return false; + } catch (\ErrorException $e) { + + $this->registry->log->error('Action : Insert data LogAcccess/saveLog :'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + + return false; + } + } + + public function viewLogByServiceName($serviceName) + { + try { + + $sql = 'select `service_name`,`username`,`timestamp` from app_log where `service_name`=:service_name'; + + $stmt = $this->registry->db->prepare($sql); + $stmt->bindValue(':service_name',$serviceName, PDO::PARAM_STR); + $stmt->execute(); + $rs=$stmt->fetchAll(PDO::FETCH_ASSOC); + + + return $rs; + } catch (PDOException $e) { + $this->registry->log->error('LogAcccess/viewLogByServiceName :'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + + return false; + } catch (\ErrorException $e) { + $this->registry->log->error('LogAcccess/viewLogByServiceName :'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + + return false; + } + } + + public function viewLogByUsername($username) + { + try { + + $sql = 'select `service_name`,`username`,`timestamp` from app_log where `username`=:username'; + + $stmt = $this->registry->db->prepare($sql); + $stmt->bindValue(':username',$username, PDO::PARAM_STR); + $stmt->execute(); + $rs=$stmt->fetchAll(PDO::FETCH_ASSOC); + + + return $rs; + } catch (PDOException $e) { + $this->registry->log->error('LogAcccess/viewLogByServiceUsername :'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + + return false; + } catch (ErrorException $e) { + $this->registry->log->error('LogAcccess/viewLogByServiceUsername :'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + + return false; + } + } + +} \ No newline at end of file diff --git a/Aiko/Aiko/Libs/LogAccess.php:Zone.Identifier b/Aiko/Aiko/Libs/LogAccess.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/LogAccess.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/Logdbtrait.php b/Aiko/Aiko/Libs/Logdbtrait.php new file mode 100644 index 0000000..e2d69c7 --- /dev/null +++ b/Aiko/Aiko/Libs/Logdbtrait.php @@ -0,0 +1,36 @@ +registry->db->prepare($sql); + $stmt->bindValue(':table_name',$tableName, PDO::PARAM_STR); + $stmt->bindValue(':data',$data,PDO::PARAM_STR); + $stmt->bindValue(':transaction_type',$transactionType,PDO::PARAM_STR); + $stmt->bindValue(':action_by',$actionBy,PDO::PARAM_STR); + $stmt->execute(); + return true; + } catch (PDOException $e) { + return false; + } catch (ErrorException $e) { + return false; + } + } +} \ No newline at end of file diff --git a/Aiko/Aiko/Libs/Logdbtrait.php:Zone.Identifier b/Aiko/Aiko/Libs/Logdbtrait.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/Logdbtrait.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/MyFpdi.php b/Aiko/Aiko/Libs/MyFpdi.php new file mode 100644 index 0000000..7a7c743 --- /dev/null +++ b/Aiko/Aiko/Libs/MyFpdi.php @@ -0,0 +1,16 @@ +widths=$w; + } + + public function SetAligns($a) + { + //Set the array of column alignments + $this->aligns=$a; + } + function RowAja($data) + { + //Calculate the height of the row + $nb=0; + for($i=0;$iNbLines($this->widths[$i],$data[$i])); + $h=5*$nb; + //Issue a page break first if needed + $this->CheckPageBreak($h); + //Draw the cells of the row + for($i=0;$iwidths[$i]; + $a=isset($this->aligns[$i]) ? $this->aligns[$i] : 'L'; + //Save the current position + $x=$this->GetX(); + $y=$this->GetY(); + //Draw the border + $this->Rect($x,$y,$w,$h); + //Print the text + $this->MultiCell($w,5,$data[$i],0,$a); + //Put the position to the right of the cell + $this->SetXY($x+$w,$y); + } + //Go to the next line + $this->Ln($h); + } + public function Row($data,$border=0,$fill=0,$draw=0) + { + //Calculate the height of the row + $nb=0; + for($i=0;$iNbLines($this->widths[$i],$data[$i])); + } + $h=5*$nb; + //Issue a page break first if needed + $this->CheckPageBreak($h); + //Draw the cells of the row + for($i=0;$iwidths[$i]; + $nb1=$this->NbLines($this->widths[$i],$data[$i]); + $a=isset($this->aligns[$i]) ? $this->aligns[$i] : 'L'; + // $h1=isset($this->height[$i]) ? $this->height[$i] :5; + //Save the current position + $x=$this->GetX(); + $y=$this->GetY(); + //Draw the border + $this->Rect($x,$y,$w,$h,$draw); + //Print the text + $this->MultiCell($w,($h/$nb1),$data[$i],$border,$a,$fill); + + //Put the position to the right of the cell + $this->SetXY($x+$w,$y); + } + //Go to the next line + $this->Ln($h); + } + public function RowNoBorder($data,$border=0,$fill=0,$draw=0) + { + //Calculate the height of the row + $border=0; + $nb=0; + for($i=0;$iNbLines($this->widths[$i],$data[$i])); + } + $h=5*$nb; + //Issue a page break first if needed + $this->CheckPageBreak($h); + //Draw the cells of the row + for($i=0;$iwidths[$i]; + $nb1=$this->NbLines($this->widths[$i],$data[$i]); + $a=isset($this->aligns[$i]) ? $this->aligns[$i] : 'L'; + // $h1=isset($this->height[$i]) ? $this->height[$i] :5; + //Save the current position + $x=$this->GetX(); + $y=$this->GetY(); + + //Draw the border + // $this->Rect($x,$y,$w,$h,$draw); + //Print the text + $this->MultiCell($w,($h/$nb1),$data[$i],$border,$a,$fill); + //Put the position to the right of the cell + $this->SetXY($x+$w,$y); + } + //Go to the next line + $this->Ln($h); + } + public function Rowb($data,$border=0,$fill=0,$draw=0,$besar=10) + { + //Calculate the height of the row + $nb=0; + for($i=0;$iNbLines($this->widths[$i],$data[$i])); + } + $h=$besar*$nb; + //Issue a page break first if needed + $this->CheckPageBreak($h); + //Draw the cells of the row + for($i=0;$iwidths[$i]; + $nb1=$this->NbLines($this->widths[$i],$data[$i]); + $a=isset($this->aligns[$i]) ? $this->aligns[$i] : 'L'; + // $h1=isset($this->height[$i]) ? $this->height[$i] :5; + //Save the current position + $x=$this->GetX(); + $y=$this->GetY(); + //Draw the border + $this->Rect($x,$y,$w,$h,$draw); + //Print the text + $this->MultiCell($w,($h/$nb1),$data[$i],$border,$a,$fill); + //Put the position to the right of the cell + $this->SetXY($x+$w,$y); + } + //Go to the next line + $this->Ln($h); + } + + + public function Rowbp($data,$border=0,$fill=0,$draw=0,$besar=10,$padding=0) + { + //Calculate the height of the row + $nb=0; + for($i=0;$iNbLines($this->widths[$i]-($padding*2),$data[$i])); + } + $h=$besar*$nb; + //Issue a page break first if needed + $this->CheckPageBreak($h); + //Draw the cells of the row + for($i=0;$iwidths[$i]-($padding*2); + $nb1=$this->NbLines($this->widths[$i]-($padding*2),$data[$i]); + $a=isset($this->aligns[$i]) ? $this->aligns[$i] : 'L'; + // $h1=isset($this->height[$i]) ? $this->height[$i] :5; + //Save the current position + $xB=$x=$this->GetX(); + $yB=$y=$this->GetY(); + //Draw the border + + if($border) + $this->Rect($x,$y,$w+($padding*2),$h+($padding*2),$draw); + + if($padding > 0) { + // $x+=$padding; + // $y+=$padding; + // $w-=$padding; + // $h-=$padding; + $this->SetXY($x+$padding,$y+$padding); + } + //Print the text + $this->MultiCell($w,$besar,$data[$i],0,$a,$fill); + //Put the position to the right of the cell + $this->SetXY($x+$w+($padding*2),$y); + } + //Go to the next line + $this->Ln($h+($padding*2)); + } + + + public function CheckPageBreak($h) + { + //If the height h would cause an overflow, add a new page immediately + if($this->GetY()+$h>$this->PageBreakTrigger) + $this->AddPage($this->CurOrientation); + } + + public function NbLines($w,$txt) + { + //Computes the number of lines a MultiCell of width w will take + $cw=&$this->CurrentFont['cw']; + if($w==0) + $w=$this->w-$this->rMargin-$this->x; + $wmax=($w-2*$this->cMargin)*1000/$this->FontSize; + $s=str_replace("\r",'',$txt); + $nb=strlen($s); + if($nb>0 and $s[$nb-1]=="\n") + $nb--; + $sep=-1; + $i=0; + $j=0; + $l=0; + $nl=1; + while($i<$nb) + { + $c=$s[$i]; + if($c=="\n") + { + $i++; + $sep=-1; + $j=$i; + $l=0; + $nl++; + continue; + } + if($c==' ') + $sep=$i; + $l+=$cw[$c]; + if($l>$wmax) + { + if($sep==-1) + { + if($i==$j) + $i++; + } + else + $i=$sep+1; + $sep=-1; + $j=$i; + $l=0; + $nl++; + } + else + $i++; + } + return $nl; + } + + public function Header() + { + + } + + public function Footer() { + + } + public function Rotate($angle,$x=-1,$y=-1) + { + if($x==-1) + $x=$this->x; + if($y==-1) + $y=$this->y; + if($this->angle!=0) + $this->_out('Q'); + $this->angle=$angle; + if($angle!=0) + { + $angle*=M_PI/180; + $c=cos($angle); + $s=sin($angle); + $cx=$x*$this->k; + $cy=($this->h-$y)*$this->k; + $this->_out(sprintf('q %.5F %.5F %.5F %.5F %.2F %.2F cm 1 0 0 1 %.2F %.2F cm',$c,$s,-$s,$c,$cx,$cy,-$cx,-$cy)); + } + } + public function _endpage() + { + if($this->angle!=0) + { + $this->angle=0; + $this->_out('Q'); + } + parent::_endpage(); + } + public function RotatedText($x,$y,$txt,$angle) + { + //Text rotated around its origin + $this->Rotate($angle,$x,$y); + $this->Text($x,$y,$txt); + $this->Rotate(0); + } + public function RotatedImage($file,$x,$y,$w,$h,$angle) + { + //Image rotated around its upper-left corner + $this->Rotate($angle,$x,$y); + $this->Image($file,$x,$y,$w,$h); + $this->Rotate(0); + } + + function SetDash($black=false, $white=false) + { + if($black and $white) + $s=sprintf('[%.3f %.3f] 0 d', $black*$this->k, $white*$this->k); + else + $s='[] 0 d'; + + $this->_out($s); + } + + function CustomMultiCell($widthBeforeCell=0, $width, $height, $text, $border=0, $align='L', $fill=0) + { + if($widthBeforeCell<>0){ + $this->cell($widthBeforeCell); + } + $nb1=$this->NbLines($width,$text); + // var_dump($nb1);exit; + $this->MultiCell($width,3,$text,$border,$align,$fill); + } + + /** + * Function to set permissions as well as user and owner passwords + * + * - permissions is an array with values taken from the following list: + * copy, print, modify, annot-forms + * If a value is present it means that the permission is granted + * - If a user password is set, user will be prompted before document is opened + * - If an owner password is set, document can be opened in privilege mode with no + * restriction if that password is entered + */ + function SetProtection($permissions=array(), $user_pass='', $owner_pass=null) + { + $options = array('print' => 4, 'modify' => 8, 'copy' => 16, 'annot-forms' => 32 ); + $protection = 192; + foreach($permissions as $permission) + { + if (!isset($options[$permission])) + $this->Error('Incorrect permission: '.$permission); + $protection += $options[$permission]; + } + if ($owner_pass === null) + $owner_pass = uniqid(rand()); + $this->encrypted = true; + $this->padding = "\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08". + "\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A"; + $this->_generateencryptionkey($user_pass, $owner_pass, $protection); + } + + function CustomMultiCellResultOnb($widthBeforeCell=0, $width, $height, $text, $border=0, $align='L', $fill=0) + { + if($widthBeforeCell<>0){ + $this->cell($widthBeforeCell); + } + $this->MultiCell($width,$height,$text,$border,$align,$fill); + } + +/**************************************************************************** +* * +* Private methods * +* * +****************************************************************************/ + + function _putstream($s) + { + if ($this->encrypted) { + $s = RC4($this->_objectkey($this->n), $s); + } + parent::_putstream($s); + } + + function _textstring($s) + { + if ($this->encrypted) { + $s = RC4($this->_objectkey($this->n), $s); + } + return parent::_textstring($s); + } + + /** + * Compute key depending on object number where the encrypted data is stored + */ + function _objectkey($n) + { + return substr($this->_md5_16($this->encryption_key.pack('VXxx',$n)),0,10); + } + + function _putresources() + { + parent::_putresources(); + if ($this->encrypted) { + $this->_newobj(); + $this->enc_obj_id = $this->n; + $this->_out('<<'); + $this->_putencryption(); + $this->_out('>>'); + $this->_out('endobj'); + } + } + + function _putencryption() + { + $this->_out('/Filter /Standard'); + $this->_out('/V 1'); + $this->_out('/R 2'); + $this->_out('/O ('.$this->_escape($this->Ovalue).')'); + $this->_out('/U ('.$this->_escape($this->Uvalue).')'); + $this->_out('/P '.$this->Pvalue); + } + + function _puttrailer() + { + parent::_puttrailer(); + if ($this->encrypted) { + $this->_out('/Encrypt '.$this->enc_obj_id.' 0 R'); + $this->_out('/ID [()()]'); + } + } + + /** + * Get MD5 as binary string + */ + function _md5_16($string) + { + return pack('H*',md5($string)); + } + + /** + * Compute O value + */ + function _Ovalue($user_pass, $owner_pass) + { + $tmp = $this->_md5_16($owner_pass); + $owner_RC4_key = substr($tmp,0,5); + return RC4($owner_RC4_key, $user_pass); + } + + /** + * Compute U value + */ + function _Uvalue() + { + return RC4($this->encryption_key, $this->padding); + } + + /** + * Compute encryption key + */ + function _generateencryptionkey($user_pass, $owner_pass, $protection) + { + // Pad passwords + $user_pass = substr($user_pass.$this->padding,0,32); + $owner_pass = substr($owner_pass.$this->padding,0,32); + // Compute O value + $this->Ovalue = $this->_Ovalue($user_pass,$owner_pass); + // Compute encyption key + $tmp = $this->_md5_16($user_pass.$this->Ovalue.chr($protection)."\xFF\xFF\xFF"); + $this->encryption_key = substr($tmp,0,5); + // Compute U value + $this->Uvalue = $this->_Uvalue(); + // Compute P value + $this->Pvalue = -(($protection^255)+1); + } + + function WriteTag($w, $h, $txt, $border=0, $align="J", $fill=false, $padding=0) + { + $this->wLine=$w; + $this->hLine=$h; + $this->Text=trim($txt); + $this->Text=preg_replace("/\n|\r|\t/","",$this->Text); + $this->border=$border; + $this->align=$align; + $this->fill=$fill; + $this->Padding=$padding; + + $this->Xini=$this->GetX(); + $this->href=""; + $this->PileStyle=array(); + $this->TagHref=array(); + $this->LastLine=false; + $this->NextLineBegin=array(); + + $this->SetSpace(); + $this->Padding(); + $this->LineLength(); + + $this->BorderTop(); + + while($this->Text!="") + { + $this->MakeLine(); + $this->PrintLine(); + } + + $this->BorderBottom(); + } + + + function SetStyle($tag, $family, $style, $size, $color, $indent=-1) + { + $tag=trim($tag); + $this->TagStyle[$tag]['family']=trim($family); + $this->TagStyle[$tag]['style']=trim($style); + $this->TagStyle[$tag]['size']=trim($size); + $this->TagStyle[$tag]['color']=trim($color); + $this->TagStyle[$tag]['indent']=$indent; + } + + + // Private Functions + + function SetSpace() // Minimal space between words + { + $tag=$this->Parser($this->Text); + $this->FindStyle($tag[2],0); + $this->DoStyle(0); + $this->Space=$this->GetStringWidth(" "); + } + + + function Padding() + { + if(preg_match("/^.+,/",$this->Padding)) { + $tab=explode(",",$this->Padding); + $this->lPadding=$tab[0]; + $this->tPadding=$tab[1]; + if(isset($tab[2])) + $this->bPadding=$tab[2]; + else + $this->bPadding=$this->tPadding; + if(isset($tab[3])) + $this->rPadding=$tab[3]; + else + $this->rPadding=$this->lPadding; + } + else + { + $this->lPadding=$this->Padding; + $this->tPadding=$this->Padding; + $this->bPadding=$this->Padding; + $this->rPadding=$this->Padding; + } + if($this->tPadding<$this->LineWidth) + $this->tPadding=$this->LineWidth; + } + + + function LineLength() + { + if($this->wLine==0) + $this->wLine=$this->w - $this->Xini - $this->rMargin; + + $this->wTextLine = $this->wLine - $this->lPadding - $this->rPadding; + } + + + function BorderTop() + { + $border=0; + if($this->border==1) + $border="TLR"; + else if(!is_numeric($this->border)) { + $border = $this->border; + if(empty($this->border)) { + $border = 0; + } else { + $border = ''; + $border.=strpos($this->border, 'T') !== false ? 'T' : ''; + $border.=strpos($this->border, 'L') !== false ? 'L' : ''; + $border.=strpos($this->border, 'R') !== false ? 'R' : ''; + } + } + + $this->Cell($this->wLine,$this->tPadding,"",$border,0,'C',$this->fill); + $y=$this->GetY()+$this->tPadding; + $this->SetXY($this->Xini,$y); + } + + + function BorderBottom() + { + $border=0; + if($this->border==1) + $border="BLR"; + else if(!is_numeric($this->border)) { + $border = $this->border; + if(empty($this->border)) { + $border = 0; + } else { + $border = ''; + $border.=strpos($this->border, 'B') !== false ? 'B' : ''; + $border.=strpos($this->border, 'L') !== false ? 'L' : ''; + $border.=strpos($this->border, 'R') !== false ? 'R' : ''; + } + } + + $this->Cell($this->wLine,$this->bPadding,"",$border,0,'C',$this->fill); + } + + + function DoStyle($tag) // Applies a style + { + $tag=trim($tag); + $this->SetFont($this->TagStyle[$tag]['family'], + $this->TagStyle[$tag]['style'], + $this->TagStyle[$tag]['size']); + + $tab=explode(",",$this->TagStyle[$tag]['color']); + if(count($tab)==1) + $this->SetTextColor($tab[0]); + else + $this->SetTextColor($tab[0],$tab[1],$tab[2]); + } + + + function FindStyle($tag, $ind) // Inheritance from parent elements + { + $tag=trim($tag); + + // Family + if($this->TagStyle[$tag]['family']!="") + $family=$this->TagStyle[$tag]['family']; + else + { + foreach($this->PileStyle as $val) + { + $val=trim($val); + if($this->TagStyle[$val]['family']!="") { + $family=$this->TagStyle[$val]['family']; + break; + } + } + } + + // Style + $style=""; + $style1=strtoupper($this->TagStyle[$tag]['style']); + if($style1!="N") + { + $bold=false; + $italic=false; + $underline=false; + foreach($this->PileStyle as $val) + { + $val=trim($val); + $style1=strtoupper($this->TagStyle[$val]['style']); + if($style1=="N") + break; + else + { + if(strpos($style1,"B")!==false) + $bold=true; + if(strpos($style1,"I")!==false) + $italic=true; + if(strpos($style1,"U")!==false) + $underline=true; + } + } + if($bold) + $style.="B"; + if($italic) + $style.="I"; + if($underline) + $style.="U"; + } + + // Size + if($this->TagStyle[$tag]['size']!=0) + $size=$this->TagStyle[$tag]['size']; + else + { + foreach($this->PileStyle as $val) + { + $val=trim($val); + if($this->TagStyle[$val]['size']!=0) { + $size=$this->TagStyle[$val]['size']; + break; + } + } + } + + // Color + if($this->TagStyle[$tag]['color']!="") + $color=$this->TagStyle[$tag]['color']; + else + { + foreach($this->PileStyle as $val) + { + $val=trim($val); + if($this->TagStyle[$val]['color']!="") { + $color=$this->TagStyle[$val]['color']; + break; + } + } + } + + // Result + $this->TagStyle[$ind]['family']=$family; + $this->TagStyle[$ind]['style']=$style; + $this->TagStyle[$ind]['size']=$size; + $this->TagStyle[$ind]['color']=$color; + $this->TagStyle[$ind]['indent']=$this->TagStyle[$tag]['indent']; + } + + + function Parser($text) + { + $tab=array(); + // Closing tag + if(preg_match("|^(]+)>)|",$text,$regs)) { + $tab[1]="c"; + $tab[2]=trim($regs[2]); + } + // Opening tag + else if(preg_match("|^(<([^>]+)>)|",$text,$regs)) { + $regs[2]=preg_replace("/^a/","a ",$regs[2]); + $tab[1]="o"; + $tab[2]=trim($regs[2]); + + // Presence of attributes + if(preg_match("/(.+) (.+)='(.+)'/",$regs[2])) { + $tab1=preg_split("/ +/",$regs[2]); + $tab[2]=trim($tab1[0]); + foreach($tab1 as $i=>$couple) + { + if($i>0) { + $tab2=explode("=",$couple); + $tab2[0]=trim($tab2[0]); + $tab2[1]=trim($tab2[1]); + $end=strlen($tab2[1])-2; + $tab[$tab2[0]]=substr($tab2[1],1,$end); + } + } + } + } + // Space + else if(preg_match("/^( )/",$text,$regs)) { + $tab[1]="s"; + $tab[2]=' '; + } + // Text + else if(preg_match("/^([^< ]+)/",$text,$regs)) { + $tab[1]="t"; + $tab[2]=trim($regs[1]); + } + + $begin=strlen($regs[1]); + $end=strlen($text); + $text=substr($text, $begin, $end); + $tab[0]=$text; + + return $tab; + } + + + function MakeLine() + { + $this->Text.=" "; + $this->LineLength=array(); + $this->TagHref=array(); + $Length=0; + $this->nbSpace=0; + + $i=$this->BeginLine(); + $this->TagName=array(); + + if($i==0) { + $Length=$this->StringLength[0]; + $this->TagName[0]=1; + $this->TagHref[0]=$this->href; + } + + while($Length<$this->wTextLine) + { + $tab=$this->Parser($this->Text); + $this->Text=$tab[0]; + if($this->Text=="") { + $this->LastLine=true; + break; + } + + if($tab[1]=="o") { + array_unshift($this->PileStyle,$tab[2]); + $this->FindStyle($this->PileStyle[0],$i+1); + + $this->DoStyle($i+1); + $this->TagName[$i+1]=1; + if($this->TagStyle[$tab[2]]['indent']!=-1) { + $Length+=$this->TagStyle[$tab[2]]['indent']; + $this->Indent=$this->TagStyle[$tab[2]]['indent']; + } + if($tab[2]=="a") + $this->href=$tab['href']; + } + + if($tab[1]=="c") { + array_shift($this->PileStyle); + if(isset($this->PileStyle[0])) + { + $this->FindStyle($this->PileStyle[0],$i+1); + $this->DoStyle($i+1); + } + $this->TagName[$i+1]=1; + if($this->TagStyle[$tab[2]]['indent']!=-1) { + $this->LastLine=true; + $this->Text=trim($this->Text); + break; + } + if($tab[2]=="a") + $this->href=""; + } + + if($tab[1]=="s") { + $i++; + $Length+=$this->Space; + $this->Line2Print[$i]=""; + if($this->href!="") + $this->TagHref[$i]=$this->href; + } + + if($tab[1]=="t") { + $i++; + $this->StringLength[$i]=$this->GetStringWidth($tab[2]); + $Length+=$this->StringLength[$i]; + $this->LineLength[$i]=$Length; + $this->Line2Print[$i]=$tab[2]; + if($this->href!="") + $this->TagHref[$i]=$this->href; + } + + } + + trim($this->Text); + if($Length>$this->wTextLine || $this->LastLine==true) + $this->EndLine(); + } + + + function BeginLine() + { + $this->Line2Print=array(); + $this->StringLength=array(); + + if(isset($this->PileStyle[0])) + { + $this->FindStyle($this->PileStyle[0],0); + $this->DoStyle(0); + } + + if(count($this->NextLineBegin)>0) { + $this->Line2Print[0]=$this->NextLineBegin['text']; + $this->StringLength[0]=$this->NextLineBegin['length']; + $this->NextLineBegin=array(); + $i=0; + } + else { + preg_match("/^(( *(<([^>]+)>)* *)*)(.*)/",$this->Text,$regs); + $regs[1]=str_replace(" ", "", $regs[1]); + $this->Text=$regs[1].$regs[5]; + $i=-1; + } + + return $i; + } + + + function EndLine() + { + if(end($this->Line2Print)!="" && $this->LastLine==false) { + $this->NextLineBegin['text']=array_pop($this->Line2Print); + $this->NextLineBegin['length']=end($this->StringLength); + array_pop($this->LineLength); + } + + while(end($this->Line2Print)==="") + array_pop($this->Line2Print); + + $this->Delta=$this->wTextLine-end($this->LineLength); + + $this->nbSpace=0; + for($i=0; $iLine2Print); $i++) { + if($this->Line2Print[$i]=="") + $this->nbSpace++; + } + } + + + function PrintLine() + { + $border=0; + if($this->border==1) + $border="LR"; + else if(!is_numeric($this->border)) { + $border = $this->border; + if(empty($this->border)) { + $border = 0; + } else { + $border = ''; + $border.=strpos($this->border, 'L') !== false ? 'L' : ''; + $border.=strpos($this->border, 'R') !== false ? 'R' : ''; + } + } + $this->Cell($this->wLine,$this->hLine,"",$border,0,'C',$this->fill); + $y=$this->GetY(); + $this->SetXY($this->Xini+$this->lPadding,$y); + + if($this->Indent!=-1) { + if($this->Indent!=0) + $this->Cell($this->Indent,$this->hLine); + $this->Indent=-1; + } + + $space=$this->LineAlign(); + $this->DoStyle(0); + for($i=0; $iLine2Print); $i++) + { + if(isset($this->TagName[$i])) + $this->DoStyle($i); + if(isset($this->TagHref[$i])) + $href=$this->TagHref[$i]; + else + $href=''; + if($this->Line2Print[$i]=="") + $this->Cell($space,$this->hLine," ",0,0,'C',false,$href); + else + $this->Cell($this->StringLength[$i],$this->hLine,$this->Line2Print[$i],0,0,'C',false,$href); + } + + $this->LineBreak(); + if($this->LastLine && $this->Text!="") + $this->EndParagraph(); + $this->LastLine=false; + } + + + function LineAlign() + { + $space=$this->Space; + if($this->align=="J") { + if($this->nbSpace!=0) + $space=$this->Space + ($this->Delta/$this->nbSpace); + if($this->LastLine) + $space=$this->Space; + } + + if($this->align=="R") + $this->Cell($this->Delta,$this->hLine); + + if($this->align=="C") + $this->Cell($this->Delta/2,$this->hLine); + + return $space; + } + + + function LineBreak() + { + $x=$this->Xini; + $y=$this->GetY()+$this->hLine; + $this->SetXY($x,$y); + } + + + function EndParagraph() + { + $border=0; + if($this->border==1) + $border="LR"; + $this->Cell($this->wLine,$this->hLine/2,"",$border,0,'C',$this->fill); + $x=$this->Xini; + $y=$this->GetY()+$this->hLine/2; + $this->SetXY($x,$y); + } + + //Cell with horizontal scaling if text is too wide + function CellFit($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='', $scale=false, $force=true) + { + //Get string width + $str_width=$this->GetStringWidth($txt); + + //Calculate ratio to fit cell + if($w==0) + $w = $this->w-$this->rMargin-$this->x; + $ratio = ($w-$this->cMargin*2)/$str_width; + + $fit = ($ratio < 1 || ($ratio > 1 && $force)); + if ($fit) + { + if ($scale) + { + //Calculate horizontal scaling + $horiz_scale=$ratio*100.0; + //Set horizontal scaling + $this->_out(sprintf('BT %.2F Tz ET',$horiz_scale)); + } + else + { + //Calculate character spacing in points + $char_space=($w-$this->cMargin*2-$str_width)/max(strlen($txt)-1,1)*$this->k; + //Set character spacing + $this->_out(sprintf('BT %.2F Tc ET',$char_space)); + } + //Override user alignment (since text will fill up cell) + $align=''; + } + + //Pass on to Cell method + $this->Cell($w,$h,$txt,$border,$ln,$align,$fill,$link); + + //Reset character spacing/horizontal scaling + if ($fit) + $this->_out('BT '.($scale ? '100 Tz' : '0 Tc').' ET'); + } + + //Cell with character spacing only if necessary + function CellFitSpace($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='') + { + $this->CellFit($w,$h,$txt,$border,$ln,$align,$fill,$link,false,false); + } + + public function RowForDownloadAttendance($data,$border=0,$fill=0,$draw=0) + { + //Calculate the height of the row + $nb=0; + for($i=0;$iNbLines($this->widths[$i],$data[$i])); + } + + $h=4*$nb; + //Issue a page break first if needed + $this->CheckPageBreak($h); + //Draw the cells of the row + for($i=0;$iwidths[$i]; + $nb1=$this->NbLines($this->widths[$i],$data[$i]); + $a=isset($this->aligns[$i]) ? $this->aligns[$i] : 'L'; + + //Save the current position + $x=$this->GetX(); + $y=$this->GetY(); + + //Draw the border + $this->Rect($x,$y,$w,$h,$draw); + $this->SetTextColor(0, 0, 0); + + $tempNote = explode(' ',$data[$i]); + if($data[$i]=='Missing'|| $data[$i]=='Missing Finger In' || $data[$i]=='AWN' || $data[$i]=='Late In' || $data[$i]=='time in not in range shift !!' || $data[$i]=='Missing Finger Out' || $data[$i]=='Early Out' || $data[$i]=='Late In Early Out' || $tempNote[0]=='Undisciplined'){ + // $this->SetTextColor(81, 156, 132); + $this->SetTextColor(255, 48, 33); + } + if($i==3&& $data[9]=='Late In'){ + $this->SetTextColor(255, 48, 33); + } + if($i==6&& $data[9]=='Early Out'){ + $this->SetTextColor(255, 48, 33); + } + + if(($i==3||$i==6)&& $data[9]=='Late In Early Out'){ + $this->SetTextColor(255, 48, 33); + } + //Print the text + $this->MultiCell($w,($h/$nb1),$data[$i],$border,$a,$fill); + + //Put the position to the right of the cell + $this->SetXY($x+$w,$y); + } + + //Go to the next line + $this->Ln($h); + } + + function drawTextBox($strText, $w, $h, $align='L', $valign='T', $border=true, $withLine = false) { + $xi=$this->GetX(); + $yi=$this->GetY(); + + $hrow=$this->FontSize; + $textrows=$this->drawRows($w,$hrow,$strText,0,$align,0,0,0); + $maxrows=floor($h/$this->FontSize); + $rows=min($textrows,$maxrows); + + $dy=0; + if (strtoupper($valign)=='M') + $dy=($h-$rows*$this->FontSize)/2; + if (strtoupper($valign)=='B') + $dy=$h-$rows*$this->FontSize; + + $this->SetY($yi+$dy); + $this->SetX($xi); + + $this->drawRows($w,$hrow,$strText,0,$align,false,$rows,1); + + if ($border) + $this->Rect($xi,$yi,$w,$h); + } + + function drawRows($w, $h, $txt, $border=0, $align='J', $fill=false, $maxline=0, $prn=0) + { + if(!isset($this->CurrentFont)) + $this->Error('No font has been set'); + $cw=$this->CurrentFont['cw']; + if($w==0) + $w=$this->w-$this->rMargin-$this->x; + $wmax=($w-2*$this->cMargin)*1000/$this->FontSize; + $s=str_replace("\r",'',(string)$txt); + $nb=strlen($s); + if($nb>0 && $s[$nb-1]=="\n") + $nb--; + $b=0; + if($border) + { + if($border==1) + { + $border='LTRB'; + $b='LRT'; + $b2='LR'; + } + else + { + $b2=''; + if(is_int(strpos($border,'L'))) + $b2.='L'; + if(is_int(strpos($border,'R'))) + $b2.='R'; + $b=is_int(strpos($border,'T')) ? $b2.'T' : $b2; + } + } + $sep=-1; + $i=0; + $j=0; + $l=0; + $ns=0; + $nl=1; + while($i<$nb) + { + //Get next character + $c=$s[$i]; + if($c=="\n") + { + //Explicit line break + if($this->ws>0) + { + $this->ws=0; + if ($prn==1) $this->_out('0 Tw'); + } + if ($prn==1) { + $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill); + } + $i++; + $sep=-1; + $j=$i; + $l=0; + $ns=0; + $nl++; + if($border && $nl==2) + $b=$b2; + if ( $maxline && $nl > $maxline ) + return substr($s,$i); + continue; + } + if($c==' ') + { + $sep=$i; + $ls=$l; + $ns++; + } + $l+=$cw[$c]; + if($l>$wmax) + { + //Automatic line break + if($sep==-1) + { + if($i==$j) + $i++; + if($this->ws>0) + { + $this->ws=0; + if ($prn==1) $this->_out('0 Tw'); + } + if ($prn==1) { + $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill); + } + } + else + { + if($align=='J') + { + $this->ws=($ns>1) ? ($wmax-$ls)/1000*$this->FontSize/($ns-1) : 0; + if ($prn==1) $this->_out(sprintf('%.3F Tw',$this->ws*$this->k)); + } + if ($prn==1){ + $this->Cell($w,$h,substr($s,$j,$sep-$j),$b,2,$align,$fill); + } + $i=$sep+1; + } + $sep=-1; + $j=$i; + $l=0; + $ns=0; + $nl++; + if($border && $nl==2) + $b=$b2; + if ( $maxline && $nl > $maxline ) + return substr($s,$i); + } + else + $i++; + } + //Last chunk + if($this->ws>0) + { + $this->ws=0; + if ($prn==1) $this->_out('0 Tw'); + } + if($border && is_int(strpos($border,'B'))) + $b.='B'; + if ($prn==1) { + $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill); + } + $this->x=$this->lMargin; + return $nl; + } +} + +// if(function_exists('mcrypt_encrypt')) +// { +// function RC4($key, $data) +// { +// return mcrypt_encrypt(MCRYPT_ARCFOUR, $key, $data, MCRYPT_MODE_STREAM, ''); +// } +// } +// else +// { + function RC4($key, $data) + { + static $last_key, $last_state; + + if($key != $last_key) + { + $k = str_repeat($key, 256/strlen($key)+1); + $state = range(0, 255); + $j = 0; + for ($i=0; $i<256; $i++){ + $t = $state[$i]; + $j = ($j + $t + ord($k[$i])) % 256; + $state[$i] = $state[$j]; + $state[$j] = $t; + } + $last_key = $key; + $last_state = $state; + } + else + $state = $last_state; + + $len = strlen($data); + $a = 0; + $b = 0; + $out = ''; + for ($i=0; $i<$len; $i++){ + $a = ($a+1) % 256; + $t = $state[$a]; + $b = ($b+$t) % 256; + $state[$a] = $state[$b]; + $state[$b] = $t; + $k = $state[($state[$a]+$state[$b]) % 256]; + $out .= chr(ord($data[$i]) ^ $k); + } + return $out; + } +// } diff --git a/Aiko/Aiko/Libs/MyPdf.php:Zone.Identifier b/Aiko/Aiko/Libs/MyPdf.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/MyPdf.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/Mycrypt.php b/Aiko/Aiko/Libs/Mycrypt.php new file mode 100644 index 0000000..937f824 --- /dev/null +++ b/Aiko/Aiko/Libs/Mycrypt.php @@ -0,0 +1,35 @@ + \ No newline at end of file diff --git a/Aiko/Aiko/Libs/Mycrypt.php:Zone.Identifier b/Aiko/Aiko/Libs/Mycrypt.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/Mycrypt.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/Query.php b/Aiko/Aiko/Libs/Query.php new file mode 100644 index 0000000..2e7f793 --- /dev/null +++ b/Aiko/Aiko/Libs/Query.php @@ -0,0 +1,35 @@ +debug_mode=$debug_mode; + $this->query=$query; + $this->registry=$registry; + } + public function getData($param=array()) + { + try{ + + } catch (PDOException $e) + { + if($this->debug_mode) + { + return $e->getMessage(); + }else + { + return FALSE; + } + + } + + + $this->param=$param; + $obj = new processdata(); + return $obj; + } +} \ No newline at end of file diff --git a/Aiko/Aiko/Libs/Query.php:Zone.Identifier b/Aiko/Aiko/Libs/Query.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/Query.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/QueryParam.php b/Aiko/Aiko/Libs/QueryParam.php new file mode 100644 index 0000000..177dfbf --- /dev/null +++ b/Aiko/Aiko/Libs/QueryParam.php @@ -0,0 +1,41 @@ +dataType=$dataType; + return $this; + } + public function query($query) + { + $this->query=$query; + return $this; + } + public function data($data) + { + $this->data=$data; + return $this; + } + public function placeHolder($placeHolder) + { + $this->placeHolder=$placeHolder; + return $this; + } + public function getDataType() + { + return $this->dataType; + } + public function getData() + { + return $this->data; + } + public function getPlaceHolder() + { + return $this->placeHolder; + } +} \ No newline at end of file diff --git a/Aiko/Aiko/Libs/QueryParam.php:Zone.Identifier b/Aiko/Aiko/Libs/QueryParam.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/QueryParam.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/QueryProcess.php b/Aiko/Aiko/Libs/QueryProcess.php new file mode 100644 index 0000000..bcbf346 --- /dev/null +++ b/Aiko/Aiko/Libs/QueryProcess.php @@ -0,0 +1,24 @@ +lifeTime = get_cfg_var("session.gc_maxlifetime"); + // open database-connection + return true; + } + function close() { + $this->gc(ini_get('session.gc_maxlifetime')); + + } + function read($sessID) { + // fetch session-data + try { + $this->registry->log->error('read :'.$sessID.' :'); + // var_dump($sessID); + $query="SELECT session_data AS d FROM ws_sessions WHERE session_id = '$sessID' AND session_expires > ".time(); + $stmt=$this->registry->db->prepare($query); + $stmt->execute(); + $rs=$stmt->fetchAll(PDO::FETCH_ASSOC); + return (count($rs)>0)?$rs[0]['d']:''; + } catch (PDOException $e) { + + $this->registry->log->error('module session/read :'.$e->getMessage()); + return ''; + } + } + function write($sessID,$sessData) { + // new session-expire-time + + $this->registry->log->error('write :'.$sessID.' :'.$sessData); + $newExp = time() + $this->lifeTime; + // is a session with this id in the database? + $fd=0; + try { + $sql="SELECT count(0) as found FROM ws_sessions + WHERE session_id =:sessionID"; + $stmt=$this->registry->db->prepare($sql); + $stmt->bindValue(':sessionID',$sessID,PDO::PARAM_STR); + $stmt->execute(); + $rs=$stmt->fetchAll(PDO::FETCH_ASSOC); + $fd=$rs[0]['found']; + } catch (PDOException $e) { + $fd=0; + $this->registry->log->error('module session /write :'.$e->getMessage()); + } + + + if($fd>0) + { + if(!empty($sessData)){ + try { + $sql="UPDATE ws_sessions + SET session_expires =:sessionExpired, + session_data =:sessionData + WHERE session_id =:sessionID"; + + $stmt=$this->registry->db->prepare($sql); + $stmt->bindValue(':sessionID',$sessID,PDO::PARAM_STR); + $stmt->bindValue(':sessionExpired',$newExp,PDO::PARAM_INT); + $stmt->bindValue(':sessionData',$sessData,PDO::PARAM_STR); + $stmt->execute(); + $resUpdate=true; + } catch (PDOException $e) { + $this->registry->log->error('module session /write :'.$e->getMessage()); + $resUpdate=false; + } + return $resUpdate; + }else + { + try { + $sql="delete from ws_sessions WHERE session_id =:sessionID"; + $stmt=$this->registry->db->prepare($sql); + $stmt->bindValue(':sessionID',$sessID,PDO::PARAM_STR); + $stmt->execute(); + $resultDelete=true; + } catch (PDOException $e) { + $this->registry->log->error('module session /write :'.$e->getMessage()); + $resultDelete=false; + } + + return $resultDelete; + } + }else + { + $resultInsert=false; + + if(!empty($sessData)){ + try { + $sql="INSERT INTO ws_sessions ( + session_id, + session_expires, + session_data) + VALUES( + :sessionID, + :sessionExpired, + :sessionData)"; + $stmt=$this->registry->db->prepare($sql); + $stmt->bindValue(':sessionID',$sessID,PDO::PARAM_STR); + $stmt->bindValue(':sessionExpired',$newExp,PDO::PARAM_INT); + $stmt->bindValue(':sessionData',$sessData,PDO::PARAM_STR); + $stmt->execute(); + $resultInsert=true; + } catch (PDOException $e) { + $this->registry->log->error('module session /write :'.$e->getMessage()); + $resultInsert=false; + } + + } + return $resultInsert; + } + + + return false; + } + function destroy($sessID) { + + try { + + $sql="DELETE FROM ws_sessions WHERE session_id = '$sessID'"; + $stmt=$this->registry->db->prepare($sql); + $stmt->execute(); + + return true; + } catch (PDOException $exc) { + $this->registry->log->error('module session /write :'.$e->getMessage()); + return false; + } + } + function gc($sessMaxLifeTime) { + + + try{ + + + /** + * sql dibawah ini digunakan untuk ambil session id yang sudah expired dan update data user session nya jika menggunakan sesion user + */ + $sql="select session_id from ws_sessions WHERE session_expires < ".time(); + $stmt=$this->registry->db->prepare($sql); + $stmt->execute(); + $rs=$stmt->fetchAll(PDO::FETCH_ASSOC); + + + $sql="DELETE FROM ws_sessions WHERE session_expires < ".time(); + $stmt=$this->registry->db->prepare($sql); + $stmt->execute(); + return true; + } catch (PDOException $e) + { + $this->registry->log->error('module session /write :'.$e->getMessage()); + return false; + } + + + } +} + + +?> diff --git a/Aiko/Aiko/Libs/Session.php:Zone.Identifier b/Aiko/Aiko/Libs/Session.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/Session.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/Storage.php b/Aiko/Aiko/Libs/Storage.php new file mode 100644 index 0000000..890a82f --- /dev/null +++ b/Aiko/Aiko/Libs/Storage.php @@ -0,0 +1,134 @@ +registry = $registry; + $this->isProduction = $this->registry->config->environment === 'production'; + $this->baseStorage = $this->isProduction ? $this->registry->config->base_storage : __SITE_PATH . '/hcportal_docs/'; + } + + public function fromException($e, $action) + { + return Helper::handleException($this->registry, $e, "storage", $action, false, "Storage"); + } + + /** @param UploadedFile $file */ + public function validateFile($file, $maxSize = 2048, $allowedMime = []) + { + if ($file instanceof UploadedFile) { + $mime = $file->getMimeType(); + if (in_array($mime, $allowedMime)) return true; + return false; + } + return false; + } + + // + // + // @param $options = [ + // 'mime' => [], + // 'size' => 0 + // ] + public function store($file, $folderName = 'temp', $prefix = '', $options = []) + { + try { + $storage = $this->trimSlashes($this->baseStorage . '/' . $folderName . '/'); + $default = $this->generateFilename($file); + $filename = $default; + if ($prefix) { + $filename = $prefix . '_' . $default; + } + $file->move($storage, $filename); + return $filename; + } catch (FileException $e) { + return $this->fromException($e, "store"); + } catch (ErrorException $e) { + return $this->fromException($e, "store"); + } + } + + public function delete($filename, $folderName = 'temp') + { + try { + $link = $this->trimSlashes($this->baseStorage . '/' . $folderName . '/' . $filename); + if (file_exists($link)) { + if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { + $fileTmp = $link; + $fileTmp = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR, $fileTmp); + @unlink($fileTmp); + } else { + unlink($link); + } + } + return true; + } catch (Exception $e) { + return $this->fromException($e, "delete"); + } + } + + public function url($filename, $path = 'temp', $isLocal = false) + { + if (!$filename) { + return null; + } + $filePath = $this->trimSlashes('hcportal_docs/' . $path . '/' . $filename); + $prefix = $this->registry->config->server_address; + if($isLocal){ + $prefix = __SITE_PATH.'/'; + } + return $prefix . $filePath; + } + + public function generateFilename($file) + { + $time = time(); + $filename = uniqid() . '_' . $time . '.' . $file->guessExtension(); + return $filename; + } + + public function isValidImage($mimeType) + { + return $this->validateMime($mimeType, [ + 'image/jpeg', + 'image/png', + 'image/jpg' + ]); + return true; + } + + public function isValidDocument($mimeType) + { + return $this->validateMime($mimeType, [ + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'application/vnd.ms-excel', + 'application/pdf' + ]); + } + + private function validateMime($mimeType, $mimeClientAlowed) + { + if (!in_array($mimeType, $mimeClientAlowed)) { + return false; + } + return true; + } + + private function trimSlashes($str) + { + return preg_replace('/(\/+)/', '/', $str); + } +} diff --git a/Aiko/Aiko/Libs/Storage.php:Zone.Identifier b/Aiko/Aiko/Libs/Storage.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/Storage.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/Token.php b/Aiko/Aiko/Libs/Token.php new file mode 100644 index 0000000..4c3ebbe --- /dev/null +++ b/Aiko/Aiko/Libs/Token.php @@ -0,0 +1,349 @@ +get_token_from_session('token'); + // var_dump($sessiontoken); + // exit(); + + + $valid = strlen($sessiontoken) == 128 && strlen($token) == 128 && $sessiontoken == $token; + + $this->get_token($area); // refresh token + + return $valid; + } + public function get_token_from_url() + { + $token = isset($_GET['token']) ? $_GET['token'] : ''; + + return $token; + } + + public function get_token_from_session($key) + { + $token = isset($_SESSION[$key]) ? $_SESSION[$key] : ''; + + return $token; + } + public function getTokenAuthUser() + { + $token = hash('sha512', mt_rand(0, mt_getrandmax()) . microtime(true)); + $_SESSION['tokenAuth'] = $token; + + return $token; + } + public function check_tokenAuthUser($token) + { + $sessiontoken = $this->get_token_from_session('tokenAuth'); + $valid = strlen($sessiontoken) == 128 && strlen($token) == 128 && $sessiontoken == $token; + if ($valid) { + return true; + } else { + return false; + } + } + + public function set_cookie() + { + $result = password_hash('4pl1k4s1D1sd1K', PASSWORD_DEFAULT, array('cost' => 10)); + // $res = setcookie('XSRF-TOKEN', $result, time() + 86400, $_SERVER['REQUEST_URI'],'',false,false); + + $res = setcookie('XSRF-TOKEN', $result, time() + 86400, '/'); + if ($res) { + return true; + } else { + return false; + } + } + public function cek_cookie($clientCookie) + { + $result = false; + if (isset($_COOKIE['XSRF-TOKEN'])) { + $serverCookie = $_COOKIE['XSRF-TOKEN']; + $result = $this->cek_hash($clientCookie, $serverCookie); + } + + return $result; + } + + private function cek_hash($clientCookie, $serverCookie) + { + if ($clientCookie == $serverCookie) { + return $this->set_cookie(); + } else { + return false; + } + } + + private static function wrapToken($jwt, $chipper) + { + try { + if (strlen($chipper) <> 6) { + throw new \ErrorException('chipper failed'); + } + $headerPreffix = (int) substr($chipper, 0, 1); + $headerSuffix = (int) substr($chipper, 1, 1); + $payloadPreffix = (int) substr($chipper, 2, 1); + $payloadSuffix = (int) substr($chipper, 3, 1); + $signPreffix = (int) substr($chipper, 4, 1); + $signSuffix = (int) substr($chipper, 5, 1); + + $jwtPart = explode('.', $jwt); + + $newJwt = self::randomChars($headerPreffix) . $jwtPart[0] . self::randomChars($headerSuffix); + + $newJwt .= '.' . self::randomChars($payloadPreffix) . $jwtPart[1] . self::randomChars($payloadSuffix); + + $newJwt .= '.' . self::randomChars($signPreffix) . $jwtPart[2] . self::randomChars($signSuffix); + + return $newJwt; + } catch (\Exception $e) { + return false; + } + } + + private static function unWrapToken($jwt, $chipper) + { + try { + if (strlen($chipper) <> 6) { + throw new \ErrorException('chipper failed'); + } + + $headerPreffix = (int) substr($chipper, 0, 1); + $headerSuffix = (int) substr($chipper, 1, 1); + $payloadPreffix = (int) substr($chipper, 2, 1); + $payloadSuffix = (int) substr($chipper, 3, 1); + $signPreffix = (int) substr($chipper, 4, 1); + $signSuffix = (int) substr($chipper, 5, 1); + + $jwtPart = explode('.', $jwt); + + $newString = self::removePreSuf($jwtPart[0], $headerPreffix, $headerSuffix); + if ($newString == false) { + throw new \ErrorException('failed clean wrapper header'); + } + $header = $newString; + + $newString = self::removePreSuf($jwtPart[1], $payloadPreffix, $payloadSuffix); + if ($newString == false) { + throw new \ErrorException('failed clean wrapper payload'); + } + $payload = $newString; + + $newString = self::removePreSuf($jwtPart[2], $signPreffix, $signSuffix); + if ($newString == false) { + throw new \ErrorException('failed clean wrapper sign'); + } + $sign = $newString; + + return $header . '.' . $payload . '.' . $sign; + } catch (\ErrorException $e) { + return false; + } + } + + private static function removePreSuf($string, $preffix, $suffix) + { + $jum = strlen(trim($string)); + $totWrapper = ($preffix + $suffix); + $tot = $totWrapper + 10; // set minimum text + if ($jum > $tot) { + $total = $jum - $totWrapper; + $newString = substr($string, $preffix, $total); + return $newString; + } + + return false; + } + + private static function randomChars($numChars) + { + $str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuzwxyz'; + return substr(str_shuffle($str), 0, $numChars); + } + + public static function encodeJWT($serverName, $dataUser, $chipper = '000000') + { + + try { + + $log = new Log('1'); + // $publicKey = file_get_contents('/Users/suhendra/mykey/suhendra_rsa.pub'); + + $privateKey = file_get_contents(__SITE_PATH . '/mykey/hcportalprivate.pem'); + + // $privateKey = openssl_get_privatekey('file:///Users/suhendra/mykey/suhendra_rsa','suh3ndr4'); + // var_dump($privateKey); + + //$tokenId = base64_encode(\mcrypt_create_iv(32)); + $tokenId = base64_encode(\openssl_random_pseudo_bytes(64)); + // $random = mt_rand(0, 999999); + // $random_string = sha1($random); + //$tokenId = base64_encode(date('Y-m-d H:i:s')); + $issuedAt = time(); + $notBefore = time(); + $expire = $notBefore + __LIFETIMEJWT; // Adding 10 menit + + /* + * Create the token as an array + */ + $data = [ + 'iat' => $issuedAt, // Issued at: time when the token was generated + 'jti' => $tokenId, // Json Token Id: an unique identifier for the token / A unique string, could be used to validate a token, but goes against not having a centralized issuer authority. + 'iss' => $serverName, // A string containing the name or identifier of the issuer application. Can be a domain name and can be used to discard tokens from other applications. + 'nbf' => $notBefore, // Timestamp of when the token should start being considered valid. Should be equal to or greater than iat. In this case, the token will begin to be valid 10 seconds + 'exp' => $expire, // Timestamp of when the token should cease to be valid. Should be greater than iat and nbf. In this case, the token will expire 60 seconds after being issued. + 'data' => $dataUser, + ]; + + $jwt = JWT::encode( + $data, //Data to be encoded in the JWT + $privateKey, // The signing key + 'RS256' // Algorithm used to sign the token, see https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40#section-3 + ); + + // var_dump($jwt); + + $newJwt = self::wrapToken($jwt, $chipper); + // var_dump($newJwt); + + if ($newJwt == false) { + throw new \ErrorException('Failed wrap Token'); + } + + $dataUser['expired'] = $expire; + $dataHeader = array( + 'jwt' => $newJwt, + 'tokenID' => $tokenId, + 'appID' => $serverName, + 'data' => $dataUser, + 'expired' => $expire + ); + + return $dataHeader; + } catch (\ErrorException $e) { + $log->error('encode token token/decodeJWT' . $e->getMessage()); + return false; + } + } + + public static function decodeJWT($jwt, $chipper = '000000') + { + try { + $log = new Log('1'); + + $publicKey = file_get_contents(__SITE_PATH . '/mykey/hcportalpublic.pem'); + + $newJwt = self::unWrapToken($jwt, $chipper); + + $token = JWT::decode($newJwt, $publicKey, array('RS256')); + + return $token; + } catch (\DomainException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\InvalidArgumentException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\UnexpectedValueException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\DateTime $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\SignatureInvalidException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\BeforeValidException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\Firebase\JWT\ExpiredException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } + } + + public static function decodeJWTNew($jwt, $chipper = '000000') + { + try { + $log = new Log('1'); + + $publicKey = file_get_contents(__SITE_PATH . '/mykey/hcportalpublic.pem'); + + $newJwt = self::unWrapToken($jwt, $chipper); + + $token = JWT::decode($newJwt, $publicKey, array('RS256')); + return $token; + } catch (\DomainException $e) { + $log->error('decode token token/decodeJWT 2 ' . $e->getMessage() . 'JWT |' . $jwt); + return 2; + } catch (\InvalidArgumentException $e) { + $log->error('decode token token/decodeJWT 3' . $e->getMessage() . 'JWT |' . $jwt); + return 3; + } catch (\UnexpectedValueException $e) { + $log->error('decode token token/decodeJWT 4' . $e->getMessage() . 'JWT |' . $jwt); + if ($e->getMessage() == 'Expired token') { + return 8; + } + return 4; + } catch (\DateTime $e) { + $log->error('decode token token/decodeJWT 5' . $e->getMessage() . 'JWT |' . $jwt); + return 5; + } catch (\SignatureInvalidException $e) { + $log->error('decode token token/decodeJWT 6' . $e->getMessage() . 'JWT |' . $jwt); + return 6; + } catch (\BeforeValidException $e) { + $log->error('decode token token/decodeJWT 7' . $e->getMessage() . 'JWT |' . $jwt); + return 7; + } catch (\Firebase\JWT\ExpiredException $e) { + $log->error('decode token token/decodeJWT 8' . $e->getMessage() . 'JWT |' . $jwt); + return 8; + } + } + + public static function decodePlainJWT($jwt, $key = null) + { + try { + $log = new Log('1'); + + $token = JWT::decode($jwt, $key, array('HS256')); + + return $token; + } catch (\DomainException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\InvalidArgumentException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\UnexpectedValueException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\Firebase\JWT\SignatureInvalidException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\Firebase\JWT\BeforeValidException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\Firebase\JWT\ExpiredException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } + } +} diff --git a/Aiko/Aiko/Libs/Token.php:Zone.Identifier b/Aiko/Aiko/Libs/Token.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/Token.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/TokenSanitation.php b/Aiko/Aiko/Libs/TokenSanitation.php new file mode 100644 index 0000000..376a270 --- /dev/null +++ b/Aiko/Aiko/Libs/TokenSanitation.php @@ -0,0 +1,87 @@ +token=$this->unWrapToken($jwt,$clientChipper); + } + + public function getToken(){ + return $this->token; + } + + public function getErros(){ + return $this->errors; + } + + private function unWrapToken($jwt, $chipper) + { + try { + if (strlen($chipper) <> 6) { + throw new \ErrorException('chipper failed'); + } + + $headerPreffix = (int) substr($chipper, 0, 1); + $headerSuffix = (int) substr($chipper, 1, 1); + $payloadPreffix = (int) substr($chipper, 2, 1); + $payloadSuffix = (int) substr($chipper, 3, 1); + $signPreffix = (int) substr($chipper, 4, 1); + $signSuffix = (int) substr($chipper, 5, 1); + + $jwtPart = explode('.', $jwt); + + + + if (count($jwtPart) != 4) { + throw new \ErrorException('token part invalid'); + } + + + $newString = $this->removePreSuf($jwtPart[0], $headerPreffix, $headerSuffix); + if ($newString == false) { + throw new \ErrorException('failed clean wrapper header'); + } + $header = $newString; + + $newString = $this->removePreSuf($jwtPart[1], $payloadPreffix, $payloadSuffix); + if ($newString == false) { + throw new \ErrorException('failed clean wrapper payload'); + } + $payload = $newString; + + $newString = $this->removePreSuf($jwtPart[2], $signPreffix, $signSuffix); + if ($newString == false) { + throw new \ErrorException('failed clean wrapper sign'); + } + $sign = $newString; + + return $header . '.' . $payload . '.' . $sign; + } catch (\ErrorException $e) { + array_push($this->errors,array($e->getMessage())); + return false; + } + } + + private function removePreSuf($string, $preffix, $suffix) + { + $jum = strlen(trim($string)); + $totWrapper = ($preffix + $suffix); + $tot = $totWrapper + 10; // set minimum text + if ($jum > $tot) { + $total = $jum - $totWrapper; + $newString = substr($string, $preffix, $total); + return $newString; + } + + return false; + } + + +} diff --git a/Aiko/Aiko/Libs/TokenSanitation.php:Zone.Identifier b/Aiko/Aiko/Libs/TokenSanitation.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/TokenSanitation.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/Trait.php b/Aiko/Aiko/Libs/Trait.php new file mode 100644 index 0000000..80b2272 --- /dev/null +++ b/Aiko/Aiko/Libs/Trait.php @@ -0,0 +1,50 @@ +db->beginTransaction(); + + // drop tmp table + $sqlDropExist = "DROP TEMPORARY TABLE IF EXISTS $tblname"; + $stmtDropExist=$this->registry->db->prepare($sqlDropExist); + $stmtDropExist->execute(); + + // create table + $sqlCreate='CREATE TEMPORARY TABLE '.$tblname. ' ( '; + $sqlCreate .=$fields[0]['field'].' '.$fields[0]['type'].'('.$fields[0]['length'].')'; + $jum=count($fields); + for ($i = 1; $i < $jum; $i++) { + $sqlCreate .=' , '.$fields[$i]['field'].' '.$fields[$i]['type'].'('.$fields[$i]['length'].')'; + } + + + $sqlCreate .=')'; + + var_dump($sqlCreate); + + $registry->db->commit(); + + return true; + } catch (PDOException $e) { + $registry->db->rollBack(); + $this->registry->log->error('Main trait in lib /saveToTmpTable :'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + + return false; + } catch (ErrorException $e) { + $registry->db->rollBack(); + $this->registry->log->error('Main trait in lib /saveToTmpTable :'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + + return false; + } + } +} \ No newline at end of file diff --git a/Aiko/Aiko/Libs/Trait.php:Zone.Identifier b/Aiko/Aiko/Libs/Trait.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/Trait.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/Validator.php b/Aiko/Aiko/Libs/Validator.php new file mode 100644 index 0000000..bc45627 --- /dev/null +++ b/Aiko/Aiko/Libs/Validator.php @@ -0,0 +1,110 @@ +rules = $rules; + if (!is_array($request) && is_object($request)) { + $this->request = json_decode(json_encode($request), true); + } else { + $this->request = $request; + } + } + + /** + * @param string $paramKey + * @param \Closure($value, $params): string|null $validatorFn + */ + public function addRule($paramKey, $validatorFn, $messages = []) + { + array_push($this->rules, new ValidationRule($this->request, $paramKey, $validatorFn, $messages)); + return $this; + } + + public function fails() + { + return count($this->errorBag) > 0; + } + + public function safe($key = null) + { + if (is_null($key)) { + return $this->valid; + } + if (isset($this->valid[$key])) { + return $this->valid[$key]; + } + return null; + } + + public function all() + { + return $this->request; + } + + public function only($keys = []) + { + $request = []; + foreach ($keys as $key) { + if (array_key_exists($key, $this->request)) { + $request[$key] = $this->request[$key]; + } + } + return $request; + } + + public function errors() + { + return $this->errorBag; + } + + public function validate($throw = false) + { + /** @var ValidationRule $rule */ + foreach ($this->rules as $rule) { + if (!$rule->validate()) { + if ($throw) { + throw new ValidatorException($rule->key, $rule->errorBag); + } + array_push($this->errorBag, $rule->errorBag); + continue; + } + $this->valid[$rule->key] = $rule->getParamValue(); + } + } +} + + +class ValidatorException extends Exception +{ + private $data; + + // Redefine the exception so message isn't optional + public function __construct($message, $data = [], $previous = null) + { + parent::__construct($message, 0, $previous); + $this->data = $data; + } + + // custom string representation of object + public function __toString() + { + return __CLASS__ . ": [{$this->code}]: {$this->message}\n"; + } + + public function getData() + { + return $this->data; + } +} \ No newline at end of file diff --git a/Aiko/Aiko/Libs/Validator.php:Zone.Identifier b/Aiko/Aiko/Libs/Validator.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/Validator.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/ValidatorRule.php b/Aiko/Aiko/Libs/ValidatorRule.php new file mode 100644 index 0000000..e227d1b --- /dev/null +++ b/Aiko/Aiko/Libs/ValidatorRule.php @@ -0,0 +1,101 @@ +key = $key; + $this->action = $action; + $this->paramBag = $paramBag; + $this->messages = $messages; + } + + public function validate() + { + $param = $this->getParamValue(); + if (is_callable($this->action)) { + $fn = $this->action; + $message = $fn($param, $this->paramBag); + if ($message !== null) { + $this->addError($message); + return false; + } + } else if (is_string($this->action)) { + $repo = new ValidatorRuleCollection(); + $ref = new ReflectionClass($repo); + $method = $this->action; + if (strpos($this->action, '|') != false) { + $exp = explode('|', $this->action); + $method = $exp[0]; + } + try { + $refMethod = $ref->getMethod($method); + $result = $refMethod->invokeArgs(new ValidatorRuleCollection(), [$this->key, $this->action, $param, $this->paramBag]); + if (!is_null($result)) { + $this->addError($result); + return false; + } + return true; + } catch (\ReflectionException $e) { + return false; + } + } else { + // defensive action + return false; + } + return true; + } + + public function parseMessage($messageKey) + { + if (array_key_exists($messageKey, $this->messages)) { + return $this->messages[$messageKey]; + } + return $messageKey; + } + + public function addError($message = null) + { + $this->errorBag = [ + 'key' => $this->key, + 'message' => is_null($message) ? "{$this->key} cant be empty" : $this->parseMessage($message) + ]; + } + + public function getParamValue() + { + if (array_key_exists($this->key, $this->paramBag)) { + return $this->paramBag[$this->key]; + } + return null; + } +} diff --git a/Aiko/Aiko/Libs/ValidatorRule.php:Zone.Identifier b/Aiko/Aiko/Libs/ValidatorRule.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/ValidatorRule.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/ValidatorRuleCollection.php b/Aiko/Aiko/Libs/ValidatorRuleCollection.php new file mode 100644 index 0000000..9ab18a5 --- /dev/null +++ b/Aiko/Aiko/Libs/ValidatorRuleCollection.php @@ -0,0 +1,136 @@ + '123456', 'password_confirmation' => '123456'] + * new Validator($params)->addRule('password', 'mustMatch|password_confirmation'); + * + */ + public function mustMatch($key, $ruleString, $value, $params) + { + $keys = explode('|', $ruleString); + if (count($keys) < 2) { + throw new Exception("validator rules not valid for $$ruleString"); + } + $compare1 = $this->_getParamValue($keys[1], $params); + $compare2 = $this->_getParamValue($key, $params); + if (is_null($compare1) || is_null($compare2)) { + return "VALIDATOR.MUST_MATCH.MUST_NOT_EMPTY"; + } + if ($compare1 != $compare2) { + return "VALIDATOR.MUST_MATCH.NOT_MATCH"; + } + return null; + } + + /** + * @param string $key pattern : file|image,document|2048 + * + * pattern for | : index 0 must be file, index 1 is file type, for the rest current support only maxSize + * + * @example + * + * $request = ['my_file' => $file, 'others' => '1234'] + * new Validator($params)->addRule('my_file', 'file|image,document|2048'); + * + */ + public function file($key, $ruleString, $value, $params) + { + $log = new Log(0); + + if (!($value instanceof UploadedFile)) { + $log->error("ValidatorRuleCollection [file]: file is not file"); + return 'VALIDATOR.FILE.IS_NOT_FILE'; + } + $keys = explode('|', $ruleString); + if (count($keys) == 0) { + throw new Exception("$key validator rules not valid for $$ruleString"); + } + $validatedMime = []; + if (strpos($keys[1], ',') == false) { + if (!in_array($keys[1], ['image', 'document'])) { + $log->error("ValidatorRuleCollection [file]: mime not supported {$keys[1]}"); + return 'VALIDATOR.FILE.MIME'; + } + $validatedMime = [$keys[1]]; + } else { + $exp = explode(',', $keys[1]); + for ($i = 0; $i < count($exp); $i++) { + if (!in_array($exp[$i], ['image', 'document'])) { + $log->error("ValidatorRuleCollection [file]: mime not supported {$exp[$i]}"); + return 'VALIDATOR.FILE.MIME'; + } + } + $validatedMime = $exp; + } + $maxSize = 4096; + if (isset($keys[2]) && is_numeric($keys[2])) { + $maxSize = (int) $maxSize; + } + $sizeInKb = $value->getSize() / 1024; + if ($sizeInKb > $maxSize) { + $log->error("ValidatorRuleCollection [file]: max size {$sizeInKb} higher than allowed $maxSize"); + return "VALIDATOR.FILE.MAX_SIZE"; + } + $mime = $value->getMimeType(); + if (in_array('image', $validatedMime)) { + if (!in_array($mime, $this->allowedMimeType)) { + $log->error("ValidatorRuleCollection [file]: image mime type not allowed $mime"); + return 'VALIDATOR.FILE.IMAGE_INVALID'; + } + } + if (in_array('document', $validatedMime)) { + if (!in_array($mime, $this->allowedMimeType)) { + $log->error("ValidatorRuleCollection [file]: document mime type not allowed $mime"); + return 'VALIDATOR.FILE.DOCUMENT_INVALID'; + } + } + return null; + } + + public function required($key, $ruleString, $value, $params) + { + if (!isset($value) || strlen($value) == 0) return 'VALIDATOR.REQUIRED'; + return null; + } + + public function _getParamValue($key, $params) + { + if (array_key_exists($key, $params)) { + return $params[$key]; + } + return null; + } +} diff --git a/Aiko/Aiko/Libs/ValidatorRuleCollection.php:Zone.Identifier b/Aiko/Aiko/Libs/ValidatorRuleCollection.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/ValidatorRuleCollection.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Aiko/Libs/WhatsApp.php b/Aiko/Aiko/Libs/WhatsApp.php new file mode 100644 index 0000000..268c8c1 --- /dev/null +++ b/Aiko/Aiko/Libs/WhatsApp.php @@ -0,0 +1,570 @@ +init($baseURL); + + + } + + /** + * init component + * + * @param String|null $baseURL + */ + private function init($baseURL = null) + { + $this->sender = $this->registry->config->whatsapp_sender; + $this->client = new Client([ + 'base_uri' => $baseURL ?? $this->registry->config->whatsapp_endpoint, + 'headers' => ['Authorization' => $this->registry->config->whatsapp_api_token, "Accept" => "application/json"], + ]); + } + + public function getTokenAccess(){ + + try{ + $client= new Client(); + $token=''; + if($this->registry->config->wa_token_need_reload){ + $data = array( + 'username'=>$this->registry->config->wa_username, + 'password'=>$this->registry->config->wa_password, + 'grant_type'=>$this->registry->config->wa_grant_type, + 'client_id'=>$this->registry->config->wa_client_id, + 'client_secret'=>$this->registry->config->wa_client_secret, + ); + $response = $client->post($this->registry->config->wa_auth_url, [ + 'headers' => ['Content-Type' => 'application/json', 'Accept' => 'application/json'], + 'body' => json_encode($data) + ]); + $data=json_decode($response->getBody()); + + + $result=$this->_saveTokenAcces($data); + + if(!$result){ + throw new ErrorException('failed save access token to db'); + } + $token=$data->access_token; + }else{ + $stmt=$this->registry->db->prepare('select access_token from wa_qontak_auth where `name`=:name'); + $stmt->bindValue(':name',$this->registry->config->wa_token_name,PDO::PARAM_STR); + $stmt->execute(); + if($stmt->rowCount()==0){ + throw new ErrorException('token access empty'); + } + $rs=$stmt->fetchAll(PDO::FETCH_ASSOC); + $token=$rs[0]['access_token']; + } + + return $token; + }catch(PDOException $e){ + $this->registry->log->error('WhatsApp/getTokenAccess:'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + return false; + }catch(ErrorException $e){ + $this->registry->log->error('WhatsApp/getTokenAccess:'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + return false; + } + + } + + private function _saveTokenAcces($data){ + try{ + // $this->registry->db->beginTransaction(); + $stmtCheck=$this->registry->db->prepare("select id from `wa_qontak_auth` where name=:name"); + $stmtCheck->bindValue(':name',$this->registry->config->wa_token_name,PDO::PARAM_STR); + $stmtCheck->execute(); + if($stmtCheck->rowCount()>0){ + $stmtUpdate=$this->registry->db->prepare('update `wa_qontak_auth` set access_token=:access_token, + token_type=:token_type, + expires_in=:expires_in, + refresh_token=:refresh_token, + created_at=:created_at where `name`=:name'); + $stmtUpdate->bindValue(':access_token',$data->access_token,PDO::PARAM_STR); + $stmtUpdate->bindValue(':token_type',$data->token_type,PDO::PARAM_STR); + $stmtUpdate->bindValue(':expires_in',$data->expires_in,PDO::PARAM_STR); + $stmtUpdate->bindValue(':refresh_token',$data->refresh_token,PDO::PARAM_STR); + $stmtUpdate->bindValue(':created_at',$data->created_at,PDO::PARAM_STR); + $stmtUpdate->bindValue(':name',$this->registry->config->wa_token_name,PDO::PARAM_STR); + $stmtUpdate->execute(); + }else{ + $stmtInsert=$this->registry->db->prepare('insert into `wa_qontak_auth` ( + access_token, + token_type, + expires_in, + refresh_token, + created_at, + name + )values + (:access_token, + :token_type, + :expires_in, + :refresh_token, + :created_at, + :name)'); + $stmtInsert->bindValue(':access_token',$data->access_token,PDO::PARAM_STR); + $stmtInsert->bindValue(':token_type',$data->token_type,PDO::PARAM_STR); + $stmtInsert->bindValue(':expires_in',$data->expires_in,PDO::PARAM_STR); + $stmtInsert->bindValue(':refresh_token',$data->refresh_token,PDO::PARAM_STR); + $stmtInsert->bindValue(':created_at',$data->created_at,PDO::PARAM_STR); + $stmtInsert->bindValue(':name',$this->registry->config->wa_token_name,PDO::PARAM_STR); + $stmtInsert->execute(); + } + // $this->registry->db->commit(); + return true; + + }catch(PDOException $e){ + $this->registry->db->rollBack(); + $this->registry->log->error('WhatsApp/_saveTokenAcces:'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + return false; + }catch(ErrorException $e){ + $this->registry->db->rollBack(); + $this->registry->log->error('WhatsApp/_saveTokenAcces:'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + return false; + } + } + + /** + * set sender + + * @param String $sender phone number + * + * @return Aiko\Whatsapp + * + */ + public function setSender($sender) + { + $this->sender = $sender; + return $this; + } + + /** + * Send message to many recepient + * + * @param Array $payload + * example of param + * [ + * [ + * 'phone' => '081xxx', + * 'message' => 'hi', + * 'link' => 'https://xxxx', + * 'type' => 'image' // default text-only + * ] + * ] + */ + public function sendBulkMessage($payload = []) + { + if (!is_array($payload)) { + $this->registry->log->customError('WhatsApp', "Parameter must be an array"); + return false; + } + + $report = []; + foreach ($payload as $value) { + $send = $this->sendMessage($value['phone'], $value['message'], $value['type'], $value['link']); + array_push($report, $send); + } + + return $report; + } + + public function sendBulkMessageQontak($payload = []) + { + + if (!is_array($payload)) { + $this->registry->log->customError('WhatsApp', "Parameter must be an array"); + return false; + } + + $report = []; + foreach ($payload as $value) { + + $send = $this->sendMessageQontak($value['phone'], $value['name'],$value['parameter'], $value['template']); + array_push($report, $send); + } + + return $report; + } + + public function sendMessage($toNumber, $message, $type = 'text', $link = null) + { + if (!in_array($type, $this->messageType)) { + $this->registry->log->customError('WhatsApp', "Message type not allowed : $type"); + return false; + } + + $endpoint = 'send-message'; + $payload = array( + 'phone' => $toNumber, + 'message' => $message, + 'secret' => false, // or true + 'priority' => false, // or true + ); + switch ($type) { + case 'image': + $endpoint = 'send-image'; + $payload = array( + 'phone' => $toNumber, + 'caption' => $message, + 'image' => $link, + 'secret' => false, // or true + 'priority' => false, // or true + ); + break; + case 'video': + $endpoint = 'send-video'; + $payload = array( + 'phone' => $toNumber, + 'caption' => $message, + 'document' => $link, + 'secret' => false, // or true + 'priority' => false, // or true + ); + break; + case 'document': + $endpoint = 'send-document'; + $payload = array( + 'phone' => $toNumber, + 'document' => $link, + 'secret' => false, // or true + 'priority' => false, // or true + ); + break; + } + + // $request = $this->client->post($endpoint, array('form_params' => $payload)); + // $response = $request->getBody(); + // $contents = json_decode($response->getContents()); + + // if ($contents) { + // $webhook = new Webhook($this->registry); + // if (isset($contents->data)) { + // $data = $contents->data->message; + // foreach ($data as $value) { + // $webhook->create([ + // 'phone' => $value->phone, + // 'status' => $value->status, + // 'note' => $value->text, + // 'id' => $value->id, + // 'deviceId' => $this->registry->config->whatsapp_device_id, + // ]); + // } + // } + // } + + // return $contents; + return true; + } + + public function sendMessageQontak($toNumber, $toName,$parameters, $templateName) + { + // try{ + // // $toNumber='+6282214258200'; + // $tokenAccess=$this->getTokenAccess(); + // $client = new Client(); + // // var_dump($templateName); + // // var_dump($this->_getTemplateId($templateName)); + // // exit(); + // $templateID=$this->_getTemplateId($templateName); + + + // if($templateID===-1){ + // $this->registry->log->error('template tidak active atau belum ada dengan templateName:'.$templateName.', user: '.\Helper::getSessionVar('username')); + // return true; + // } + + // $data=array( + // "to_name"=>$toName, + // "to_number"=>\Helper::formatPhoneNumber($toNumber), + // "message_template_id"=>$templateID, + // "channel_integration_id"=>$this->registry->config->channel_integration_id, + // "language"=> array( + // "code"=> "id" + // ), + // "parameters"=>array( + // "body"=>$parameters + // ) + // ); + + // $client = new Client(); + // $request = $client->request('POST', $this->registry->config->whatsapp_endpoint, [ + // 'headers' => [ + // 'Authorization' => 'Bearer '.$tokenAccess, + // 'Content-Type' => 'application/json', 'Accept' => 'application/json'], + // 'body' => json_encode($data)] + // ); + // $response = $client->send($request); + // dd($response->json()); + + + // $response = $client->post($this->registry->config->whatsapp_endpoint, [ + // 'headers' => [ + // 'Authorization' => 'Bearer '.$tokenAccess, + // 'Content-Type' => 'application/json', 'Accept' => 'application/json'], + // 'body' => json_encode($data) + // ]); + + // var_dump(json_encode($responseData)); + // exit(); + // $responseData=json_decode($response->getBody()); + + // if(property_exists($responseData,'status')){ + // if(!$responseData->status=='success'){ + // throw new ErrorException('Gagal kirim WA'); + // } + // }else{ + // throw new ErrorException('Gagal kirim WA, response undefined'); + // } + // return true; + // }catch(ErrorException $e){ + // $this->registry->log->error('WhatsApp/sendMessageQontak:'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + // return false; + // } + + try { + + $tokenAccess=$this->getTokenAccess(); + $client = new Client(); + $templateID=$this->_getTemplateId($templateName); + + + if($templateID===-1){ + $this->registry->log->error('template tidak active atau belum ada dengan templateName:'.$templateName.', user: '.\Helper::getSessionVar('username')); + return true; + } + + $data=array( + "to_name"=>$toName, + "to_number"=>\Helper::formatPhoneNumber($toNumber), + "message_template_id"=>$templateID, + "channel_integration_id"=>$this->registry->config->channel_integration_id, + "language"=> array( + "code"=> "id" + ), + "parameters"=>array( + "body"=>$parameters + ) + ); + + $request = $client->post($this->registry->config->whatsapp_endpoint, [ + 'headers' => [ + 'Authorization' => 'Bearer '.$tokenAccess, + 'Content-Type' => 'application/json', 'Accept' => 'application/json'], + 'body' => json_encode($data) + ]); + + $this->response = json_decode($request->getBody()->getContents()); + return true; + } catch (\GuzzleHttp\Exception\RequestException $e) { + $this->errors = json_decode($e->getResponse()->getBody()->getContents()); + $this->registry->log->error('WhatsApp/sendMessageQontak:'.$this->errors->error->messages[0].', user: '.\Helper::getSessionVar('username')); + } + + return false; + + } + + private function _getTemplateId($name){ + try{ + $stmt=$this->registry->db->prepare('select id from wa_templates where `name`=:templateName'); + $stmt->bindValue(':templateName',$name,PDO::PARAM_STR); + $stmt->execute(); + if($stmt->rowCount()==0){ + // throw new ErrorException('template id dengan name :'.$name.' kosong'); + //jika template tidak ada return -1 bisa jadi sudah di non activekan + return -1; + } + $rs=$stmt->fetchAll(PDO::FETCH_ASSOC); + return $rs[0]['id']; + }catch(PDOException $e){ + $this->registry->log->error('WhatsApp/_getTemplateId:'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + return false; + }catch(ErrorException $e){ + $this->registry->log->error('WhatsApp/_getTemplateId:'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + return false; + } + } + + public function sendDocumentLocally($toNumber, $filePath, $config) + { + $handle = fopen($filePath, "r"); + $file = fread($handle, filesize($filePath)); + $config['size'] = filesize($filePath); + $endpoint = 'send-document-from-local'; + $payload = array( + 'phone' => $toNumber, + 'file' => base64_encode($file), + 'data' => json_encode($config), + ); + + $request = $this->client->post($endpoint, array('form_params' => $payload)); + $response = $request->getBody(); + $contents = json_decode($response->getContents()); + + return $contents; + } + + /** + * Send message to many recepient in very sumple terms + * + * @param Array $payload + * example of param + * [ + * [ + * 'phone' => '081xxx', + * 'message' => 'hi', + * 'secret' => false, + * 'priority' => false + * ] + * ] + */ + public function simpleBulkMessage($params = []) + { + $endpoint = 'v2/send-bulk/text'; + $request = $this->client->post($endpoint, array('body' => json_encode($params))); + $response = $request->getBody(); + $contents = json_decode($response->getContents()); + + return $contents; + } + public function sendDocument($toNumber, $urlPath, $caption = '') + { + // $endpoint = 'send-document'; + // $payload = array( + // 'phone' => $toNumber, + // 'document' => $urlPath, + // 'caption' => $caption, + // 'isGroup' => false, + // ); + + // $request = $this->client->post($endpoint, array('form_params' => $payload)); + // $response = $request->getBody(); + // $contents = json_decode($response->getContents()); + + // return $contents; + return true; + } + + public function sendDocumentQontak($toNumber, $toName,$parameters, $templateName,$header) + { + try{ + + $tokenAccess=$this->getTokenAccess(); + $client = new Client(); + // var_dump($templateName); + // var_dump($this->_getTemplateId($templateName)); + // exit(); + $data=array( + "to_name"=>$toName, + "to_number"=>\Helper::formatPhoneNumber($toNumber), + "message_template_id"=>$this->_getTemplateId($templateName), + "channel_integration_id"=>$this->registry->config->channel_integration_id, + "language"=> array( + "code"=> "id" + ), + "parameters"=>array( + "header"=> $header, + "body"=>$parameters + ) + ); + $response = $client->post($this->registry->config->whatsapp_endpoint, [ + 'headers' => [ + 'Authorization' => 'Bearer '.$tokenAccess, + 'Content-Type' => 'application/json', 'Accept' => 'application/json'], + 'body' => json_encode($data) + ]); + $responseData=json_decode($response->getBody()); + if(property_exists($responseData,'status')){ + if(!$responseData->status=='success'){ + throw new ErrorException('Gagal kirim WA'); + } + }else{ + throw new ErrorException('Gagal kirim WA, response undefined'); + } + return true; + }catch(ErrorException $e){ + $this->registry->log->error('WhatsApp/sendDocumentQontak:'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + return false; + } + + } + + public function sendMessageQontakTermination($toNumber, $toName,$parameters, $templateName) + { + try { + + $tokenAccess=$this->getTokenAccess(); + $client = new Client(); + $templateID=$this->_getTemplateId($templateName); + + + if($templateID===-1){ + $this->registry->log->error('template tidak active atau belum ada dengan templateName:'.$templateName.', user: '.\Helper::getSessionVar('username')); + return true; + } + + $data=array( + "to_name"=>$toName, + "to_number"=>\Helper::formatPhoneNumber($toNumber), + "message_template_id"=>$templateID, + "channel_integration_id"=>$this->registry->config->channel_integration_id, + "language"=> array( + "code"=> "id" + ), + "parameters"=>array( + "body"=>$parameters + ) + ); + + $request = $client->post($this->registry->config->whatsapp_endpoint, [ + 'headers' => [ + 'Authorization' => 'Bearer '.$tokenAccess, + 'Content-Type' => 'application/json', 'Accept' => 'application/json'], + 'body' => json_encode($data) + ]); + + $this->response = json_decode($request->getBody()->getContents()); + return $this->response; + } catch (\GuzzleHttp\Exception\RequestException $e) { + // $this->registry->log->error('WhatsApp/sendMessageQontak:'.$this->errors->error->messages[0].', user: '.\Helper::getSessionVar('username')); + $this->errors = json_decode($e->getResponse()->getBody()->getContents()); + return $this->errors; + } + + + } +} diff --git a/Aiko/Aiko/Libs/WhatsApp.php:Zone.Identifier b/Aiko/Aiko/Libs/WhatsApp.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Aiko/Libs/WhatsApp.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Framework/Core.php b/Aiko/Framework/Core.php new file mode 100644 index 0000000..5a1de38 --- /dev/null +++ b/Aiko/Framework/Core.php @@ -0,0 +1,831 @@ +vars[$index] = $value; + } + public function __get($index) + { + return $this->vars[$index]; + } +} + +abstract class Controller +{ + protected $registry; + public $ActionAjaxOff; + protected $methodAccess; + protected $apiAction; + protected $apiParams; + protected $apiModule; + protected $publicAction = array(); + private $allowJwt = array(); + protected $appID; + protected $tokenID; + protected $generalActions=array(); + + protected $isFile=false; + + private $allowedMimeType = [ + 'image/jpeg', + 'image/png', + 'image/jpg', + 'video/mp4', + 'application/pdf', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheetapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'text/plain', + 'application/octet-stream', + 'application/zip', + 'application/msword', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'application/vnd.ms-word.document.macroEnabled.12', + 'application/vnd.ms-word.template.macroEnabled.12', + 'application/vnd.ms-excel', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'application/vnd.ms-excel.sheet.macroEnabled.12', + 'application/vnd.ms-excel.template.macroEnabled.12', + 'application/vnd.ms-excel.addin.macroEnabled.12', + 'application/vnd.ms-excel.sheet.binary.macroEnabled.12' + ]; + + public function __construct($registry) + { + // session_id('hcportal-session-id'); + // session_start(); + // Http::enabledCors(); + + $this->registry = $registry; + $this->methodAccess = $_SERVER['REQUEST_METHOD']; + $this->allowJwt = array('dologin', 'dologout', 'refreshToken', 'generateNewToken', 'loginauth'); + + + // connect main DB + // $this->registry = $registry; + // $this->registry->db = Connections::getInstance( + // $this->registry->config->host, + // $this->registry->config->db, + // $this->registry->config->socket, + // $this->registry->config->user, + // $this->registry->config->password, + // $this->registry->config->dbms + // ); + + if($this->registry->config->dbMainConType!=='local') + { + $this->registry->db = Connections::getInstance($this->registry->config->dbMainConType); + }else { + $this->registry->db = Connections::getInstance( + $this->registry->config->dbMainConType, + $this->registry->config->host, + $this->registry->config->socket, + $this->registry->config->user, + $this->registry->config->password + ); + } + + // $handler = new Session($registry); + // $result= session_set_save_handler($handler,true); + + // session_start(); + // session_start(); + + + // if (!interface_exists('SessionHandlerInterface')) { + // exit('ATTENTION: the session handler implemented by Predis requires PHP >= 5.4.0 ' . + // "or a polyfill for SessionHandlerInterface provided by an external package.\n"); + // } + // $single_server=[ + // 'scheme' => 'tcp', + // 'host' => '10.1.200.218', + // 'port' => 6388, + // ]; + // $client = new Client($single_server, ['prefix' => 'sessions:']); + + // // Set `gc_maxlifetime` to specify a time-to-live of 5 seconds for session keys. + // $handler = new Handler($client, ['gc_maxlifetime' => get_cfg_var("session.gc_maxlifetime")]); + + // // Register the session handler. + // $handler->register(); + + // // We just set a fixed session ID only for the sake of our example. + // session_id('hcportalsessionid'); + + if(!isset($_SESSION)) + { + session_start(); + } + // check mime_type + $this->checkContentFile(); + + + } + + abstract public function index(); + + protected function checkToken() + { + try { + $token = Http::getTokenJWT(); + + + // get token ID + $tokenPart = explode('.', $token); + + if (count($tokenPart) != 4) { + throw new \ErrorException('token part invalid'); + } + + $stmt = $this->registry->db->prepare('select appID,tokenID,chipper,data,expired from jwt where id=:id'); + $stmt->bindValue(':id', $tokenPart[3], \PDO::PARAM_INT); + $stmt->execute(); + $rs = $stmt->fetchAll(\PDO::FETCH_ASSOC); + + if (count($rs) == 0) { + throw new \ErrorException('token jwt not exist'); + } + + $this->appID=$rs[0]['appID']; + $this->tokenID=$rs[0]['tokenID']; + + $now = time(); + if ($rs[0]['expired'] < $now) { + throw new \Exception('Time Token refresh Exceded'); + } + + // update expired + $stmt = $this->registry->db->prepare('update jwt set expired=:expired where id=:id'); + $stmt->bindValue(':id', $tokenPart[3], \PDO::PARAM_INT); + $stmt->bindValue(':expired', time() + __LIFETIMEJWT, \PDO::PARAM_INT); + $stmt->execute(); + + $newToken = $tokenPart[0] . '.' . $tokenPart[1] . '.' . $tokenPart[2]; + + $data = Token::decodeJWTNew($newToken, $rs[0]['chipper']); + if (is_numeric($data)) { + if ($data === 8) // expired token + { + $this->registry->log->customError('tokenError', 'Module Controller / check Token : expired token , token :' . $data); + Http::tokenExpired(array('message' => 'Token need refresh')); + } else { + throw new \ErrorException('decode Error token :' . $data); + } + } + $rData = json_decode(json_encode($data->data), true); + \Helper::setSession($rData); + return true; + } catch (\ErrorException $e) { + $this->registry->log->customError('tokenError', 'Module Controller / check Token :' . $e->getMessage()); + Http::UnauthorizedResponseJson(array('message' => 'Wrong Token')); + //return false; + } catch (\Exception $e) { + $this->registry->log->customError('tokenError', 'Module Controller / check Token :' . $e->getMessage()); + Http::UnauthorizedResponseJson(array('message' => $e->getMessage())); + } catch (\PDOException $e) { + $this->registry->log->customError('tokenError', 'Module Controller / check Token :' . $e->getMessage()); + Http::UnauthorizedResponseJson(array('message' => 'query error ')); + } + } + protected function checkTokenOld() + { + try { + $token = Http::getTokenJWT(); + + + + $data = Token::decodeJWTNew($token); + if (is_numeric($data)) { + if ($data === 8) // expired token + { + $this->registry->log->customError('tokenError', 'Module Controller / check Token : expired token , token :' . $data); + Http::tokenExpired(array('message' => 'Wrong Token')); + } else { + throw new \ErrorException('decode Error token :' . $data); + } + } + $rData = json_decode(json_encode($data->data), true); + \Helper::setSession($rData); + return true; + } catch (\ErrorException $e) { + $this->registry->log->customError('tokenError', 'Module Controller / check Token :' . $e->getMessage()); + Http::UnauthorizedResponseJson(array('message' => 'Wrong Token')); + //return false; + } catch (\Exception $e) { + $this->registry->log->customError('tokenError', 'Module Controller / check Token :' . $e->getMessage()); + Http::UnauthorizedResponseJson(array('message' => $e->getMessage())); + } catch (\PDOException $e) { + $this->registry->log->customError('tokenError', 'Module Controller / check Token :' . $e->getMessage()); + Http::UnauthorizedResponseJson(array('message' => 'query error ')); + } + } + + protected function checkRulesAccess() + { + $rule = new Rule($this->registry); + if (!in_array($this->apiAction, $this->publicAction)) { + $hasAccess = $rule->hasAccess($this->apiModule, $this->apiAction); + + if ($hasAccess == false) { + Http::ErrorQueryResponse('operation not permit', 'json'); + } + } + } + + protected function checkAPIAccess() + { + + /* check method access */ + $this->allowOptionMethod(); + + if (!in_array($this->methodAccess, array('POST', 'GET', 'DELETE'))) { + Http::UnauthorizedResponseJson(array('message' => 'Method Not allowed')); + } + $this->apiAction = ''; + switch ($this->methodAccess) { + case 'POST': + /* check and get action */ + $this->apiAction = Http::GetvarData('action'); + if (!isset($this->apiAction)) { + $jtext = Http::GetBodyRequest(); + $this->apiParams = \Firebase\JWT\JWT::jsonDecode($jtext); + if (!isset($this->apiParams->action)) { + Http::UnauthorizedResponseJson(array('message' => 'Action not set')); + } + $this->apiAction = $this->apiParams->action; + } + + break; + + default: + // GET // DELETE + $this->apiAction = Http::GetvarData('action'); + if (strlen($this->apiAction) === 0) { + Http::UnauthorizedResponseJson(array('message' => 'Action not set')); + } + break; + } + + /* check token */ + $isAllowed = $this->checkToken(); + if (!$isAllowed) { + Http::UnauthorizedResponseJson(array('message' => 'Wrong Token')); + } + + /* check rule */ + $this->checkRulesAccess(); + } + + protected function isAuthorized() + { + /* check method access */ + $this->allowOptionMethod(); + + if (!in_array($this->methodAccess, array('POST', 'GET', 'DELETE'))) { + Http::UnauthorizedResponseJson(array('message' => 'Method Not allowed')); + } + $this->apiAction = ''; + + // var_dump($this->methodAccess); + + switch ($this->methodAccess) { + case 'POST': + /* check and get action */ + if($this->isFile){ + $aText['action']=Http::GetVarData('action','post'); + $this->apiParams=\Firebase\JWT\JWT::jsonDecode(\Firebase\JWT\JWT::jsonEncode($aText)); + $this->apiAction = Http::GetVarData('action','post'); + }else{ + $jtext = Http::GetBodyRequest(); + $this->apiParams = \Firebase\JWT\JWT::jsonDecode($jtext); + + if (!isset($this->apiParams->action)) { + Http::UnauthorizedResponseJson(array('message' => 'Action not set')); + } + + $this->apiAction = $this->apiParams->action; + + } + + break; + + default: + // GET // DELETE + $this->apiAction = Http::GetvarData('action'); + $this->apiParams = json_decode(json_encode(Http::getAllRequest())); + if (strlen($this->apiAction) === 0) { + Http::UnauthorizedResponseJson(array('message' => 'Action not set')); + } + break; + } + + if (!in_array($this->apiAction, $this->allowJwt)) { + /* check token */ + $isAllowed = $this->checkToken(); + if (!$isAllowed) { + Http::UnauthorizedResponseJson(array('message' => 'Wrong Token')); + } + } + + + if (is_array($this->generalActions)) { + /* check rule */ + if(!in_array($this->apiAction,$this->generalActions)){ + $this->checkRulesAccess(); + } + } + + + /* process request */ + $this->prosesRequest(); + } + + protected function checkAPIAccessEvaluation() + { + if ($this->methodAccess == 'OPTIONS') { + if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) { + Http::ResponseJson('ok', '0', '1'); + } + } + $isAllowed = $this->checkTokenEvaluation(); + if (!$isAllowed) { + Http::UnauthorizedResponseJson(array('message' => 'Wrong Token')); + } + } + + protected function checkTokenEvaluation() + { + try { + + $token = Http::getTokenJWT(); + $data = Token::decodeJWT($token); + if (!isset($data->data)) { + throw new \ErrorException('decode Error token :' . $token); + } + + $_SESSION = array(); + session_destroy(); + + $_SESSION['group'] = $data->data->group; + $_SESSION['username'] = $data->data->username; + $_SESSION['name'] = isset($data->data->name) ? $data->data->name : $data->data->nama; + $_SESSION['section'] = isset($data->data->section) ? $data->data->section : $data->data->secion; + $_SESSION['userID'] = $data->data->userID; + $_SESSION['empNo'] = isset($data->data->empNo) ? $data->data->empNo : ''; + $_SESSION['empSite'] = $data->data->empSite; + $_SESSION['empSubArea'] = isset($data->data->empSubArea) ? $data->data->empSubArea : ''; + $_SESSION['flagApp'] = isset($data->data->flagApp) ? $data->data->flagApp : ''; + $_SESSION['nationality'] = isset($data->data->nationality) ? $data->data->nationality : ''; + $_SESSION['role'] = isset($data->data->role) ? $data->data->role : ''; + + // if jwt valid set session var + + return true; + } catch (\ErrorException $e) { + $this->registry->log->error('Module Controller / check Token Eval :' . $e->getMessage()); + return false; + } + } + + protected function allowOptionMethod() + { + if ($this->methodAccess == 'OPTIONS') { + if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) { + Http::ResponseJson(array('ok'), '0', '1'); + } + } + } + + private function prosesRequest() + { + switch ($this->methodAccess) { + case 'POST': + $this->executePost(); + break; + case 'GET': + $this->executeGet(); + break; + case 'DELETE': + $this->executeDelete(); + break; + default: + Http::ErrorQueryResponse('method not permit'); + break; + } + } + protected function executePost() + { + $act = $this->apiAction; + if (method_exists($this, $act)) { + $this->$act(); + } else { + Http::ErrorQueryResponse('Action not registered'); + } + } + private function executeGet() + { + $act = $this->apiAction; + if (method_exists($this, $act)) { + $this->$act(); + } else { + Http::ErrorQueryResponse('Action not registered'); + } + } + protected function executeDelete() + { + } + + protected function extendAllowJwt(array $extended) + { + foreach ($extended as $value) { + array_push($this->allowJwt, $value); + } + } + + + + /** + * fungsi ini untuk convert message dari api. + * untuk keperluan migrasi FE ke framework yang baru + * karena fokus utama migrasi FE dulu jadi BE yang menyesuaikan + * + * @param message + * @return $result : string + */ + protected function convertMessages($message) + { + $result = $message; + switch($message){ + case 'PAYROLL.MESSAGE.SUCCMESINS': + $result = 'MESSAGE.SUCCMESINS'; + break; + case 'PAYROLL.MESSAGE.FAILMESEXIST': + $result = 'MESSAGE.DATA_ALREADY_EXIST'; + break; + case 'PAYROLL.MESSAGE.FAILMESUNKNOWN': + $result = 'MESSAGE.FAILMESUNKNOWN'; + break; + case 'PAYROLL.MESSAGE.FAILMESERRREQ': + $result = 'MESSAGE.FAILMESERRREQ'; + break; + case 'PAYROLL.MESSAGE.SUCCMESDEL': + $result = 'MESSAGE.SUCCMESDEL'; + break; + case 'PAYROLL.MESSAGE.SUCCMESUPD': + $result = 'MESSAGE.SUCCMESUPD'; + break; + case 'PAYROLL.MESSAGE.FAILMESQUERY': + $result = 'MESSAGE.FAILMESQUERY'; + break; + case 'MENU.MASTER_DATA.ADMINISTRATIVE_AREA.MAIN.CANTDELETE': + $result = 'MESSAGE.CANTDELETE'; + break; + } + + return $result; + } + + /** + * fungsi ini untuk convert response menjadi format pagination. + * untuk keperluan migrasi FE ke framework yang baru + * karena fokus utama migrasi FE dulu jadi BE yang menyesuaikan + * + * @param array + * @return array + */ + protected function convertToPaginationFormat($array) + { + $total = count($array); + $aData['iTotalDisplayRecords'] = $total; + $aData['iTotalRecords'] = $total; + $aData['aData'] = $array; + + return $aData; + } + + private function checkContentFile(){ + $this->isFile=Http::isMultipartFormData(); + if($this->isFile){ + if (!empty($_FILES) && is_array($_FILES) && count($_FILES) > 0) { + foreach ($_FILES as $file) { + $filepath = $file['tmp_name']; + // $filesize = filesize($filepath); + $fileinfo = finfo_open(FILEINFO_MIME_TYPE); + $filetype = finfo_file($fileinfo, $filepath); + finfo_close($fileinfo); + if (!in_array($filetype, $this->allowedMimeType)) { + Http::ErrorQueryResponse(array('name' => $file['name'], 'message' =>'15220-failed'), 'json'); + } + } + } + } + } + + protected function setSession($token) + { + // get token ID + $tokenPart = explode('.', $token); + \Helper::dump($tokenPart); + if (count($tokenPart) != 4) { + throw new \ErrorException('token part invalid'); + } + + $stmt = $this->registry->db->prepare('select appID,tokenID,chipper,data,expired from jwt where id=:id'); + $stmt->bindValue(':id', $tokenPart[3], \PDO::PARAM_INT); + $stmt->execute(); + $rs = $stmt->fetchAll(\PDO::FETCH_ASSOC); + + if (count($rs) == 0) { + throw new \ErrorException('token jwt not exist'); + } + + $this->appID=$rs[0]['appID']; + $this->tokenID=$rs[0]['tokenID']; + + $now = time(); + if ($rs[0]['expired'] < $now) { + throw new \Exception('Time Token refresh Exceded'); + } + + // update expired + $stmt = $this->registry->db->prepare('update jwt set expired=:expired where id=:id'); + $stmt->bindValue(':id', $tokenPart[3], \PDO::PARAM_INT); + $stmt->bindValue(':expired', time() + __LIFETIMEJWT, \PDO::PARAM_INT); + $stmt->execute(); + + $newToken = $tokenPart[0] . '.' . $tokenPart[1] . '.' . $tokenPart[2]; + + $data = Token::decodeJWTNew($newToken, $rs[0]['chipper']); + if (is_numeric($data)) { + if ($data === 8) // expired token + { + $this->registry->log->customError('tokenError', 'Module Controller / check Token : expired token , token :' . $data); + Http::tokenExpired(array('message' => 'Token need refresh')); + } else { + throw new \ErrorException('decode Error token :' . $data); + } + } + $rData = json_decode(json_encode($data->data), true); + \Helper::setSession($rData); + } +} + +class Router +{ + private $registry; + private $path; + private $args = array(); + public $file; + public $controller; + public $action; + public $parts; + private $controllerPath; + + private $prefix; + public function __construct($registry,$prefix='') + { + $this->registry = $registry; + $this->prefix=$prefix; + } + + public function loader() + { + + try { + /*** a new controller class instance , pembuatan controller object***/ + $class = $this->controller; + $this->registry->controller = $class; + $this->registry->action = $this->action; + $ClassName = ucfirst($class); + $mod = strtolower($class); + + $aModules = explode('/', $this->controllerPath); + $jumModules = count($aModules); + //$mod1 = substr($this->controllerPath, 1); + $mod1 = $this->controllerPath; + $strslash = substr($this->controllerPath, 0, 1); + if ($strslash == '/' || $strslash == '\\') { + $mod1 = substr($this->controllerPath, 1); + } + + $newmod = str_replace('/', '\\', $mod1); + + $namespaces = "\\modules\\{$newmod}\\controller\\{$ClassName}Controller"; + + $this->registry->ContPath = $mod1; + + $controller = new $namespaces($this->registry); + + /*** check if the action is callable ***/ + if (is_callable(array($controller, $this->action)) == false) { + + $action = 'index'; + } else { + $action = $this->action; + } + + /*** run the action , ini sama kayak execute function yang ada pada controller pada mvc sebelumnya + * ***/ + if ($this->registry->config->ajax == 'on') { + if (!empty($controller->ActionAjaxOff)) { + if (!in_array($action, $controller->ActionAjaxOff)) { + // if true + + if (!$this->registry->isAjax) { + exit('ajax request required'); + } + } + } else { + if (!$this->registry->isAjax) { + exit('ajax request required'); + } + } + } else { + if ($this->registry->isAjax) { + exit('please set ajax config to "on" if request ajax required'); + } + } + $controller->$action(); + } catch (\Exception $e) { + $this->registry->log->error('Core / Loader :' . $e->getMessage() . ' Line :' . $e->getLine() . ' ' . $e->getFile()); + Http::InternalServerError('error loader'); + } + } + + private function getController() + { + + try { + /* get variable*/ + $this->controller = $this->getControllerName(); + $j = 0; + if (!(empty($this->parts[2]) or $this->parts[2] == '-')) { + for ($i = 2; $i < count($this->parts); $i++) { + $this->args[$j] = $this->parts[$i]; + $j++; + } + $this->registry->vars = $this->args; + } else { + $this->registry->vars = 'null'; + } + + /*** set the file path ***/ + return $this->controller; + } catch (\Exception $e) { + + $this->registry->log->error('Core / Loader :' . $e->getMessage() . ' Line :' . $e->getLine() . ' ' . $e->getFile()); + \Aiko\Http::InternalServerError('Error loader'); + } + } + public function getControllerName() + { + + try { + $restrict = ''; + if ($this->registry->config->restrict == 'yes') { + if (isset($this->registry->config->ipconfig)) { + $ip = $this->getRealIpAddr(); + $register = in_array($ip, $this->registry->config->ipconfig); + + if ($ip != '127.0.0.1') { + if (!$register) { + $restrict = 'restrict'; + } + } + } else { + $restrict = 'restrict'; + } + } + $this->getName($restrict); + $this->Request_check(); + + return $this->controller; + } catch (\Exception $e) { + + $this->registry->log->error('Core / Loader :' . $e->getMessage() . ' Line :' . $e->getLine()); + \Aiko\Http::InternalServerError('Error loader'); + } + } + + private function getName($restrict) + { + try { + if ($restrict == 'restrict') { + $this->controller = 'restrict'; + $this->controllerPath = 'restrict'; + } else { + $route = (empty($_GET['rt'])) ? '' : $_GET['rt']; + if (empty($route)) { + // jika route tidak ada / pada awal page + $route = 'index'; + } else { + // clean root with prefix + $route= $this->cleanRoute($route); + /*** get the parts of the route ***/ + $this->parts = explode('/', $route); + // set controller name + // cek apakan part yang pertama memiliki controller kalau tidak ditemukan return 404 + if (!is_dir(__SITE_PATH . '/src/modules/' . $this->parts[0])) { + $this->controller = 'error404'; + $this->controllerPath = 'error404'; + } else { + $i = 0; + $path = ''; + $found = false; + do { + $path .= '/' . $this->parts[$i]; + $dir = __SITE_PATH . '/src/modules' . $path; + if (file_exists($dir . '/controller')) { + $found = true; + break; + } + $i++; + } while ($i < count($this->parts)); + if ($found) { + $this->controller = $this->parts[$i]; + $this->controllerPath = $path; + } else { + $this->controller = 'error404'; + $this->controllerPath = 'error404'; + } + + if (isset($this->parts[$i + 1])) { + // set action name + $this->action = $this->parts[$i + 1]; + } + } + } + // cek apakah controller kosong, jika kosong set ke index + if (empty($this->controller)) { + $this->controller = 'index'; + $this->controllerPath = 'index'; + } + + /*** Get action ***/ + if (empty($this->action)) { + $this->action = 'index'; + } + } + } catch (\Exception $e) { + + $this->registry->log->error('Core / Loader :' . $e->getMessage() . ' Line :' . $e->getLine()); + \Aiko\Http::InternalServerError('Error loader'); + } + } + private function Request_check() + { + $this->registry->isAjax = isset($_SERVER['HTTP_X_REQUESTED_WITH']) and + strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'; + } + public function getControllerPath() + { + return $this->controllerPath; + } + private function getRealIpAddr() + { + if (!empty($_SERVER['HTTP_CLIENT_IP'])) { //check ip from share internet + $ip = $_SERVER['HTTP_CLIENT_IP']; + } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { //to check ip is pass from proxy + $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; + } else { + $ip = $_SERVER['REMOTE_ADDR']; + } + return $ip; + } + + private function cleanRoute($route):string{ + $prefixLength=strlen($this->prefix); + if ($prefixLength==0){ + return $route; + } + $routePrefix=substr($route,0,$prefixLength); + if($this->prefix!==$routePrefix){ + + Http::InternalServerError('failed route'); + } + $newRoute= substr($route,$prefixLength); + if(strlen($newRoute)==0 || $newRoute=='/'){ + $newRoute='index'; + } + + // check apakah string pertama route / ? + if(substr($newRoute,0,1)=='/'){ + $newRoute=substr($newRoute,1); + } + return $newRoute; + } + +} diff --git a/Aiko/Framework/Core.php:Zone.Identifier b/Aiko/Framework/Core.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Framework/Core.php:Zone.Identifier:Zone.Identifier b/Aiko/Framework/Core.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Framework/Core.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Framework/Database.php b/Aiko/Framework/Database.php new file mode 100644 index 0000000..b35e760 --- /dev/null +++ b/Aiko/Framework/Database.php @@ -0,0 +1,184 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + self::$instance->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL); + // self::$instance->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); + + return self::$instance; + } catch (PDOException $e) { + self::showerror("Sorry, an error has occured. Please try your request \n" . $e->getMessage()); + die(); + } + } else { + return self::$instance; + } + + } + + public static function getInstancePMA() { + $config = getConfig('pma'); + $host = $config['host']; + $db = $config['db']; + $socket = $config['socket']; + $user = $config['user']; + $pass = $config['password']; + if (!self::$instancePMA) + { + try + { + self::$instancePMA = new PDO("mysql:host=$host;dbname=$db;unix_socket=$socket;", "$user","$pass"); + self::$instancePMA-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + self::$instancePMA->setAttribute(PDO::ATTR_CASE,PDO::CASE_NATURAL); + return self::$instancePMA; + }catch (PDOException $e) + { + self::showerror("Sorry, an error has occured. Please try your request \n".$e->getMessage()); + die(); + } + }else + { + return self::$instancePMA; + } + + } + + public static function getInstanceCartal($type) { + $config = getConfig($type); + $host = $config['host']; + $db = $config['db']; + $socket = $config['socket']; + $user = $config['user']; + $pass = $config['password']; + if (!self::$instanceCartal) + { + try + { + self::$instanceCartal = new PDO("mysql:host=$host;dbname=$db;unix_socket=$socket;", "$user","$pass"); + self::$instanceCartal-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + self::$instanceCartal->setAttribute(PDO::ATTR_CASE,PDO::CASE_NATURAL); + return self::$instanceCartal; + }catch (PDOException $e) + { + self::showerror("Sorry, an error has occured. Please try your request \n".$e->getMessage()); + die(); + } + }else + { + return self::$instanceCartal; + } + + } + + public static function getInstanceSCADA($type) { + $config = getConfig($type); + $host = $config['host']; + $db = $config['db']; + $user = $config['user']; + $pass = $config['password']; + $port = $config['port']; + if (!self::$scada) + { + try + { + self::$scada = new PDO("pgsql:host=$host;port=$port;dbname=$db;", "$user", "$pass"); + self::$scada-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + self::$scada->setAttribute(PDO::ATTR_CASE,PDO::CASE_NATURAL); + return self::$scada; + }catch (PDOException $e) + { + self::showerror("Sorry, an error has occured. Please try your request \n".$e->getMessage()); + die(); + } + }else + { + return self::$instanceCartal; + } + + } + + public static function exceptionHandler($e) + { + set_exception_handler('exceptionHandler'); + self::showerror("Sorry, the site under maintenance \n"); + } + public static function showerror($m) + { + echo "

Error

"; + echo nl2br(htmlspecialchars($m)); + } +/** + * + * + * Like the constructor, we make __clone private + * so nobody can clone the instance + * + */ + private function __clone() + {} + +} diff --git a/Aiko/Framework/Database.php:Zone.Identifier b/Aiko/Framework/Database.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Framework/Database.php:Zone.Identifier:Zone.Identifier b/Aiko/Framework/Database.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Framework/Database.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Framework/Error.php b/Aiko/Framework/Error.php new file mode 100644 index 0000000..76510c1 --- /dev/null +++ b/Aiko/Framework/Error.php @@ -0,0 +1,11 @@ +config = json_decode(json_encode($config)); + +//$registry->config = json_decode(json_encode(parse_ini_file(__SITE_PATH . '/includes/' . 'config.ini'))); + + +// var_dump($registry->config); + +/* + * set server address dari file config + */ +define('__SERVERADDR', $registry->config->server_address); + +/* + * set time zone area application + */ +date_default_timezone_set($registry->config->time_zone); + +/* + Create object registry for carry object + */ + +$registry->router = new Aiko\Router($registry); + +/* + Set Controller Name + */ + +$registry->controller = $registry->router->getControllerName(); + +/* + Create object template + */ + +$registry->template = new \Aiko\Template\Template($registry); + +/* + Set Debugging + */ +/*set Aiko Debugging on developer mode*/ + +$registry->ab = new \Aiko\Debug($registry->config->environment); + +/* set log aplikasi */ +$registry->log = new \Aiko\Log($registry->config->log); + + +//$this->registry = $registry; +//$sessionHandler = new \Aiko\Session($registry); +// session_set_save_handler($sessionHandler, true); +// session_set_save_handler( +// array($sessionHandler, 'open'), +// array($sessionHandler, 'close'), +// array($sessionHandler, 'read'), +// array($sessionHandler, 'write'), +// array($sessionHandler, 'destroy'), +// array($sessionHandler, 'gc') +// ); +// the following prevents unexpected effects when using objects as save handlers +// register_shutdown_function('session_write_close'); + +// session_start(); +// proceed to set and retrieve values by key from $_SESSION + +/* turn of dompdf autoload because we use composer */ +define('DOMPDF_ENABLE_AUTOLOAD', false); + +// require_once __SITE_PATH.'/vendor/dompdf/dompdf/dompdf_config.inc.php'; + +/* + Run Controller + */ + +$registry->router->loader(); diff --git a/Aiko/Framework/Init.php:Zone.Identifier b/Aiko/Framework/Init.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Framework/Init.php:Zone.Identifier:Zone.Identifier b/Aiko/Framework/Init.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Framework/Init.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Framework/Model.php b/Aiko/Framework/Model.php new file mode 100644 index 0000000..e63614c --- /dev/null +++ b/Aiko/Framework/Model.php @@ -0,0 +1,235 @@ +registry = $registry; + /* if($this->registry->config->dbMainConType!=='local') + { + $this->registry->db = Connections::getInstance($this->registry->config->dbMainConType); + }else { + $this->registry->db = Connections::getInstance( + $this->registry->config->dbMainConType, + $this->registry->config->host, + $this->registry->config->socket, + $this->registry->config->user, + $this->registry->config->password + ); + } */ + + + } + + public function ConnectToOracle() + { + try { + $host = $this->registry->config->hostOracle; + $db = $this->registry->config->dbOracle; + $user = $this->registry->config->userOracle; + $pass = $this->registry->config->passwordOracle; + // die($user.$pass); + $this->registry->dbOracle = new PDO("oci:dbname=//$host:1521/$db;", "$user", "$pass", array( + PDO::ATTR_TIMEOUT => 10, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + )); + $this->registry->dbOracle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $this->registry->dbOracle->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL); + + } catch (\PDOException $e) { + die("Sorry, an error has occured. Please try your request \n"); + } + + } + + public function connectToDBPMA() + { + $this->registry->dbpma = Connections::getInstancePMA(); + } + + protected function beginTransaction() + { + $this->registry->db->beginTransaction(); + } + protected function commit() + { + $this->registry->db->commit(); + } + protected function rollBack() + { + $this->registry->db->rollBack(); + } + + protected function sendResponse($moreInfo, $messages, $status) + { + return array( + "moreInfo" => $moreInfo, + "messages" => $messages, + "status" => $status, + ); + } + + public function connectToCarTal() + { + return Connections::getInstanceCartal($this->registry->config->dbCarTalType); + } + + public function connectToScada() + { + return Connections::getInstanceSCADA($this->registry->config->dbScadaType); + } + + protected function checkValidNikByEmpId($empId,$nik){ + try{ + $stmt=$this->registry->db->prepare('select nik from employement where nik=:nik and emp_profile_id=:emp_id'); + $stmt->bindValue(':nik',$nik,PDO::PARAM_STR); + $stmt->bindValue(':emp_id',$empId,PDO::PARAM_INT); + $stmt->execute(); + if($stmt->rowCount()>0){ + + return true; + } + return false; + }catch(\PDOException $e){ + return false; + }catch(\ErrorException $e){ + return false; + } + } + + private function serializeColumn($arr = [], $isBinding = false) + { + $serialize = ''; + for ($i = 0; $i < count($arr); $i++) { + if ($isBinding) { + $serialize .= ":$arr[$i],"; + } else { + if (is_numeric($arr[$i])) { + $serialize .= "$arr[$i],"; + } else { + $serialize .= "'$arr[$i]',"; + } + } + } + + return substr($serialize, 0, -1); + } + + public function prepareQuery($query) + { + if (isset($this->preparedStatements[$query])) { + $stmt = $this->preparedStatements[$query]; + } else { + // Call PDO::prepare. + $stmt = $this->registry->db->prepare($query); + $this->preparedStatements[$query] = $stmt; + } + return $stmt; + } + + private function checkDebugMode($stmt) + { + if ($this->enabledDebugMode) { + $stmt->debugDumpParams(); + die(); + } + } + + protected function error($e, $name="") + { + if(!empty($name)){ + $this->registry->log->customError($name, 'Message: '. $e->getMessage() . ' | Line: '. $e->getLine(). ' | File: '. $e->getFile()) . ' | User: ' . \Helper::getSessionVar('username'); + }else{ + $this->registry->log->error('Message: '. $e->getMessage() . ' | Line: '. $e->getLine(). ' | File: '. $e->getFile() . ' | User: ' . \Helper::getSessionVar('username')); + } + } + + protected function getColumnIndex($col) + { + $idx = \PHPExcel_Cell::columnIndexFromString($col); + return $idx - 1; + } + + protected function getWorkSheetData($fileName, $sheetIndex) + { + $objPHPExcel = new PHPExcel(); + $inputFileType = \PHPExcel_IOFactory::identify($fileName); + $objReader = \PHPExcel_IOFactory::createReader($inputFileType); + + $objPHPExcel = $objReader->load($fileName); + $objWorkSheet = $objPHPExcel->setActiveSheetIndex($sheetIndex); + + return $objWorkSheet; + } + + /** + * $type allowed + * - time untuk jam + * - date untuk tanggal + */ + protected function getColumnValue($objWorkSheet, $columnIndex, $row, $type='') + { + $result = $objWorkSheet->getCellByColumnAndRow($this->getColumnIndex($columnIndex), $row)->getValue(); + if(!empty($type)){ + $format = 'YYYY-MM-DD'; + $defValue = "1970-01-01"; + if($type=='time'){ + $defValue = "00:00:00"; + $format = 'hh:mm:ss'; + } + if(empty($result)){ + return $defValue; + } + return \PHPExcel_Style_NumberFormat::toFormattedString(trim($result), $format); + } + + return trim($result); + } + + protected function saveFileData($file, $path, $allowedMime = []) + { + $filename = $file->getClientOriginalName(); + $mimeType = $file->getClientMimeType(); + $mimeClientAlowed = array('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-excel'); + if(count($allowedMime)>0){ + $mimeClientAlowed = $allowedMime; + } + if (!in_array($mimeType, $mimeClientAlowed)) { + throw new Exception('error file type'); + } + $targetPath = $this->registry->config->base_storage. $path; + $targetFile = str_replace('//', '/', $targetPath); + $newfilename = $targetFile . '_' . time() . '_' . $filename; + // store data to storage + $file->move($targetFile, $newfilename); + + return array('filename' => $filename, 'newfilename' => $newfilename); + } + + protected function isEmpty($param) + { + if(is_null($param) || empty($param) || !$param){ + return true; + } + + return false; + } +} + diff --git a/Aiko/Framework/Model.php:Zone.Identifier b/Aiko/Framework/Model.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Framework/Model.php:Zone.Identifier:Zone.Identifier b/Aiko/Framework/Model.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Framework/Model.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Framework/Template.php b/Aiko/Framework/Template.php new file mode 100644 index 0000000..10e5838 --- /dev/null +++ b/Aiko/Framework/Template.php @@ -0,0 +1,107 @@ +registry = $registry; // set registry object + +} + + + public function __set($index, $value) // magic method yang berfungsi untuk set variable untuk template saja + { + $this->vars[$index] = $value; + } + +// ini method yang berfungsi untuk menampilkan view +function show($name,$listJS= array(),$listCSS= array()) { + // variable path berfungsi menyimpan path file view + $path = __SITE_PATH .'/src/modules/'.$this->registry->ContPath. '/views' . '/' . $name . '.php'; + $pathJS= __SITE_PATH .'/src/modules/'.$this->registry->ContPath. '/js' . '/' . $name . '.js'; + $srcjs= __SERVERADDR.'/src/modules'.$this->registry->ContPath. '/js' . '/' . $name . '.js'; + $pathCSS= __SITE_PATH .'/src/modules/'.$this->registry->ContPath. '/css' . '/' . $name . '.css'; + $srccss= __SERVERADDR.'/src/modules'.$this->registry->ContPath. '/css' . '/' . $name . '.css'; + if (file_exists($path) == false) + { + throw new \Exception('Template not found in '. $path); + return false; + } + + + // Load variables, jadikan index array sebagai variable pada php + foreach ($this->vars as $key => $value) + { + //set variable php + $$key = $value; + } + + if(sizeof($listCSS)>0) + { + foreach ($listCSS as $val) { + echo ""; + } + + } + + // include file + if (file_exists($pathCSS) == true) + { + echo ""; + } + include ($path); // load view + if (file_exists($pathJS) == true) + { + echo ""; + } + if(sizeof($listJS)>0) + { + foreach ($listJS as $val) { + echo ""; + } + + } +} + +/** + * method ini digunakan untuk menampilkan data dalam PDF + * require dompdf + */ +public function getContentFile($name) +{ + $path = __SITE_PATH .'/src/modules/'.$this->registry->ContPath. '/pdf' . '/' . $name . '.php'; + + if (file_exists($path) == false) + { + throw new \Exception('Template not found in '. $path); + return false; + } + + // Load variables, jadikan index array sebagai variable pada php + foreach ($this->vars as $key => $value) + { + //set variable php + $$key = $value; + } + + $obstart=ob_start(); + if ($obstart == false) + { + throw new \Exception('output bueffering not start '); + return false; + } + + include ($path); // load view + $out = ob_get_clean(); + return $out; +} + +} + +?> diff --git a/Aiko/Framework/Template.php:Zone.Identifier b/Aiko/Framework/Template.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Framework/Template.php:Zone.Identifier:Zone.Identifier b/Aiko/Framework/Template.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Framework/Template.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Framework/Token.php b/Aiko/Framework/Token.php new file mode 100644 index 0000000..97e20dc --- /dev/null +++ b/Aiko/Framework/Token.php @@ -0,0 +1,351 @@ +get_token_from_session('token'); + // var_dump($sessiontoken); + // exit(); + + + $valid = strlen($sessiontoken) == 128 && strlen($token) == 128 && $sessiontoken == $token; + + $this->get_token($area); // refresh token + + return $valid; + } + public function get_token_from_url() + { + $token = isset($_GET['token']) ? $_GET['token'] : ''; + + return $token; + } + + public function get_token_from_session($key) + { + $token = isset($_SESSION[$key]) ? $_SESSION[$key] : ''; + + return $token; + } + public function getTokenAuthUser() + { + $token = hash('sha512', mt_rand(0, mt_getrandmax()) . microtime(true)); + $_SESSION['tokenAuth'] = $token; + + return $token; + } + public function check_tokenAuthUser($token) + { + $sessiontoken = $this->get_token_from_session('tokenAuth'); + $valid = strlen($sessiontoken) == 128 && strlen($token) == 128 && $sessiontoken == $token; + if ($valid) { + return true; + } else { + return false; + } + } + + public function set_cookie() + { + $result = password_hash('4pl1k4s1D1sd1K', PASSWORD_DEFAULT, array('cost' => 10)); + // $res = setcookie('XSRF-TOKEN', $result, time() + 86400, $_SERVER['REQUEST_URI'],'',false,false); + + $res = setcookie('XSRF-TOKEN', $result, time() + 86400, '/'); + if ($res) { + return true; + } else { + return false; + } + } + public function cek_cookie($clientCookie) + { + $result = false; + if (isset($_COOKIE['XSRF-TOKEN'])) { + $serverCookie = $_COOKIE['XSRF-TOKEN']; + $result = $this->cek_hash($clientCookie, $serverCookie); + } + + return $result; + } + + private function cek_hash($clientCookie, $serverCookie) + { + if ($clientCookie == $serverCookie) { + return $this->set_cookie(); + } else { + return false; + } + } + + private static function wrapToken($jwt, $chipper) + { + try { + if (strlen($chipper) <> 6) { + throw new \ErrorException('chipper failed'); + } + $headerPreffix = (int) substr($chipper, 0, 1); + $headerSuffix = (int) substr($chipper, 1, 1); + $payloadPreffix = (int) substr($chipper, 2, 1); + $payloadSuffix = (int) substr($chipper, 3, 1); + $signPreffix = (int) substr($chipper, 4, 1); + $signSuffix = (int) substr($chipper, 5, 1); + + $jwtPart = explode('.', $jwt); + + $newJwt = self::randomChars($headerPreffix) . $jwtPart[0] . self::randomChars($headerSuffix); + + $newJwt .= '.' . self::randomChars($payloadPreffix) . $jwtPart[1] . self::randomChars($payloadSuffix); + + $newJwt .= '.' . self::randomChars($signPreffix) . $jwtPart[2] . self::randomChars($signSuffix); + + return $newJwt; + } catch (\Exception $e) { + return false; + } + } + + private static function unWrapToken($jwt, $chipper) + { + try { + if (strlen($chipper) <> 6) { + throw new \ErrorException('chipper failed'); + } + + $headerPreffix = (int) substr($chipper, 0, 1); + $headerSuffix = (int) substr($chipper, 1, 1); + $payloadPreffix = (int) substr($chipper, 2, 1); + $payloadSuffix = (int) substr($chipper, 3, 1); + $signPreffix = (int) substr($chipper, 4, 1); + $signSuffix = (int) substr($chipper, 5, 1); + + $jwtPart = explode('.', $jwt); + + + $newString = self::removePreSuf($jwtPart[0], $headerPreffix, $headerSuffix); + if ($newString == false) { + throw new \ErrorException('failed clean wrapper header'); + } + $header = $newString; + + $newString = self::removePreSuf($jwtPart[1], $payloadPreffix, $payloadSuffix); + if ($newString == false) { + throw new \ErrorException('failed clean wrapper payload'); + } + $payload = $newString; + + $newString = self::removePreSuf($jwtPart[2], $signPreffix, $signSuffix); + if ($newString == false) { + throw new \ErrorException('failed clean wrapper sign'); + } + $sign = $newString; + + return $header . '.' . $payload . '.' . $sign; + } catch (\ErrorException $e) { + return false; + } + } + + private static function removePreSuf($string, $preffix, $suffix) + { + $jum = strlen(trim($string)); + $totWrapper = ($preffix + $suffix); + $tot = $totWrapper + 10; // set minimum text + if ($jum > $tot) { + $total = $jum - $totWrapper; + $newString = substr($string, $preffix, $total); + return $newString; + } + + return false; + } + + private static function randomChars($numChars) + { + $str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuzwxyz'; + return substr(str_shuffle($str), 0, $numChars); + } + + public static function encodeJWT($serverName, $dataUser, $chipper = '000000') + { + + try { + + $log = new Log('1'); + // $publicKey = file_get_contents('/Users/suhendra/mykey/suhendra_rsa.pub'); + + $privateKey = file_get_contents(__SITE_PATH . '/mykey/hcportalprivate.pem'); + + // $privateKey = openssl_get_privatekey('file:///Users/suhendra/mykey/suhendra_rsa','suh3ndr4'); + // var_dump($privateKey); + + //$tokenId = base64_encode(\mcrypt_create_iv(32)); + $tokenId = base64_encode(\openssl_random_pseudo_bytes(64)); + // $random = mt_rand(0, 999999); + // $random_string = sha1($random); + //$tokenId = base64_encode(date('Y-m-d H:i:s')); + $issuedAt = time(); + $notBefore = time(); + $expire = $notBefore + __EXPIREDJWT; // Adding 10 menit + $expireReused = $notBefore + __LIFETIMEJWT; // Adding 2hari + + /* + * Create the token as an array + */ + $data = [ + 'iat' => $issuedAt, // Issued at: time when the token was generated + 'jti' => $tokenId, // Json Token Id: an unique identifier for the token / A unique string, could be used to validate a token, but goes against not having a centralized issuer authority. + 'iss' => $serverName, // A string containing the name or identifier of the issuer application. Can be a domain name and can be used to discard tokens from other applications. + 'nbf' => $notBefore, // Timestamp of when the token should start being considered valid. Should be equal to or greater than iat. In this case, the token will begin to be valid 10 seconds + 'exp' => $expire, // Timestamp of when the token should cease to be valid. Should be greater than iat and nbf. In this case, the token will expire 60 seconds after being issued. + 'data' => $dataUser, + ]; + + $jwt = JWT::encode( + $data, //Data to be encoded in the JWT + $privateKey, // The signing key + 'RS256' // Algorithm used to sign the token, see https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40#section-3 + ); + + // var_dump($jwt); + + $newJwt = self::wrapToken($jwt, $chipper); + // var_dump($newJwt); + + if ($newJwt == false) { + throw new \ErrorException('Failed wrap Token'); + } + + $dataUser['expired'] = $expire; + $dataHeader = array( + 'jwt' => $newJwt, + 'tokenID' => $tokenId, + 'appID' => $serverName, + 'data' => $dataUser, + 'expired' => $expireReused + ); + + return $dataHeader; + } catch (\ErrorException $e) { + $log->error('encode token token/decodeJWT' . $e->getMessage()); + return false; + } + } + + public static function decodeJWT($jwt, $chipper = '000000') + { + try { + $log = new Log('1'); + + $publicKey = file_get_contents(__SITE_PATH . '/mykey/hcportalpublic.pem'); + + $newJwt = self::unWrapToken($jwt, $chipper); + + $token = JWT::decode($newJwt, $publicKey, array('RS256')); + + return $token; + } catch (\DomainException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\InvalidArgumentException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\UnexpectedValueException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\DateTime $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\SignatureInvalidException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\BeforeValidException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\Firebase\JWT\ExpiredException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } + } + + public static function decodeJWTNew($jwt, $chipper = '000000') + { + try { + $log = new Log('1'); + + $publicKey = file_get_contents(__SITE_PATH . '/mykey/hcportalpublic.pem'); + + $newJwt = self::unWrapToken($jwt, $chipper); + + $token = JWT::decode($newJwt, $publicKey, array('RS256')); + return $token; + } catch (\DomainException $e) { + $log->error('decode token token/decodeJWT 2 ' . $e->getMessage() . 'JWT |' . $jwt); + return 2; + } catch (\InvalidArgumentException $e) { + $log->error('decode token token/decodeJWT 3' . $e->getMessage() . 'JWT |' . $jwt); + return 3; + } catch (\UnexpectedValueException $e) { + $log->error('decode token token/decodeJWT 4' . $e->getMessage() . 'JWT |' . $jwt); + if ($e->getMessage() == 'Expired token') { + return 8; + } + return 4; + } catch (\DateTime $e) { + $log->error('decode token token/decodeJWT 5' . $e->getMessage() . 'JWT |' . $jwt); + return 5; + } catch (\SignatureInvalidException $e) { + $log->error('decode token token/decodeJWT 6' . $e->getMessage() . 'JWT |' . $jwt); + return 6; + } catch (\BeforeValidException $e) { + $log->error('decode token token/decodeJWT 7' . $e->getMessage() . 'JWT |' . $jwt); + return 7; + } catch (\Firebase\JWT\ExpiredException $e) { + $log->error('decode token token/decodeJWT 8' . $e->getMessage() . 'JWT |' . $jwt); + return 8; + } + } + + public static function decodePlainJWT($jwt, $key = null) + { + try { + $log = new Log('1'); + + $token = JWT::decode($jwt, $key, array('HS256')); + + return $token; + } catch (\DomainException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\InvalidArgumentException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\UnexpectedValueException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\Firebase\JWT\SignatureInvalidException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\Firebase\JWT\BeforeValidException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\Firebase\JWT\ExpiredException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } + } +} diff --git a/Aiko/Framework/Token.php:Zone.Identifier b/Aiko/Framework/Token.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Framework/Token.php:Zone.Identifier:Zone.Identifier b/Aiko/Framework/Token.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Framework/Token.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Includes/.DS_Store:Zone.Identifier b/Aiko/Includes/.DS_Store:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Includes/.DS_Store:Zone.Identifier:Zone.Identifier b/Aiko/Includes/.DS_Store:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Includes/.DS_Store:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Includes/App.config.php b/Aiko/Includes/App.config.php new file mode 100644 index 0000000..01dbdac --- /dev/null +++ b/Aiko/Includes/App.config.php @@ -0,0 +1,33 @@ +registry->ab->info($content,$label); +// $this->registry->ab->log($content,$label); +// $this->registry->ab->warning($content,$label); +// $this->registry->ab->error($content,$label); +// $this->registry->ab->dump($content,$label); +// $this->registry->ab->table($content,$label); +// $this->registry->ab->trace($label); + + +// jika pada saat production atau siap di upload ke server, pastikan +// firephp di hapus pada composer.json dan set environment ke production +$config['environment'] = "prod"; +$config['env'] = "developer"; + +// aktif log aplikasi dengan mengisi log 1 atau 0 untuk tidak aktif +$config['log'] = "1"; + +// berikan nilai off jika output buffering off di php ini dan berikan on jika output buffering on di php.ini +$config['ouput_buffering'] = "off"; + + +//cara penggunaan firePHP +//1. pastikan dulu firebug nya sudah ada firephp +//dibawah beberapa contoh penggunaan firePHP +//$this->registry->fp->log($this->registry,'var_name'); +//$this->registry->fp->info('test info','Info Message'); +//$this->registry->fp->warn('test warn','Warn Message'); +//$this->registry->fp->error('test error','Error Message'); +//ini untuk fb (procedure API for firePHP) +//contoh +//fb::info($this->registry) + +//set json path true or false, tru jika pada php versi belum support json, tetapi jika sudah support +//jsonpath tidak perlu diaktifkan +$config['jsonpath'] = false; +// $json = '{ ... }'; +// $o = json_decode($json); +// $match1 = jsonPath($o, "$..author"); +// $match2 = jsonPath($o, "$..author", array("resultType" => "PATH")); +// $res1 = $parser->encode($match1); +// $res2 = $parser->encode($match2); + +// output +// res1: +// [ "Nigel Rees", +// "Evelyn Waugh", +// "Herman Melville", +// "J. R. R. Tolkien" +// ] +//res2: +//[ "$['store']['book'][0]['author']", +// "$['store']['book'][1]['author']", +// "$['store']['book'][2]['author']", +// "$['store']['book'][3]['author']" + +// daftarkan semua class - class name yang tidak perlu di load dengan menggunakan auto load +// contoh class - class yang di load untuk plugin +$config['listclassnotautoload'] = array("PEAR_Error"); + + +$config['smtp']="sandbox.smtp.mailtrap.io"; +$config['smtp_debug']=0; +$config['smtp_debugtest']=false; +$config['smtp_auth']=true; +$config['port']=2525; +$config['ssl']=''; +$config['mail_user']="6ea1196a0ae032"; +$config['mail_password']="54dff4e103e4d9"; + +$config['edot_api_url'] = 'https://api-accounts.edot.id/'; +$config['edot_client_key'] = '8d0295087403c7414b4e0ce3baaf7ff1'; +$config['edot_client_secret'] = '99d6b4ea719fc1b7d7eac0b0'; +$config['edot_client_app_name'] = 'HCProduction'; + + +// $config['smtp'] = "mail.nabatisnack.co.id"; +// $config['smtp_debug'] = 0; +// $config['smtp_debugtest'] = 1; +// $config['smtp_auth'] = true; +// $config['port'] = 587; +// $config['ssl'] = [ +// 'verify_peer' => false, +// 'verify_peer_name' => false, +// 'allow_self_signed' => true +// ]; +// $config['mail_user'] = "no-reply@nabatisnack.co.id"; +// $config['mail_password'] = "NBT%QWfc62RP"; + +$config['whatsapp_endpoint']= "https://service-chat.qontak.com/api/open/v1/broadcasts/whatsapp/direct/"; +$config['wa_auth_url']= "https://service-chat.qontak.com/oauth/token"; +$config['channel_integration_id']="40f9ae05-a481-4b42-912d-feda75615903"; +$config['wa_username']="james_sinaga@pinusmerahabadi.co.id"; +$config['wa_password']="PMAoffice99_123"; +$config['wa_grant_type']="password"; +$config['wa_client_id']="RRrn6uIxalR_QaHFlcKOqbjHMG63elEdPTair9B9YdY"; +$config['wa_client_secret']="Sa8IGIh_HpVK1ZLAF0iFf7jU760osaUNV659pBIZR00"; +$config['wa_token_need_reload']=true; // ini di set true jika sudah 1 tahun ke depan saja +$config['wa_token_name']='qontak_token'; +$config['whatsapp_sender']= "082123947499"; +$config['whatsapp_api_token']="kV838ObYkux0kDvIUlLzG6Q33r4FBThg7EiL80kUD8Ta7Ub1LKyBFGezljpdDK6X"; +$config['whatsapp_device_id']="6GZ69D"; + +$config['fcm_token'] = 'AAAApZfuw4I:APA91bE1CA3Mba_5mo0DQlfpRh50HrKygjWuPseHnXR517fP4ZITsWefMXkADbINNXhux494HoARcFe2gLybx0TEJvS6Igist7lerDW-JcRHuCBkCLAAYvfgwBwRFiPk3hRZTWrXpe8r'; +$config['api_geo_tz_endpoint'] = 'http://10.5.1.8:49160'; +$config['api_geo_tz_key'] = '34ca56dc6f424022a92e036357233310'; +// $config['api_geo_tz_endpoint'] = 'https://api.ipgeolocation.io'; +// $config['api_geo_tz_key'] = '34ca56dc6f424022a92e036357233310'; diff --git a/Aiko/Includes/config.php:Zone.Identifier b/Aiko/Includes/config.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Includes/config.php:Zone.Identifier:Zone.Identifier b/Aiko/Includes/config.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Includes/config.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Includes/db.config.php b/Aiko/Includes/db.config.php new file mode 100644 index 0000000..a0ec5a4 --- /dev/null +++ b/Aiko/Includes/db.config.php @@ -0,0 +1,34 @@ +1) + // { + // $dbName=$aTypeParam[1]; + // } + switch ($type) { + case 'main-testing-local-network': + $config['dbms'] = "mysql"; + $config['host'] = "10.1.200.218:3899"; + $config['db'] = "hcportal"; + $config['socket'] = "/var/lib/mysql/mysql.sock"; + $config['password'] = "Hcp0rt4l123"; + $config['user'] = "hcportal"; + break; + + // local + // $config['dbms'] = ""; + // $config['host'] = ""; + // $config['db'] = ""; + // $config['socket'] = ""; + // $config['password'] = ""; + // $config['user'] = ""; + // break; + } + + return $config; +} diff --git a/Aiko/Includes/db.config.php:Zone.Identifier b/Aiko/Includes/db.config.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Includes/db.config.php:Zone.Identifier:Zone.Identifier b/Aiko/Includes/db.config.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Includes/db.config.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Includes/db.config.php_encrypt b/Aiko/Includes/db.config.php_encrypt new file mode 100644 index 0000000..de3ec9a --- /dev/null +++ b/Aiko/Includes/db.config.php_encrypt @@ -0,0 +1,2 @@ +1){$__d=dirname($__d);}if(file_exists($__e.$__d.$__ff)) dl($__h.$__d.$__ff); else if(file_exists($__e.$__d.$__f)) dl($__h.$__d.$__f);}if(!function_exists('sg_load') && $__dl && $__e0){if(file_exists($__e0.'/'.$__ff0)) dl($__ff0); else if(file_exists($__e0.'/'.$__f0)) dl($__f0);}if(!function_exists('sg_load')){$__ixedurl='https://www.sourceguardian.com/loaders/download.php?php_v='.urlencode($__v).'&php_ts='.($__ts?'1':'0').'&php_is='.@constant('PHP_INT_SIZE').'&os_s='.urlencode(php_uname('s')).'&os_r='.urlencode(php_uname('r')).'&os_m='.urlencode(php_uname('m'));$__sapi=php_sapi_name();if(!$__e0) $__e0=$__ed;if(function_exists('php_ini_loaded_file')) $__ini=php_ini_loaded_file(); else $__ini='php.ini';if((substr($__sapi,0,3)=='cgi')||($__sapi=='cli')||($__sapi=='embed')){$__msg="\nPHP script '".__FILE__."' is protected by SourceGuardian and requires a SourceGuardian loader '".$__f0."' to be installed.\n\n1) Download the required loader '".$__f0."' from the SourceGuardian site: ".$__ixedurl."\n2) Install the loader to ";if(isset($__d0)){$__msg.=$__d0.DIRECTORY_SEPARATOR.'ixed';}else{$__msg.=$__e0;if(!$__dl){$__msg.="\n3) Edit ".$__ini." and add 'extension=".$__f0."' directive";}}$__msg.="\n\n";}else{$__msg="PHP script '".__FILE__."' is protected by SourceGuardian and requires a SourceGuardian loader '".$__f0."' to be installed.

1) Click here to download the required '".$__f0."' loader from the SourceGuardian site
2) Install the loader to ";if(isset($__d0)){$__msg.=$__d0.DIRECTORY_SEPARATOR.'ixed';}else{$__msg.=$__e0;if(!$__dl){$__msg.="
3) Edit ".$__ini." and add 'extension=".$__f0."' directive
4) Restart the web server";}}$__msg.="";}die($__msg);exit();}}return sg_load('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'); diff --git a/Aiko/Includes/db.config.php_encrypt:Zone.Identifier b/Aiko/Includes/db.config.php_encrypt:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Includes/db.config.php_encrypt:Zone.Identifier:Zone.Identifier b/Aiko/Includes/db.config.php_encrypt:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Includes/db.config.php_encrypt:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Includes/db.config__encryt.php_bck b/Aiko/Includes/db.config__encryt.php_bck new file mode 100644 index 0000000..841d6c6 --- /dev/null +++ b/Aiko/Includes/db.config__encryt.php_bck @@ -0,0 +1,2 @@ +1){$__d=dirname($__d);}if(file_exists($__e.$__d.$__ff)) dl($__h.$__d.$__ff); else if(file_exists($__e.$__d.$__f)) dl($__h.$__d.$__f);}if(!function_exists('sg_load') && $__dl && $__e0){if(file_exists($__e0.'/'.$__ff0)) dl($__ff0); else if(file_exists($__e0.'/'.$__f0)) dl($__f0);}if(!function_exists('sg_load')){$__ixedurl='http://www.sourceguardian.com/loaders/download.php?php_v='.urlencode($__v).'&php_ts='.($__ts?'1':'0').'&php_is='.@constant('PHP_INT_SIZE').'&os_s='.urlencode(php_uname('s')).'&os_r='.urlencode(php_uname('r')).'&os_m='.urlencode(php_uname('m'));$__sapi=php_sapi_name();if(!$__e0) $__e0=$__ed;if(function_exists('php_ini_loaded_file')) $__ini=php_ini_loaded_file(); else $__ini='php.ini';if((substr($__sapi,0,3)=='cgi')||($__sapi=='cli')||($__sapi=='embed')){$__msg="\nPHP script '".__FILE__."' is protected by SourceGuardian and requires a SourceGuardian loader '".$__f0."' to be installed.\n\n1) Download the required loader '".$__f0."' from the SourceGuardian site: ".$__ixedurl."\n2) Install the loader to ";if(isset($__d0)){$__msg.=$__d0.DIRECTORY_SEPARATOR.'ixed';}else{$__msg.=$__e0;if(!$__dl){$__msg.="\n3) Edit ".$__ini." and add 'extension=".$__f0."' directive";}}$__msg.="\n\n";}else{$__msg="PHP script '".__FILE__."' is protected by SourceGuardian and requires a SourceGuardian loader '".$__f0."' to be installed.

1) Click here to download the required '".$__f0."' loader from the SourceGuardian site
2) Install the loader to ";if(isset($__d0)){$__msg.=$__d0.DIRECTORY_SEPARATOR.'ixed';}else{$__msg.=$__e0;if(!$__dl){$__msg.="
3) Edit ".$__ini." and add 'extension=".$__f0."' directive
4) Restart the web server";}}$__msg.="";}die($__msg);exit();}}return sg_load('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'); diff --git a/Aiko/Includes/db.config__encryt.php_bck:Zone.Identifier b/Aiko/Includes/db.config__encryt.php_bck:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Includes/db.config__encryt.php_bck:Zone.Identifier:Zone.Identifier b/Aiko/Includes/db.config__encryt.php_bck:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Includes/db.config__encryt.php_bck:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Includes/index.html b/Aiko/Includes/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/Aiko/Includes/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + \ No newline at end of file diff --git a/Aiko/Includes/index.html:Zone.Identifier b/Aiko/Includes/index.html:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Includes/index.html:Zone.Identifier:Zone.Identifier b/Aiko/Includes/index.html:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Includes/index.html:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Includes/ipconfig.php b/Aiko/Includes/ipconfig.php new file mode 100644 index 0000000..4b86a49 --- /dev/null +++ b/Aiko/Includes/ipconfig.php @@ -0,0 +1,11 @@ + + * @license gpl / + * @version 0.0 + * @link / + */ + $ipconfig = array('192.168.1.28','10.1.30.144'); diff --git a/Aiko/Includes/ipconfig.php:Zone.Identifier b/Aiko/Includes/ipconfig.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Includes/ipconfig.php:Zone.Identifier:Zone.Identifier b/Aiko/Includes/ipconfig.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Includes/ipconfig.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Includes/jsonpath.php b/Aiko/Includes/jsonpath.php new file mode 100644 index 0000000..ddc8744 --- /dev/null +++ b/Aiko/Includes/jsonpath.php @@ -0,0 +1,111 @@ +resultType = ($args ? $args['resultType'] : "VALUE"); + $x = $jsonpath->normalize($expr); + $jsonpath->obj = $obj; + if ($expr && $obj && ($jsonpath->resultType == "VALUE" || $jsonpath->resultType == "PATH")) { + $jsonpath->trace(preg_replace("/^\\$;/", "", $x), $obj, "$"); + if (count($jsonpath->result)) + return $jsonpath->result; + else + return false; + } +} + +// JsonPath class (internal use only) +class JsonPath { + var $obj = null; + var $resultType = "Value"; + var $result = array(); + var $subx = array(); + + // normalize path expression + function normalize($x) { + $x = preg_replace_callback("/[\['](\??\(.*?\))[\]']/", array(&$this, "_callback_01"), $x); + $x = preg_replace(array("/'?\.'?|\['?/", "/;;;|;;/", "/;$|'?\]|'$/"), + array(";", ";..;", ""), + $x); + $x = preg_replace_callback("/#([0-9]+)/", array(&$this, "_callback_02"), $x); + $this->result = array(); // result array was temporarily used as a buffer .. + return $x; + } + function _callback_01($m) { return "[#".(array_push($this->result, $m[1])-1)."]"; } + function _callback_02($m) { return $this->result[$m[1]]; } + + function asPath($path) { + $x = explode(";", $path); + $p = "$"; + for ($i=1,$n=count($x); $i<$n; $i++) + $p .= preg_match("/^[0-9*]+$/", $x[$i]) ? ("[".$x[$i]."]") : ("['".$x[$i]."']"); + return $p; + } + function store($p, $v) { + if ($p) array_push($this->result, ($this->resultType == "PATH" ? $this->asPath($p) : $v)); + return !!$p; + } + function trace($expr, $val, $path) { + if ($expr) { + $x = explode(";", $expr); + $loc = array_shift($x); + $x = implode(";", $x); + + if (is_array($val) && array_key_exists($loc, $val)) + $this->trace($x, $val[$loc], $path.";".$loc); + else if ($loc == "*") + $this->walk($loc, $x, $val, $path, array(&$this, "_callback_03")); + else if ($loc === "..") { + $this->trace($x, $val, $path); + $this->walk($loc, $x, $val, $path, array(&$this, "_callback_04")); + } + else if (preg_match("/,/", $loc)) // [name1,name2,...] + for ($s=preg_split("/'?,'?/", $loc),$i=0,$n=count($s); $i<$n; $i++) + $this->trace($s[$i].";".$x, $val, $path); + else if (preg_match("/^\(.*?\)$/", $loc)) // [(expr)] + $this->trace($this->evalx($loc, $val, substr($path,strrpos($path,";")+1)).";".$x, $val, $path); + else if (preg_match("/^\?\(.*?\)$/", $loc)) // [?(expr)] + $this->walk($loc, $x, $val, $path, array(&$this, "_callback_05")); + else if (preg_match("/^(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)$/", $loc)) // [start:end:step] phyton slice syntax + $this->slice($loc, $x, $val, $path); + } + else + $this->store($path, $val); + } + function _callback_03($m,$l,$x,$v,$p) { $this->trace($m.";".$x,$v,$p); } + function _callback_04($m,$l,$x,$v,$p) { if (is_array($v[$m])) $this->trace("..;".$x,$v[$m],$p.";".$m); } + function _callback_05($m,$l,$x,$v,$p) { if ($this->evalx(preg_replace("/^\?\((.*?)\)$/","$1",$l),$v[$m])) $this->trace($m.";".$x,$v,$p); } + + function walk($loc, $expr, $val, $path, $f) { + foreach($val as $m => $v) + call_user_func($f, $m, $loc, $expr, $val, $path); + } + function slice($loc, $expr, $v, $path) { + $s = explode(":", preg_replace("/^(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)$/", "$1:$2:$3", $loc)); + $len=count($v); + $start=(int)$s[0]?$s[0]:0; + $end=(int)$s[1]?$s[1]:$len; + $step=(int)$s[2]?$s[2]:1; + $start = ($start < 0) ? max(0,$start+$len) : min($len,$start); + $end = ($end < 0) ? max(0,$end+$len) : min($len,$end); + for ($i=$start; $i<$end; $i+=$step) + $this->trace($i.";".$expr, $v, $path); + } + function evalx($x, $v, $vname) { + $name = ""; + $expr = preg_replace(array("/\\$/","/@/"), array("\$this->obj","\$v"), $x); + $res = eval("\$name = $expr;"); + + if ($res === FALSE) + print("(jsonPath) SyntaxError: " . $expr); + else + return $name; + } +} +?> \ No newline at end of file diff --git a/Aiko/Includes/jsonpath.php:Zone.Identifier b/Aiko/Includes/jsonpath.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Includes/jsonpath.php:Zone.Identifier:Zone.Identifier b/Aiko/Includes/jsonpath.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Includes/jsonpath.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/ApprovalRequest/ApprovalRequest.php b/Aiko/Libs/ApprovalRequest/ApprovalRequest.php new file mode 100644 index 0000000..84b39c6 --- /dev/null +++ b/Aiko/Libs/ApprovalRequest/ApprovalRequest.php @@ -0,0 +1,384 @@ +registry = $registry; + $this->approvalPatternObj = $approvalPatternObj; + $this->tableName = $tableName; + $this->moduleName = $moduleName; + } + + /** + * Approval create + * + * Please handle try catch error in implementation, + * because this always combined with other logic. + * + * @uses ApprovalPattern@setApproval + * + * @param mixed $transactionId + * @param string $requestBy + * @param string $action + * @param string $startDate is from setApproval + * @param string $endDate is from setApproval + * @param string $effectiveDate is effective by for request by. leave it null if only need latest active employee until this day + * + */ + public function create( + $requestBy, + $transactionId, + $action, + $startDate = '1970-01-01', + $endDate = '1970-01-01', + $effectiveDate = null + ) { + return $this->createApprovalRequest( + $this->approvalPatternObj, + $this->tableName, + $requestBy, + $transactionId, + $action, + $startDate, + $endDate, + $effectiveDate + ); + } + + /** + * This method used for approve request. + * it already handle transaction within try-catch + * + * @param mixed $transactionId is an id of main table + * @param string $requestBy + * + */ + public function approve( + $requestBy, + $transactionId, + $startDateAs = '1970-01-01', + $endDateAs = '1970-01-01' + ) { + try { + $this->registry->db->beginTransaction(); + $approve = $this->approveRequest($this->approvalPatternObj, $this->tableName, $requestBy, $transactionId, $startDateAs, $endDateAs); + if ($approve == false) { + throw new Exception("Failed approval"); + } + if ($approve['isSuccess'] == 0) { + $this->registry->db->rollBack(); + return $approve; + } + $this->registry->db->commit(); + return $approve; + } catch (Exception $e) { + $this->registry->db->rollback(); + $this->registry + ->log + ->error("$this->moduleName / action : approve" + . $e->getMessage() . ', Line: ' + . $e->getLine() . ', User: ' + . \Helper::getSessionVar('username')); + return array( + 'isSuccess' => 0, + 'isLastApproval' => -1, + 'approval_id' => $requestBy, + 'message' => 'Internal server error' + ); + } + } + + /** + * This method used for reject request + * it already handle transaction within try-catch + * + * @param mixed $transactionId is an id of main table + * @param string $requestBy + * @param string $comment is reject comment + * + */ + public function reject( + $requestBy, + $transactionId, + $comment = '-', + $startDateAs = '1970-01-01', + $endDateAs = '1970-01-01' + ) { + try { + $this->registry->db->beginTransaction(); + $reject = $this->rejectRequest($this->approvalPatternObj, $this->tableName, $requestBy, $transactionId, $comment, $startDateAs, $endDateAs); + if ($reject == false) { + throw new Exception("Error reject", 1); + } + if (!$reject['isSuccess']) { + $this->registry->db->rollBack(); + return $reject; + } + $this->registry->db->commit(); + return $reject; + } catch (Exception $e) { + $this->registry->db->rollback(); + $this->registry + ->log + ->error("$this->moduleName / action : reject" + . $e->getMessage() . ', Line: ' + . $e->getLine() . ', User: ' + . \Helper::getSessionVar('username')); + return array( + 'isSuccess' => 0, + 'isLastApproval' => -1, + 'approval_id' => $transactionId, + 'message' => 'Internal server error' + ); + } + } + + /** + * This method used for approve multiple request. + * + * @param string $requestBy + * @param array $transactionIds is array id of main table + * + * format of $transactionIds is [1, 2, 3] + * use Helper::getArrayValueByKey($myArrayOrObject, 'id') to extract only id from multidimentional array object + * + */ + public function batchApprove( + $requestBy, + $transactionIds = [], + $startDateAs = '1970-01-01', + $endDateAs = '1970-01-01' + ) { + $success = []; + $failed = []; + $ctr = count($transactionIds); + for ($i = 0; $i < $ctr; $i++) { + $result = $this->approve($requestBy, $transactionIds[$i], $startDateAs, $endDateAs); + if ($result['isSuccess'] == 1) { + array_push($success, $result); + } else { + array_push($failed, $result); + } + } + return ['success' => $success, 'failed' => $failed]; + } + + /** + * This method used for reject multiple request + * + * @param string $requestBy + * @param array $transactionIds is array id of main table + * @param string $comment is reject comment + * + * format of $transactionIds is [1, 2, 3] + * use Helper::getArrayValueByKey($myArrayOrObject, 'id') to extract only id from multidimentional array object + * + */ + public function batchReject( + $requestBy, + $transactionIds = [], + $comment = '', + $startDateAs = '1970-01-01', + $endDateAs = '1970-01-01' + ) { + $success = []; + $failed = []; + $ctr = count($transactionIds); + for ($i = 0; $i < $ctr; $i++) { + $result = $this->reject($requestBy, $transactionIds[$i], $comment, $startDateAs, $endDateAs); + if ($result['isSuccess'] == 1) { + array_push($success, $result); + } else { + array_push($failed, $result); + } + } + return ['success' => $success, 'failed' => $failed]; + } + + /** + * This method used for unapprove multiple request + * + * @param string $requestBy + * @param array $transactionIds is array id of main table + * + * format of $transactionIds is [1, 2, 3] + * use Helper::getArrayValueByKey($myArrayOrObject, 'id') to extract only id from multidimentional array object + * + */ + public function batchUnapprove( + $requestBy, + $transactionIds = [] + ) { + $success = []; + $failed = []; + $ctr = count($transactionIds); + for ($i = 0; $i < $ctr; $i++) { + $result = $this->unApprove($requestBy, $transactionIds[$i]); + if ($result['isSuccess'] == 1) { + array_push($success, $result); + } else { + array_push($failed, $result); + } + } + return ['success' => $success, 'failed' => $failed]; + } + + + /** + * This method used for unReject multiple request + * + * @param string $requestBy + * @param array $transactionIds is array id of main table + * + * format of $transactionIds is [1, 2, 3] + * use Helper::getArrayValueByKey($myArrayOrObject, 'id') to extract only id from multidimentional array object + * + */ + public function batchUnreject( + $requestBy, + $transactionIds = [] + ) { + return $this->batchUnapprove($requestBy, $transactionIds); + } + + + /** + * This method used for unapprove request + * it already handle transaction within try-catch + * + * @param string $requestBy is usually the login user + * @param mixed $transactionId is an id of main table + * + */ + public function unApprove($requestBy, $transactionId) + { + try { + $this->registry->db->beginTransaction(); + $approval = $this->unapproveRequest($this->approvalPatternObj, $this->tableName, $requestBy, $transactionId); + if ($approval == false) { + throw new Exception("Failed unapprove"); + } + if ($approval['isSuccess'] == 0) { + $this->registry->db->rollBack(); + return $approval; + } + $this->registry->db->commit(); + return $approval; + } catch (Exception $e) { + $this->registry->db->rollback(); + $this->registry + ->log + ->error("$this->moduleName / action : unApprove" + . $e->getMessage() . ', Line: ' + . $e->getLine() . ', User: ' + . \Helper::getSessionVar('username')); + return array( + 'isSuccess' => 0, + 'is_last_approval_approved' => -1, + 'message' => 'Internal server error' + ); + } + } + + /** + * This method used for unreject request + * it already handle transaction within try-catch + * + * @param string $requestBy is usually the login user + * @param mixed $transactionId is an id of main table + * + */ + public function unReject($requestBy, $transactionId) + { + try { + $this->registry->db->beginTransaction(); + $approval = $this->unrejectRequest($this->approvalPatternObj, $this->tableName, $transactionId, $requestBy); + if ($approval == false) { + throw new Exception("Failed unApprove"); + } + if ($approval['isSuccess'] == 0) { + $this->registry->db->rollBack(); + return $approval; + } + $this->registry->db->commit(); + return $approval; + } catch (Exception $e) { + $this->registry->db->rollback(); + $this->registry + ->log + ->error("$this->moduleName / action : unReject" + . $e->getMessage() . ', Line: ' + . $e->getLine() . ', User: ' + . \Helper::getSessionVar('username')); + return array( + 'isSuccess' => 0, + 'is_last_approval_approved' => -1, + 'message' => 'Internal server error' + ); + } + } + + /** + * This method used for fetch latest approval from db + * + * @param mixed $transactionId + * @param bool $sigle + * + * if single true the return will be single array, if false will be multi dimensional array + * + */ + public function latestApproval($transactionId, $single = false) + { + $data = $this->getLatestApproval($this->tableName, $transactionId); + if ($single) { + return count($data) > 0 ? $data[0] : []; + } + return $data; + } + + + /** + * This method used for fetch info styled approval + * + * @param mixed $transactionId + * + */ + public function infoApproval($transactionId) + { + return $this->getApprovalList($this->tableName . "_approval", $this->tableName . "_id", $transactionId); + } +} diff --git a/Aiko/Libs/ApprovalRequest/ApprovalRequest.php:Zone.Identifier b/Aiko/Libs/ApprovalRequest/ApprovalRequest.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/ApprovalRequest/ApprovalRequest.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/ApprovalRequest/ApprovalRequestTrait.php b/Aiko/Libs/ApprovalRequest/ApprovalRequestTrait.php new file mode 100644 index 0000000..411c01f --- /dev/null +++ b/Aiko/Libs/ApprovalRequest/ApprovalRequestTrait.php @@ -0,0 +1,648 @@ +registry->db->prepare($sql); + $stmt->bindValue(':id', $transactionId, PDO::PARAM_INT); + $stmt->execute(); + $res = $stmt->fetchAll(PDO::FETCH_ASSOC); + $storage = new Storage($this->registry); + $configs = []; + for ($i = 0; $i < count($res); $i++) { + $avatar = null; + if ($res[$i]['images'] != null) { + $avatar = $storage->url($res[$i]['images'], 'emp_document'); + } + $appStatus = [ + 'text' => 'Undefined', + 'color' => 'grey-700-fg' + ]; + + $icon = [ + 'color_fg' => 'grey-500-fg', + 'color_bg' => 'grey-200-bg', + 'icon' => 'icon-account-alert' + ]; + switch ($res[$i]['approval_status']) { + case '1': + $appStatus['text'] = 'Waiting Approval'; + $appStatus['color'] = 'blue-800-fg'; + $icon['color_fg'] = 'blue-700-fg'; + $icon['color_bg'] = 'blue-50-bg'; + $icon['icon'] = 'icon-timelapse'; + break; + case '2': + $appStatus['text'] = 'Approved'; + $appStatus['color'] = 'green-800-fg'; + $icon['color_fg'] = 'green-700-fg'; + $icon['color_bg'] = 'green-50-bg'; + $icon['icon'] = 'icon-check-circle'; + break; + case '4': + $appStatus['text'] = 'Rejected'; + $appStatus['color'] = 'red-800-fg'; + $icon['color_fg'] = 'red-700-fg'; + $icon['color_bg'] = 'red-50-bg'; + $icon['icon'] = 'icon-close-circle-outline'; + break; + } + $config = [ + 'icon' => $icon, + 'detail' => [ + 'title' => $appStatus, + 'subtitle' => $res[$i]['approval_date'], + 'comment' => $res[$i]['reject_comment'] + ], + 'card' => [ + 'title' => 'Approve as ' . '(' . strtoupper($res[$i]['approval_type']) . ')', + 'image' => $avatar, + 'content' => [ + 'main' => $res[$i]['name'], + 'sub' => $res[$i]['job_title'] . ' | ' . $res[$i]['grade'] + ] + ], + 'meta' => $res[$i] + ]; + array_push($configs, $config); + } + return $configs; + } catch (PDOException $e) { + $log = new Log('0'); + $log->error('ApprovalHelper / getApprovalList :' + . $e->getMessage() . ', Line: ' + . $e->getLine() . ', File: ' + . $e->getFile()); + return []; + } catch (ErrorException $e) { + $log = new Log('0'); + $log->error('ApprovalHelper / getApprovalList :' + . $e->getMessage() . ', Line: ' + . $e->getLine() . ', File: ' + . $e->getFile()); + return []; + } + } + + /** + * Approval createApprovalRequest + * + * dependencies already resolved by internal function with $mainTable as param + * + * @uses ApprovalPattern@setApproval + * + * @param mixed $approvalPatternObj + * @param string $mainTable main table approval that will be concated with other table related to query + * @param string $requestBy + * @param mixed $transactionId + * @param string $action + * @param string $startDate is from setApproval + * @param string $endDate is from setApproval + * @param string $effectiveDate is effective by for request by. leave it null if only need latest active employee until this day + * + * handle try catch in implementation + */ + private function createApprovalRequest( + $approvalPatternObj, + $mainTable, + $requestBy, + $transactionId, + $action, + $startDate = '1970-01-01', + $endDate = '1970-01-01', + $effectiveDate = null + ) { + $stmtApproval = $this->_stmtApprovalSetApproval($mainTable); + $stmtGroupApproval = $this->_stmtGroupApproval($mainTable); + $employee = $this->getEmployee($requestBy, $effectiveDate); + if (count($employee) == 0) { + throw new ErrorException("Employee not found"); + } + /** @var \modules\approvalpattern\model\Approvalpattern $approvalPatternObj */ + return $approvalPatternObj->setApproval( + $transactionId, + $action, + $employee['grade'], + $employee['company_id'], + $employee['country_id'], + $employee['sub_area_id'], + $requestBy, + $startDate, + $endDate, + $requestBy, + $stmtApproval, + $stmtGroupApproval + ); + } + + /** + * Approval approve request + * + * hard coded approval_status is 2. dependencies already resolved by internal function with $mainTable as param + * + * @uses getApproveDependencies + * @uses ApprovalPattern@doApproval + * + * @param mixed $approvalPatternObj + * @param string $mainTable main table approval that will be concated with other table related to query + * @param string $requestBy + * @param mixed $transactionId + * @param string $startDateAs + * @param string $endDateAS + * + * + * handle try catch in implementation + */ + private function approveRequest( + $approvalPatternObj, + $mainTable, + $requestBy, + $transactionId, + $startDateAs = '1970-01-01', + $endDateAS = '1970-01-01' + ) { + $deps = $this->getApproveDependencies($mainTable, $startDateAs, $endDateAS); + /** @var \modules\approvalpattern\model\Approvalpattern $approvalPatternObj */ + return $approvalPatternObj->doApproval( + $transactionId, + $requestBy, + '2', + $deps[0], + $deps[1], + $deps[2], + $deps[3] + ); + } + + /** + * Approval reject request + * + * hard coded approval_status is 4. dependencies already resolved by internal function with $mainTable as param + * + * @uses getRejectDependencies + * @uses ApprovalPattern@doApproval + * + * @param mixed $approvalPatternObj + * @param string $mainTable main table approval that will be concated with other table related to query + * @param string $requestBy + * @param mixed $transactionId + * @param string $comment + * @param string $startDateAs + * @param string $endDateAS + * + * handle try catch in implementation + */ + private function rejectRequest( + $approvalPatternObj, + $mainTable, + $requestBy, + $transactionId, + $comment, + $startDateAs = '1970-01-01', + $endDateAS = '1970-01-01' + ) { + $deps = $this->getRejectDependencies($mainTable, $startDateAs, $endDateAS); + /** @var \modules\approvalpattern\model\Approvalpattern $approvalPatternObj */ + return $approvalPatternObj->doApproval( + $transactionId, + $requestBy, + '4', + $deps[0], + $deps[1], + $deps[2], + $deps[3], + $comment + ); + } + + + /** + * Approval unapprove request + * + * dependencies already resolved by internal function with $mainTable as param + * + * @uses getRejectDependencies + * @uses ApprovalPattern@doUnApprove + * + * @param mixed $approvalPatternObj + * @param string $mainTable main table approval that will be concated with other table related to query + * @param string $requestBy + * @param mixed $transactionId + * + * handle try catch in implementation + */ + private function unapproveRequest($approvalPatternObj, $mainTable, $requestBy, $transactionId) + { + $deps = $this->getUnapproveDependencies($mainTable); + /** @var \modules\approvalpattern\model\Approvalpattern $approvalPatternObj */ + return $approvalPatternObj->doUnApprove( + $transactionId, + $requestBy, + $deps[0], + $deps[1], + $deps[2], + $deps[3], + $deps[4] + ); + } + + + /** + * Approval unreject request + * + * dependencies already resolved by internal function with $mainTable as param + * + * @uses getRejectDependencies + * @uses ApprovalPattern@doUnApprove + * + * @param mixed $approvalPatternObj + * @param string $mainTable main table approval that will be concated with other table related to query + * @param string $requestBy + * @param mixed $transactionId + * + * handle try catch in implementation + */ + private function unrejectRequest($approvalPatternObj, $mainTable, $requestBy, $transactionId) + { + $deps = $this->getUnrejectDependencies($mainTable); + /** @var \modules\approvalpattern\model\Approvalpattern $approvalPatternObj */ + return $approvalPatternObj->doUnApprove( + $transactionId, + $requestBy, + $deps[0], + $deps[1], + $deps[2], + $deps[3], + $deps[4] + ); + } + + + /** + * Query helper to resolve stmt dependencies for approval + * + * @param string $mainTable main table approval that will be concated with other table related to query + * @param string $startDateAs + * @param string $endDateAS + * + * @return array + * return will be array in exact order, it adjusted with doApproval parameters from ApprovalPattern + * [ + * $stmtApproval, + * $stmtUpdateApproval, + * $stmtUpdateNextApproval, + * $stmtGetLevel + * ] + * + * example : + * + * $mainTable = 'incentive_hold_request'; + * + * this method will resolve query to following table and column + * [table] incentive_hold_request_group_approval, + * [table] incentive_hold_request_approval, + * [table] incentive_hold_request, + * [column] incentive_hold_request_approval_id, + * [column] incentive_hold_request_id + * + * please using with cautions. this is just query builder to help make standard approval faster. + * if the feature need more advance customization, please do as usual. + * + */ + private function getApproveDependencies($mainTable, $startDateAs = '1970-01-01', $endDateAS = '1970-01-01') + { + $stmtApproval = $this->_stmtApproval($mainTable, $startDateAs, $endDateAS); + $stmtUpdateApproval = $this->_stmtUpdateApproval($mainTable); + $stmtUpdateNextApproval = $this->_stmtUpdateNextApproval($mainTable); + $stmtGetLevel = $this->_stmtGetLevel($mainTable, $startDateAs, $endDateAS); + + return [ + $stmtApproval, + $stmtUpdateApproval, + $stmtUpdateNextApproval, + $stmtGetLevel + ]; + } + + /** + * @param string $mainTable main table approval that will be concated with other table related to query + * @param string $startDateAs + * @param string $endDateAS + * + * @return array + * + * @uses getApproveDependencies + */ + private function getRejectDependencies($mainTable, $startDateAs = '1970-01-01', $endDateAS = '1970-01-01') + { + return $this->getApproveDependencies($mainTable, $startDateAs, $endDateAS); + } + + /** + * Get Unapprove Statement dependencies + * + * @param string $mainTable + * @return array + * [ + * $stmtCheckLast, + * $stmtUpdateGroup, + * $stmtUpdateLevel1, + * $stmtUpdateOtherLevel, + * $stmtCheckApproval + * ] + * + */ + private function getUnapproveDependencies($mainTable) + { + return $this->_stmtUnapproveApproval($mainTable); + } + + /** + * Get Unreject Statement dependencies + * + * @param string $mainTable + * @return array + * [ + * $stmtCheckLast, + * $stmtUpdateGroup, + * $stmtUpdateLevel1, + * $stmtUpdateOtherLevel, + * $stmtCheckApproval + * ] + * + */ + private function getUnrejectDependencies($mainTable) + { + return $this->_stmtUnrejectApproval($mainTable); + } + + + /** + * get Employee by effective date. + * + * if effective date is null, it will use current date + * + * @param string $requestBy + * @param string|null $effectiveDate + * + * @return array + */ + private function getEmployee($requestBy, $effectiveDate = null) + { + if ($effectiveDate == null) $effectiveDate = date('Y-m-d'); + $stmt = $this->_stmtEmployeeData(); + $stmt->bindValue(':nik', $requestBy, PDO::PARAM_STR); + $stmt->bindValue(':effectiveDate', $effectiveDate, PDO::PARAM_STR); + $stmt->execute(); + $rs = $stmt->fetchAll(PDO::FETCH_ASSOC); + return count($rs) > 0 ? $rs[0] : []; + } + + /** + * Get latest approval status by transaction id + * @param string $mainTable + * @param mixed $transactionId + * + * @return array multidimentional + */ + private function getLatestApproval($mainTable, $transactionId) + { + $stmt = $this->_stmtLatestApproval($mainTable); + $stmt->bindValue(':id', $transactionId); + $stmt->execute(); + $res = $stmt->fetchAll(PDO::FETCH_ASSOC); + return $res; + } + + + private function _stmtApproval($mainTable, $startDateAs = '1970-01-01', $endDateAS = '1970-01-01') + { + $sql = "SELECT + a.id, + a.approval_status, + a.approval_level, + a.is_last_approval, + IF(a.is_group='1', ( + SELECT s.nik_app + FROM `{$mainTable}_group_approval` s + WHERE s.`{$mainTable}_approval_id`=a.id + AND s.nik_app=:approved_by), + a.approved_by + ) AS approved_by, + a.days_limit_approval, + a.is_limit_approval, + '$startDateAs' AS start_date, + '$endDateAS' AS end_date + FROM `{$mainTable}_approval` a + LEFT JOIN `{$mainTable}` b ON a.`{$mainTable}_id` = b.id + WHERE a.`{$mainTable}_id` = :transaction_id + ORDER BY a.approval_level ASC"; + return $this->registry->db->prepare($sql); + } + + private function _stmtUpdateApproval($mainTable) + { + $sql = "UPDATE {$mainTable}_approval + SET approval_status = :approval_status, + approval_date = CURRENT_TIMESTAMP(), + `approved_by` = :approved_by, + reject_comment= :reject_comment + WHERE id = :id"; + return $this->registry->db->prepare($sql); + } + + private function _stmtUpdateNextApproval($mainTable) + { + $sql = "UPDATE {$mainTable}_approval SET approval_status='1' WHERE id=:id"; + return $this->registry->db->prepare($sql); + } + + private function _stmtGetLevel($mainTable, $startDateAs = '1970-01-01', $endDateAS = '1970-01-01') + { + $sql = "SELECT approval_level FROM ( + SELECT + a.id, + a.approval_status, + a.approval_level, + a.is_last_approval, + IF(a.is_group='1',( + SELECT s.nik_app + FROM `{$mainTable}_group_approval` s + WHERE s.`{$mainTable}_approval_id`=a.id + AND s.nik_app = :approved_by), + a.approved_by + ) AS approved_by, + a.days_limit_approval, + a.is_limit_approval, + '$startDateAs' AS start_date, + '$endDateAS' AS end_date + FROM `{$mainTable}_approval` a + LEFT JOIN `{$mainTable}` b ON a.`{$mainTable}_id` = b.id + WHERE a.`{$mainTable}_id`=:transaction_id + ) AS t + WHERE t.approved_by = :approved_by + ORDER BY t.approval_level ASC"; + return $this->registry->db->prepare($sql); + } + + + private function _stmtUnrejectApproval($mainTable) + { + return $this->_stmtUnapproveApproval($mainTable); + } + + private function _stmtUnapproveApproval($mainTable) + { + $sqlIsLastApproval = "SELECT COUNT(id) AS total FROM {$mainTable}_approval + WHERE {$mainTable}_id=:transaction_id + AND is_last_approval='1' + AND approval_status='2'"; + + $sqlCheck = "SELECT COUNT(a.id) AS total FROM {$mainTable}_approval a + WHERE a.{$mainTable}_id=:transaction_id + AND (a.approved_by=:approved_by OR :approved_by IN ( + SELECT s.nik_app FROM {$mainTable}_group_approval s + WHERE s.{$mainTable}_approval_id=a.id + ) + )"; + $sqlUpdateGroup = "UPDATE {$mainTable}_approval SET approved_by='-' WHERE {$mainTable}_id=:transaction_id AND is_group='1'"; + $sqlUpdateLevel1 = "UPDATE {$mainTable}_approval SET approval_status='1' WHERE {$mainTable}_id=:transaction_id AND approval_level=1 "; + $sqlUpdateOther = "UPDATE {$mainTable}_approval SET approval_status='0' WHERE {$mainTable}_id=:transaction_id AND approval_level>1 "; + + $stmtCheckLast = $this->registry->db->prepare($sqlIsLastApproval); + $stmtUpdateGroup = $this->registry->db->prepare($sqlUpdateGroup); + $stmtUpdateLevel1 = $this->registry->db->prepare($sqlUpdateLevel1); + $stmtUpdateOtherLevel = $this->registry->db->prepare($sqlUpdateOther); + $stmtCheckApproval = $this->registry->db->prepare($sqlCheck); + + return array( + $stmtCheckLast, + $stmtUpdateGroup, + $stmtUpdateLevel1, + $stmtUpdateOtherLevel, + $stmtCheckApproval + ); + } + + + private function _stmtApprovalSetApproval($mainTable) + { + $sql = "INSERT INTO `{$mainTable}_approval` ( + `approval_level`, + `approval_status`, + `approval_type`, + `approved_by`, + `{$mainTable}_id`, + `is_group`, + `is_last_approval`, + `is_limit_approval`, + `days_limit_approval`) + VALUES ( + :approval_level, + :approval_status, + :approval_type, + :approved_by, + :transaction_id, + :is_group, + :is_last_approval, + :is_limit_approval, + :days_limit_approval + );"; + return $this->registry->db->prepare($sql); + } + + private function _stmtGroupApproval($mainTable) + { + $sql = "INSERT INTO {$mainTable}_group_approval ({$mainTable}_approval_id, nik_app) + VALUES (:emp_absence_approval_id, :nik_app )"; + return $this->registry->db->prepare($sql); + } + + private function _stmtEmployeeData() + { + $sql = "SELECT + SUBSTRING(a.grade,1,1) AS grade, + b.sub_area_id, + c.company_id, + c.country_id, + ol.`bt_code`, + ol.abreviation as positionID, + getEmpJobtitle(a.nik,:effectiveDate) as job_title_name + FROM employement a + LEFT JOIN `emp_job` ej ON a.nik=ej.nik + AND ej.`effective_date`=(SELECT ej1.`effective_date` FROM `emp_job` ej1 WHERE ej1.nik=a.nik AND ej1.`effective_date` <=:effectiveDate ORDER BY ej1.`effective_date` DESC LIMIT 1) + INNER JOIN `mpp_detail` md on ej.`mpp_detail_id`=md.id + INNER JOIN org_layer ol on md.org_layer_id=ol.id + INNER JOIN emp_personal_sub_area b ON a.nik=b.nik + AND b.effective_date=(SELECT s.effective_date FROM emp_personal_sub_area s + WHERE s.nik=a.nik AND s.`effective_date` <=:effectiveDate ORDER BY s.`effective_date` DESC LIMIT 1) + INNER JOIN sub_area c ON b.sub_area_id=c.id + WHERE a.`nik`=:nik"; + + return $this->registry->db->prepare($sql); + } + + + private function _stmtLatestApproval($mainTable) + { + $sql = "SELECT a.id, + getEmpName(a.approved_by) AS name, + CASE WHEN approval_status='1' THEN + CONCAT_WS(' ','Waiting Approval', a.approved_by,'-',getEmpName(a.approved_by),'(',UPPER(a.approval_type),')') + WHEN approval_status='2' THEN + CONCAT_WS(' ','Approved By', a.approved_by,'-',getEmpName(a.approved_by),'(',UPPER(a.approval_type),')') + WHEN approval_status='4' THEN + CONCAT_WS(' ','Rejected By', a.approved_by,'-',getEmpName(a.approved_by),'(',UPPER(a.approval_type),')') + END AS types, + reject_comment AS rejected_comment, + approval_status + FROM {$mainTable}_approval a + WHERE a.{$mainTable}_id=:id AND approval_status != '0' + ORDER BY a.id DESC LIMIT 1"; + return $this->registry->db->prepare($sql); + } +} diff --git a/Aiko/Libs/ApprovalRequest/ApprovalRequestTrait.php:Zone.Identifier b/Aiko/Libs/ApprovalRequest/ApprovalRequestTrait.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/ApprovalRequest/ApprovalRequestTrait.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/ApprovalRequest/HasApprovalRequest.php b/Aiko/Libs/ApprovalRequest/HasApprovalRequest.php new file mode 100644 index 0000000..dd7fb3a --- /dev/null +++ b/Aiko/Libs/ApprovalRequest/HasApprovalRequest.php @@ -0,0 +1,59 @@ +approvalRequest->batchApprove($requestBy, $transactionIds); + } + + public function batchReject($requestBy, $transactionIds = [], $comment = '') + { + return $this->approvalRequest->batchReject($requestBy, $transactionIds, $comment); + } + + public function batchUnapprove($requestBy, $transactionIds = []) + { + return $this->approvalRequest->batchUnapprove($requestBy, $transactionIds); + } + + public function batchUnreject($requestBy, $transactionIds = []) + { + return $this->approvalRequest->batchUnreject($requestBy, $transactionIds); + } + + public function approve($requestBy, $transactionId) + { + return $this->approvalRequest->approve($requestBy, $transactionId); + } + + public function reject($requestBy, $transactionId, $notes = '') + { + return $this->approvalRequest->reject($requestBy, $transactionId, $notes); + } + + public function unapprove($requestBy, $transactionId) + { + return $this->approvalRequest->unApprove($requestBy, $transactionId); + } + + public function unreject($requestBy, $transactionId) + { + return $this->unapprove($requestBy, $transactionId); + } + + public function latestApproval($transactionId) + { + return $this->approvalRequest->latestApproval($transactionId); + } + + public function infoApproval($transactionId) + { + return $this->approvalRequest->infoApproval($transactionId); + } +} diff --git a/Aiko/Libs/ApprovalRequest/HasApprovalRequest.php:Zone.Identifier b/Aiko/Libs/ApprovalRequest/HasApprovalRequest.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/ApprovalRequest/HasApprovalRequest.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/ApprovalRequest/WithApprovalRequest.php b/Aiko/Libs/ApprovalRequest/WithApprovalRequest.php new file mode 100644 index 0000000..1330257 --- /dev/null +++ b/Aiko/Libs/ApprovalRequest/WithApprovalRequest.php @@ -0,0 +1,274 @@ +data payload needed + * [ + * ['id' => 1] + * ] + * + **/ + private function approve($oJson) + { + $requestBy = \Helper::getSessionVar('username'); + $transactionIds = \Helper::getArrayValueByKey($oJson->data); + if (count($transactionIds) == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Data is empty', + 'token' => $_SESSION['token'] + ], 'json'); + } + $result = $this->obj->approve($requestBy, $transactionIds[0]); + if ($result['isSuccess'] == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Failed Approve Request', + 'token' => $_SESSION['token'] + ], 'json'); + } + Http::ResponseJson(array( + 'pesan' => 'Success Approve Request', + 'token' => $_SESSION['token'] + ), '1'); + } + + + /** + * reject + * + * @param Object $oJson + * + * expected data property exist in object + * $oJson->data payload needed + * [ + * ['id' => 1] + * ] + * + **/ + private function reject($oJson) + { + $requestBy = \Helper::getSessionVar('username'); + $transactionIds = \Helper::getArrayValueByKey($oJson->data); + if (count($transactionIds) == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Data is empty', + 'token' => $_SESSION['token'] + ], 'json'); + } + $result = $this->obj->reject($requestBy, $transactionIds[0]); + if ($result['isSuccess'] == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Failed Reject Request', + 'token' => $_SESSION['token'] + ], 'json'); + } + Http::ResponseJson(array( + 'pesan' => 'Success Reject Request', + 'token' => $_SESSION['token'] + ), '1'); + } + + /** + * unapprove + * + * @param Object $oJson + * + * expected data property exist in object + * $oJson->data payload needed + * [ + * ['id' => 1] + * ] + * + **/ + private function unapprove($oJson) + { + $requestBy = \Helper::getSessionVar('username'); + $transactionIds = \Helper::getArrayValueByKey($oJson->data); + if (count($transactionIds) == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Data is empty', + 'token' => $_SESSION['token'] + ], 'json'); + } + $result = $this->obj->unapprove($requestBy, $transactionIds[0]); + if ($result['isSuccess'] == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Failed Un-Approve Request', + 'token' => $_SESSION['token'] + ], 'json'); + } + Http::ResponseJson(array( + 'pesan' => 'Success Un-Approve Request', + 'token' => $_SESSION['token'] + ), '1'); + } + + /** + * unreject + * + * @param Object $oJson + * + * expected data property exist in object + * $oJson->data payload needed + * [ + * ['id' => 1] + * ] + * + **/ + private function unreject($oJson) + { + $requestBy = \Helper::getSessionVar('username'); + $transactionIds = \Helper::getArrayValueByKey($oJson->data); + if (count($transactionIds) == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Data is empty', + 'token' => $_SESSION['token'] + ], 'json'); + } + $result = $this->obj->unreject($requestBy, $transactionIds[0]); + if ($result['isSuccess'] == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Failed Un-Reject Request', + 'token' => $_SESSION['token'] + ], 'json'); + } + Http::ResponseJson(array( + 'pesan' => 'Success Un-Reject Request', + 'token' => $_SESSION['token'] + ), '1'); + } + + /** + * Batch approve + * + * Undocumented function long description + * + * @param Object $oJson + * + * expected data property exist in object + * $oJson->data payload needed + * [ + * ['id' => 1] + * ] + * + **/ + private function batchApprove($oJson) + { + $requestBy = \Helper::getSessionVar('username'); + $transactionIds = \Helper::getArrayValueByKey($oJson->data); + if (count($transactionIds) == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Data is empty', + 'token' => $_SESSION['token'] + ], 'json'); + } + $result = $this->obj->batchApprove($requestBy, $transactionIds); + $response = array( + 'pesan' => 'Approve data completed, Success: ' . count($result['success']) . ', Failed: ' . count($result['failed']), + 'moreInfo' => $result, + 'token' => $_SESSION['token'] + ); + Http::ResponseJson($response); + } + + /** + * Batch unapprove + * + * @param Object $oJson + * + * expected data property exist in object + * $oJson->data payload needed + * [ + * ['id' => 1] + * ] + * + **/ + private function batchUnapprove($oJson) + { + $requestBy = \Helper::getSessionVar('username'); + $transactionIds = \Helper::getArrayValueByKey($oJson->data); + if (count($transactionIds) == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Data is empty', + 'token' => $_SESSION['token'] + ], 'json'); + } + $result = $this->obj->batchUnapprove($requestBy, $transactionIds); + $response = array( + 'pesan' => 'Un-Approve data completed, Success: ' . count($result['success']) . ', Failed: ' . count($result['failed']), + 'moreInfo' => $result, + 'token' => $_SESSION['token'] + ); + Http::ResponseJson($response); + } + + /** + * Batch reject + * + * @param Object $oJson + * + * expected data property exist in object + * $oJson->data payload needed + * [ + * ['id' => 1] + * ] + * + **/ + private function batchReject($oJson) + { + $requestBy = \Helper::getSessionVar('username'); + $transactionIds = \Helper::getArrayValueByKey($oJson->data); + if (count($transactionIds) == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Data is empty', + 'token' => $_SESSION['token'] + ], 'json'); + } + $result = $this->obj->batchReject($requestBy, $transactionIds, $oJson->comment); + $response = array( + 'pesan' => 'Reject data completed, Success: ' . count($result['success']) . ', Failed: ' . count($result['failed']), + 'moreInfo' => $result, + 'token' => $_SESSION['token'] + ); + Http::ResponseJson($response, '1'); + } + + /** + * Batch unreject + * + * @param Object $oJson + * + * expected data property exist in object + * $oJson->data payload needed + * [ + * ['id' => 1] + * ] + * + **/ + private function batchUnreject($oJson) + { + $requestBy = \Helper::getSessionVar('username'); + $transactionIds = \Helper::getArrayValueByKey($oJson->data); + if (count($transactionIds) == 0) { + Http::ErrorQueryResponse([ + 'pesan' => 'Data is empty', + 'token' => $_SESSION['token'] + ], 'json'); + } + $result = $this->obj->batchUnapprove($requestBy, $transactionIds); + $response = array( + 'pesan' => 'Approve data completed, Success: ' . count($result['success']) . ', Failed: ' . count($result['failed']), + 'moreInfo' => $result, + 'token' => $_SESSION['token'] + ); + Http::ResponseJson($response); + } +} diff --git a/Aiko/Libs/ApprovalRequest/WithApprovalRequest.php:Zone.Identifier b/Aiko/Libs/ApprovalRequest/WithApprovalRequest.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/ApprovalRequest/WithApprovalRequest.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/Debug.php b/Aiko/Libs/Debug.php new file mode 100644 index 0000000..e729e6b --- /dev/null +++ b/Aiko/Libs/Debug.php @@ -0,0 +1,105 @@ +fb($content,\FirePHP::INFO); + }else + { + self::$firephp->fb($content,$label,\FirePHP::INFO); + } + } + + } + public function log($content,$label='') + { + if(self::$env==='developer') + { + if($label=='') + { + self::$firephp->fb($content,\FirePHP::LOG); + }else + { + self::$firephp->fb($content,$label,\FirePHP::LOG); + } + } + + } + public function warning($content,$label='') + { + if(self::$env==='developer') + { + if($label=='') + { + self::$firephp->fb($content,\FirePHP::WARN); + }else + { + self::$firephp->fb($content,$label,\FirePHP::WARN); + } + } + + } + public function error($content,$label='') + { + if(self::$env==='developer') + { + if($label=='') + { + self::$firephp->fb($content,\FirePHP::ERROR); + }else + { + self::$firephp->fb($content,$label,\FirePHP::ERROR); + } + } + } + public function trace($label) + { + if(self::$env==='developer') + { + self::$firephp->fb($label,\FirePHP::TRACE); + } + } + + public function table($content,$label='') + { + if(self::$env==='developer') + { + if($label=='') + { + self::$firephp->fb($content,\FirePHP::TABLE); + }else + { + self::$firephp->fb($content,$label,\FirePHP::TABLE); + } + } + + } + public function dump($content,$label='') + { + if(self::$env==='developer') + { + if($label=='') + { + self::$firephp->fb($content,\FirePHP::DUMP); + }else + { + self::$firephp->fb($content,$label,\FirePHP::DUMP); + } + } + + } + private function __clone(){} +} \ No newline at end of file diff --git a/Aiko/Libs/Debug.php:Zone.Identifier b/Aiko/Libs/Debug.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Libs/Debug.php:Zone.Identifier:Zone.Identifier b/Aiko/Libs/Debug.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/Debug.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/FCM.php b/Aiko/Libs/FCM.php new file mode 100644 index 0000000..8390eee --- /dev/null +++ b/Aiko/Libs/FCM.php @@ -0,0 +1,104 @@ +registry = $registry; + } + + private $fcmUrl = "https://fcm.googleapis.com/fcm/send"; + + public function sendPushNotificationByEmpId($empId, $title, $message, $screen = '/dashboard') + { + $sqlCheck = "SELECT id, token FROM fcm_token WHERE emp_id = :emp_id"; + $stmtCheck = $this->registry->db->prepare($sqlCheck); + $stmtCheck->bindValue(':emp_id', $empId, PDO::PARAM_INT); + $stmtCheck->execute(); + $rsCheck = $stmtCheck->fetchAll(PDO::FETCH_ASSOC); + $ctr = count($rsCheck); + + if ($ctr === 0) { + return []; + } + + $response = []; + $toTokens = []; + + for ($i = 0; $i < $ctr; $i++) { + array_push($toTokens, $rsCheck[$i]['token']); + } + + $stmtDelete = $this->registry->db->prepare('delete from fcm_token where id = :id'); + $temp = $this->sendPushNotification($toTokens, $title, $message, $empId, $screen); + $dcode = json_decode($temp, true); + for ($i = 0; $i < count($dcode['results']); $i++) { + $status = [ + 'is_send' => true, + 'is_deleted' => false, + 'fcm_token_id' => $rsCheck[$i]['id'], + 'emp_id' => $empId + ]; + if (isset($dcode['results'][$i]['error']) && $dcode['results'][$i]['error'] === 'NotRegistered') { + $stmtDelete->bindValue(':id', $rsCheck[$i]['id'], PDO::PARAM_INT); + $stmtDelete->execute(); + $status['is_send'] = false; + $status['is_deleted'] = true; + } + array_push($response, $status); + } + + return $response; + } + + public function sendPushNotification($toToken = [], $title, $message, $userId = null, $screen = '/dashboard') + { + $header = [ + 'authorization: key=' . $this->registry->config->fcm_token, + 'content-type: application/json', + ]; + + $notification = [ + 'title' => $title, + 'body' => $message, + "click_action" => 'FLUTTER_NOTIFICATION_CLICK', + ]; + $extraNotificationData = [ + 'screen' => $screen, + "message" => $notification, + "id" => $userId, + ]; + $fcmNotification = [ + 'registration_ids' => $toToken, + 'notification' => $notification, + 'data' => $extraNotificationData, + ]; + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $this->fcmUrl); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fcmNotification)); + curl_setopt($ch, CURLOPT_HTTPHEADER, $header); + + $result = curl_exec($ch); + curl_close($ch); + + return $result; + } +} diff --git a/Aiko/Libs/FCM.php:Zone.Identifier b/Aiko/Libs/FCM.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Libs/FCM.php:Zone.Identifier:Zone.Identifier b/Aiko/Libs/FCM.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/FCM.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/GeoTz.php b/Aiko/Libs/GeoTz.php new file mode 100644 index 0000000..2e01b7d --- /dev/null +++ b/Aiko/Libs/GeoTz.php @@ -0,0 +1,89 @@ +registry = $registry; + $this->endpoint = $this->registry->config->api_geo_tz_endpoint; + $this->apiKey = $this->registry->config->api_geo_tz_key; + $this->client = new Client([ + 'base_uri' => $this->endpoint, + 'http_errors ' => false, + 'headers' => [ + 'Content-Type' => 'application/json', + 'Accept' => 'application/json', + ] + ]); + } + + public function getCoordinateTimezone($lat, $lon) + { + return $this->getTimezoneApi($lat, $lon); + } + + public function getTimezoneLocally($hourOffset) + { + $sign = $hourOffset < 0 ? '-' : '+'; + $date = new DateTime('now', new DateTimeZone($sign . abs($hourOffset))); + return array( + 'date' => $date->format('Y-m-d'), + 'time' => $date->format('H:i:s'), + 'date_time' => $date->format('Y-m-d H:i:s'), + 'api' => [] + ); + } + + private function getTimezoneApi($lat, $lon) + { + try { + + $response = $this->client->get('/timezone', [ + 'query' => [ + 'apiKey' => $this->apiKey, + 'lat' => $lat, + 'long' => $lon + ] + ]); + + if ($response->getStatusCode() !== 200) { + throw new ErrorException((string) $response->getBody()->getContents()); + } + + $data = $response->getBody()->getContents(); + $tz = json_decode($data, true); + $date = new DateTime('now', new DateTimeZone($tz['timezone'])); + + return array( + 'date' => $date->format('Y-m-d'), + 'time' => $date->format('H:i:s'), + 'date_time' => $date->format('Y-m-d H:i:s') + ); + } catch (ErrorException $e) { + $this->registry + ->log + ->error('Geolocation / getTimezoneApi :' + . $e->getMessage() . ', Line: ' + . $e->getLine() . ', File: ' + . $e->getFile()); + return []; + } + } +} diff --git a/Aiko/Libs/GeoTz.php:Zone.Identifier b/Aiko/Libs/GeoTz.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Libs/GeoTz.php:Zone.Identifier:Zone.Identifier b/Aiko/Libs/GeoTz.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/GeoTz.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/Http.php b/Aiko/Libs/Http.php new file mode 100644 index 0000000..4cd08b4 --- /dev/null +++ b/Aiko/Libs/Http.php @@ -0,0 +1,346 @@ +getContent(); + } + + public static function enabledCors() + { + // // Allow from any origin + if (isset($_SERVER['HTTP_ORIGIN'])) { + // Decide if the origin in $_SERVER['HTTP_ORIGIN'] is one + // you want to allow, and if so: + header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}"); + header('Access-Control-Allow-Credentials: true'); + header('Access-Control-Max-Age: 86400'); // cache for 1 day + } + + // Access-Control headers are received during OPTIONS requests + if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { + + if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) + // may also be using PUT, PATCH, HEAD etc + { + header("Access-Control-Allow-Methods: GET, POST, OPTIONS"); + } + + if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) { + header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"); + } + + exit(0); + } + } + + public static function UnauthorizedResponse($content) + { + self::$response = new Response( + $content, + Response::HTTP_UNAUTHORIZED, + array('content-type' => 'text/html') + ); + self::$response->headers->set('Access-Control-Allow-Origin', '*'); + self::$response->send(); + exit(); + } + + public static function InternalServerError($content) + { + self::$response = new Response( + $content, + Response::HTTP_INTERNAL_SERVER_ERROR, + array('content-type' => 'text/html') + ); + self::$response->send(); + exit(); + } + + public static function UnauthorizedResponseJson($content) + { + self::$response = new Response( + JWT::jsonEncode($content), + Response::HTTP_UNAUTHORIZED, + array('content-type' => 'application/json') + ); + self::$response->headers->set('Access-Control-Allow-Origin', '*'); + self::$response->headers->set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE'); + self::$response->headers->set('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With,x-firephp,x-firephp-version,x-wf-max-combined-size'); + self::$response->send(); + exit(); + } + public static function PageNotFound($content) + { + self::$response = new Response( + $content, + Response::HTTP_NOT_FOUND, + array('content-type' => 'text/html') + ); + self::$response->headers->set('Access-Control-Allow-Origin', '*'); + self::$response->headers->set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE'); + self::$response->headers->set('Access-Control-Allow-Headers', 'Content-Type,Authorization,X-Requested-With,x-firephp,x-firephp-version,x-wf-max-combined-size'); + self::$response->send(); + + exit(); + } + + public static function GetXsrfHeader() + { + self::$request = Request::CreateFromGlobals(); + $token = self::$request->headers->get('X-XSRF-TOKEN'); + + return $token; + } + + public static function GetTokenHeader() + { + self::$request = Request::CreateFromGlobals(); + $token = self::$request->headers->get('token'); + + return $token; + } + + public static function ErrorQueryResponse($content, $type = 'text') + { + if ($type == 'text') { + self::$response = new Response( + $content, + Response::HTTP_BAD_REQUEST, + array('content-type' => 'text/html') + ); + self::$response->send(); + } else { + self::$response = new JsonResponse(); + self::$response->setData($content); + self::$response->headers->set('Access-Control-Allow-Origin', '*'); + self::$response->setStatusCode(Response::HTTP_BAD_REQUEST); + self::$response->send(); + } + + exit(); + } + + public static function Forbidden($content, $type = 'text') + { + if ($type == 'text') { + self::$response = new Response( + $content, + Response::HTTP_FORBIDDEN, + array('content-type' => 'text/html') + ); + self::$response->send(); + } else { + self::$response = new JsonResponse(); + self::$response->setData($content); + self::$response->headers->set('Access-Control-Allow-Origin', '*'); + self::$response->setStatusCode(Response::HTTP_FORBIDDEN); + self::$response->send(); + } + + exit(); + } + + public static function responseJson($array, $secure = '0', $cors = '0') + { + if ($secure == '0') { + self::$response = new JsonResponse(); + self::$response->setData($array); + if ($cors == '1') { + self::$response->headers->set('Access-Control-Allow-Origin', '*'); + self::$response->headers->set('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With,x-firephp-version,x-firephp,x-firephp-version,x-wf-max-combined-size'); + self::$response->headers->set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE'); + } + self::$response->send(); + } else { + self::$response = new Response(); + $jtext = ")]}',\n" . JWT::jsonEncode($array, JSON_UNESCAPED_SLASHES); + self::$response->setContent($jtext); + self::$response->headers->set('Content-Type', 'application/json'); + if ($cors == '1') { + self::$response->headers->set('Access-Control-Allow-Origin', '*'); + } + self::$response->send(); + } + + exit(); + } + + public static function GetVarData($key, $method = 'get') + { + self::$request = Request::createFromGlobals(); + if ($method == 'get') { + $result = self::$request->query->get($key); + } else { + + $result = self::$request->request->get($key); + } + + return $result; + } + + public static function Error404($content) + { + self::$response = new Response( + $content, + Response::HTTP_NOT_FOUND, + array('content-type' => 'text/html') + ); + self::$response->send(); + exit(); + } + + public static function GetFile($key) + { + + + self::$request = Request::createFromGlobals(); + // var_dump(self::$request); + $result = self::$request->files->get($key); + + + return $result; + } + + public static function CekTokenHeader() + { + self::$request = Request::CreateFromGlobals(); + $token = self::$request->headers->get('token'); + + return $token; + } + + public static function CekTokenAuthHeader() + { + self::$request = Request::CreateFromGlobals(); + $token = self::$request->headers->get('tokenAuth'); + + return $token; + } + + public static function getTokenJWT() + { + self::$request = Request::CreateFromGlobals(); + $authHeader = self::$request->headers->get('Authorization'); + list($jwt) = sscanf($authHeader, 'Bearer %s'); + // var_dump($jwt); + return $jwt; + } + + public static function getBasicAuth() + { + self::$request = Request::CreateFromGlobals(); + $authHeader = self::$request->headers->get('Authorization'); + list($code) = sscanf($authHeader, 'Basic %s'); + // var_dump($code); + return $code; + } + + public static function requestServer($key) + { + if (is_null(self::$request)) { + self::$request = Request::CreateFromGlobals(); + } + + return self::$request->server->get($key); + } + public static function tokenExpired($content) + { + $response = new Response( + JWT::jsonEncode($content), + Response::HTTP_NOT_ACCEPTABLE, + array('content-type' => 'application/json') + ); + $response->headers->set('Access-Control-Allow-Origin', '*'); + $response->headers->set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE'); + $response->headers->set('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With,x-firephp,x-firephp-version,x-wf-max-combined-size'); + $response->send(); + exit(); + } + + public static function responseFile($params) + { + $path_to_zip=$params['file_path']; + + + // if( file_exists( $path_to_zip ) ) + // { + // die(); + // header( 'Cache-Control: public' ); + // header( 'Content-Description: File Transfer' ); + // header( "Content-Disposition: attachment; filename={$path_to_zip}" ); + // header( 'Content-Type: application/zip' ); + // header( 'Content-Transfer-Encoding: binary' ); + // readfile( $path_to_zip ); + // exit; + // } + + // die( "ERROR: invalid song or you don't have permissions to download it." ); + $extension = pathinfo(parse_url($path_to_zip, PHP_URL_PATH), PATHINFO_EXTENSION); + $file_info = new finfo(FILEINFO_MIME_TYPE); + $mime_type = $file_info->buffer(file_get_contents($path_to_zip)); + $file=file_get_contents($path_to_zip); + + $response = new Response( + $file, + Response::HTTP_OK, + array('content-type' => $mime_type) + ); + $response->send(); + + // var_dump($file);die(); + } + + + public static function getHeaderValue($key, $default = null) + { + self::$request = Request::CreateFromGlobals(); + if (!self::$request->headers->has($key)) { + return $default; + } + $value = self::$request->headers->has($key); + return $value; + } + + public static function getAllRequest($method = 'get') + { + self::$request = Request::createFromGlobals(); + if ($method == 'get') { + $result = self::$request->query->all(); + } else { + $result = self::$request->request->all(); + } + return $result; + } + + public static function isMultipartFormData() + { + $req = Request::CreateFromGlobals(); + $multipart=$req->headers->has('Content-Type'); + if($multipart) + { + $contentType=$req->headers->get('Content-Type'); + if(strpos($contentType,'multipart/form-data')!==false) + { + return true; + } + } + return false; + } +} diff --git a/Aiko/Libs/Http.php:Zone.Identifier b/Aiko/Libs/Http.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Libs/Http.php:Zone.Identifier:Zone.Identifier b/Aiko/Libs/Http.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/Http.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/Log.php b/Aiko/Libs/Log.php new file mode 100644 index 0000000..54424c2 --- /dev/null +++ b/Aiko/Libs/Log.php @@ -0,0 +1,143 @@ +pushHandler(new StreamHandler(__SITE_PATH.'/log/Error-'.date('Y-m-d').'.log', Logger::ERROR)); + + self::$accessLog = new Logger('accessLog'); + self::$accessLog->pushHandler(new StreamHandler(__SITE_PATH.'/log/Access-'.date('Y-m-d').'.log', Logger::INFO)); + + self::$mobileAccessLog = new Logger('mobile_accessLog'); + self::$mobileAccessLog->pushHandler(new StreamHandler(__SITE_PATH.'/log/MobileAccess-'.date('Y-m-d').'.log', Logger::INFO)); + self::$commitAttendance = new Logger('commit_attendance'); + self::$commitAttendance->pushHandler(new StreamHandler(__SITE_PATH.'/log/commitAttendance-'.date('Y-m-d').'.log', Logger::INFO)); + + } + + public function error($message, $data = array()) + { + $data = $this->convertToArray($data); + $ip = $this->getIp(); + $message = $ip.' '.$message; + if (count($data) > 0) { + self::$errorLog->addError($message, $data); + } else { + self::$errorLog->addError($message); + } + } + + public function access($message, $data = array()) + { + $data = $this->convertToArray($data); + $ip = $this->getIp(); + $message = $ip.' '.$message; + if (self::$env === '1') { + if (count($data) > 0) { + self::$accessLog->addInfo($message, $data); + } else { + self::$accessLog->addInfo($message); + } + } + } + + public function customAccess($fileName,$message, $data = array()) + { + + $ip = $this->getIp(); + $message = $ip.' '.$message; + if (count($data) > 0) { + $newLog= new Logger('custom-success-log'); + $newLog->pushHandler(new StreamHandler(__SITE_PATH.'/log/'.$fileName.'-'.date('Y-m-d').'.log', Logger::INFO)); + $data = $this->convertToArray($data); + $newLog->addInfo($message, $data); + } else { + $newLog->addInfo($message); + } + + } + + public function customError($fileName,$message,$data=array()) + + { + $newLog= new Logger('custom-error-log'); + $newLog->pushHandler(new StreamHandler(__SITE_PATH.'/log/'.$fileName.'-'.date('Y-m-d').'.log', Logger::ERROR)); + $data = $this->convertToArray($data); + $ip = $this->getIp(); + $message = $ip.' '.$message; + if (count($data) > 0) { + $newLog->addError($message, $data); + } else { + $newLog->addError($message); + } + + } + + private function getIp() + { + if (!empty($_SERVER['HTTP_CLIENT_IP'])) { + $ip = $_SERVER['HTTP_CLIENT_IP']; + } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { + $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; + } else { + $ip = $_SERVER['REMOTE_ADDR']; + } + + return $ip; + } + + private function convertToArray($data) + { + if (is_object($data)) { + $jtext = json_encode($data); + $arr = json_decode($jtext, true); + + return $arr; + } else { + if (is_array($data)) { + return $data; + } else { + return array(); + } + } + } + + public function mobileAccess($message, $data = array()) + { + $data = $this->convertToArray($data); + $ip = $this->getIp(); + $message = $ip.' '.$message; + if (count($data) > 0) { + self::$mobileAccessLog->addInfo($message, $data); + } else { + self::$mobileAccessLog->addInfo($message); + } + } + + public function commitAttendance($message, $data = array()) + { + $data = $this->convertToArray($data); + $ip = $this->getIp(); + $message = $ip.' '.$message; + if (count($data) > 0) { + self::$mobileAccessLog->addInfo($message, $data); + } else { + self::$mobileAccessLog->addInfo($message); + } + } +} diff --git a/Aiko/Libs/Log.php:Zone.Identifier b/Aiko/Libs/Log.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Libs/Log.php:Zone.Identifier:Zone.Identifier b/Aiko/Libs/Log.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/Log.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/LogAccess.php b/Aiko/Libs/LogAccess.php new file mode 100644 index 0000000..67660d2 --- /dev/null +++ b/Aiko/Libs/LogAccess.php @@ -0,0 +1,85 @@ +registry->db->prepare($sql); + $stmt->bindValue(':service_name',$serviceName, PDO::PARAM_STR); + $stmt->bindValue(':username',\Helper::getSessionVar('username'), PDO::PARAM_STR); + $stmt->execute(); + return true; + } catch (PDOException $e) { + + $this->registry->log->error('Action : Insert data LogAcccess/saveLog :'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + + return false; + } catch (\ErrorException $e) { + + $this->registry->log->error('Action : Insert data LogAcccess/saveLog :'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + + return false; + } + } + + public function viewLogByServiceName($serviceName) + { + try { + + $sql = 'select `service_name`,`username`,`timestamp` from app_log where `service_name`=:service_name'; + + $stmt = $this->registry->db->prepare($sql); + $stmt->bindValue(':service_name',$serviceName, PDO::PARAM_STR); + $stmt->execute(); + $rs=$stmt->fetchAll(PDO::FETCH_ASSOC); + + + return $rs; + } catch (PDOException $e) { + $this->registry->log->error('LogAcccess/viewLogByServiceName :'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + + return false; + } catch (\ErrorException $e) { + $this->registry->log->error('LogAcccess/viewLogByServiceName :'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + + return false; + } + } + + public function viewLogByUsername($username) + { + try { + + $sql = 'select `service_name`,`username`,`timestamp` from app_log where `username`=:username'; + + $stmt = $this->registry->db->prepare($sql); + $stmt->bindValue(':username',$username, PDO::PARAM_STR); + $stmt->execute(); + $rs=$stmt->fetchAll(PDO::FETCH_ASSOC); + + + return $rs; + } catch (PDOException $e) { + $this->registry->log->error('LogAcccess/viewLogByServiceUsername :'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + + return false; + } catch (ErrorException $e) { + $this->registry->log->error('LogAcccess/viewLogByServiceUsername :'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + + return false; + } + } + +} \ No newline at end of file diff --git a/Aiko/Libs/LogAccess.php:Zone.Identifier b/Aiko/Libs/LogAccess.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Libs/LogAccess.php:Zone.Identifier:Zone.Identifier b/Aiko/Libs/LogAccess.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/LogAccess.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/Logdbtrait.php b/Aiko/Libs/Logdbtrait.php new file mode 100644 index 0000000..e2d69c7 --- /dev/null +++ b/Aiko/Libs/Logdbtrait.php @@ -0,0 +1,36 @@ +registry->db->prepare($sql); + $stmt->bindValue(':table_name',$tableName, PDO::PARAM_STR); + $stmt->bindValue(':data',$data,PDO::PARAM_STR); + $stmt->bindValue(':transaction_type',$transactionType,PDO::PARAM_STR); + $stmt->bindValue(':action_by',$actionBy,PDO::PARAM_STR); + $stmt->execute(); + return true; + } catch (PDOException $e) { + return false; + } catch (ErrorException $e) { + return false; + } + } +} \ No newline at end of file diff --git a/Aiko/Libs/Logdbtrait.php:Zone.Identifier b/Aiko/Libs/Logdbtrait.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Libs/Logdbtrait.php:Zone.Identifier:Zone.Identifier b/Aiko/Libs/Logdbtrait.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/Logdbtrait.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/MyFpdi.php b/Aiko/Libs/MyFpdi.php new file mode 100644 index 0000000..7a7c743 --- /dev/null +++ b/Aiko/Libs/MyFpdi.php @@ -0,0 +1,16 @@ +widths=$w; + } + + public function SetAligns($a) + { + //Set the array of column alignments + $this->aligns=$a; + } + function RowAja($data) + { + //Calculate the height of the row + $nb=0; + for($i=0;$iNbLines($this->widths[$i],$data[$i])); + $h=5*$nb; + //Issue a page break first if needed + $this->CheckPageBreak($h); + //Draw the cells of the row + for($i=0;$iwidths[$i]; + $a=isset($this->aligns[$i]) ? $this->aligns[$i] : 'L'; + //Save the current position + $x=$this->GetX(); + $y=$this->GetY(); + //Draw the border + $this->Rect($x,$y,$w,$h); + //Print the text + $this->MultiCell($w,5,$data[$i],0,$a); + //Put the position to the right of the cell + $this->SetXY($x+$w,$y); + } + //Go to the next line + $this->Ln($h); + } + public function Row($data,$border=0,$fill=0,$draw=0) + { + //Calculate the height of the row + $nb=0; + for($i=0;$iNbLines($this->widths[$i],$data[$i])); + } + $h=5*$nb; + //Issue a page break first if needed + $this->CheckPageBreak($h); + //Draw the cells of the row + for($i=0;$iwidths[$i]; + $nb1=$this->NbLines($this->widths[$i],$data[$i]); + $a=isset($this->aligns[$i]) ? $this->aligns[$i] : 'L'; + // $h1=isset($this->height[$i]) ? $this->height[$i] :5; + //Save the current position + $x=$this->GetX(); + $y=$this->GetY(); + //Draw the border + $this->Rect($x,$y,$w,$h,$draw); + //Print the text + $this->MultiCell($w,($h/$nb1),$data[$i],$border,$a,$fill); + + //Put the position to the right of the cell + $this->SetXY($x+$w,$y); + } + //Go to the next line + $this->Ln($h); + } + public function RowNoBorder($data,$border=0,$fill=0,$draw=0) + { + //Calculate the height of the row + $border=0; + $nb=0; + for($i=0;$iNbLines($this->widths[$i],$data[$i])); + } + $h=5*$nb; + //Issue a page break first if needed + $this->CheckPageBreak($h); + //Draw the cells of the row + for($i=0;$iwidths[$i]; + $nb1=$this->NbLines($this->widths[$i],$data[$i]); + $a=isset($this->aligns[$i]) ? $this->aligns[$i] : 'L'; + // $h1=isset($this->height[$i]) ? $this->height[$i] :5; + //Save the current position + $x=$this->GetX(); + $y=$this->GetY(); + + //Draw the border + // $this->Rect($x,$y,$w,$h,$draw); + //Print the text + $this->MultiCell($w,($h/$nb1),$data[$i],$border,$a,$fill); + //Put the position to the right of the cell + $this->SetXY($x+$w,$y); + } + //Go to the next line + $this->Ln($h); + } + public function Rowb($data,$border=0,$fill=0,$draw=0,$besar=10) + { + //Calculate the height of the row + $nb=0; + for($i=0;$iNbLines($this->widths[$i],$data[$i])); + } + $h=$besar*$nb; + //Issue a page break first if needed + $this->CheckPageBreak($h); + //Draw the cells of the row + for($i=0;$iwidths[$i]; + $nb1=$this->NbLines($this->widths[$i],$data[$i]); + $a=isset($this->aligns[$i]) ? $this->aligns[$i] : 'L'; + // $h1=isset($this->height[$i]) ? $this->height[$i] :5; + //Save the current position + $x=$this->GetX(); + $y=$this->GetY(); + //Draw the border + $this->Rect($x,$y,$w,$h,$draw); + //Print the text + $this->MultiCell($w,($h/$nb1),$data[$i],$border,$a,$fill); + //Put the position to the right of the cell + $this->SetXY($x+$w,$y); + } + //Go to the next line + $this->Ln($h); + } + + + public function Rowbp($data,$border=0,$fill=0,$draw=0,$besar=10,$padding=0) + { + //Calculate the height of the row + $nb=0; + for($i=0;$iNbLines($this->widths[$i]-($padding*2),$data[$i])); + } + $h=$besar*$nb; + //Issue a page break first if needed + $this->CheckPageBreak($h); + //Draw the cells of the row + for($i=0;$iwidths[$i]-($padding*2); + $nb1=$this->NbLines($this->widths[$i]-($padding*2),$data[$i]); + $a=isset($this->aligns[$i]) ? $this->aligns[$i] : 'L'; + // $h1=isset($this->height[$i]) ? $this->height[$i] :5; + //Save the current position + $xB=$x=$this->GetX(); + $yB=$y=$this->GetY(); + //Draw the border + + if($border) + $this->Rect($x,$y,$w+($padding*2),$h+($padding*2),$draw); + + if($padding > 0) { + // $x+=$padding; + // $y+=$padding; + // $w-=$padding; + // $h-=$padding; + $this->SetXY($x+$padding,$y+$padding); + } + //Print the text + $this->MultiCell($w,$besar,$data[$i],0,$a,$fill); + //Put the position to the right of the cell + $this->SetXY($x+$w+($padding*2),$y); + } + //Go to the next line + $this->Ln($h+($padding*2)); + } + + + public function CheckPageBreak($h) + { + //If the height h would cause an overflow, add a new page immediately + if($this->GetY()+$h>$this->PageBreakTrigger) + $this->AddPage($this->CurOrientation); + } + + public function NbLines($w,$txt) + { + //Computes the number of lines a MultiCell of width w will take + $cw=&$this->CurrentFont['cw']; + if($w==0) + $w=$this->w-$this->rMargin-$this->x; + $wmax=($w-2*$this->cMargin)*1000/$this->FontSize; + $s=str_replace("\r",'',$txt); + $nb=strlen($s); + if($nb>0 and $s[$nb-1]=="\n") + $nb--; + $sep=-1; + $i=0; + $j=0; + $l=0; + $nl=1; + while($i<$nb) + { + $c=$s[$i]; + if($c=="\n") + { + $i++; + $sep=-1; + $j=$i; + $l=0; + $nl++; + continue; + } + if($c==' ') + $sep=$i; + $l+=$cw[$c]; + if($l>$wmax) + { + if($sep==-1) + { + if($i==$j) + $i++; + } + else + $i=$sep+1; + $sep=-1; + $j=$i; + $l=0; + $nl++; + } + else + $i++; + } + return $nl; + } + + public function Header() + { + + } + + public function Footer() { + + } + public function Rotate($angle,$x=-1,$y=-1) + { + if($x==-1) + $x=$this->x; + if($y==-1) + $y=$this->y; + if($this->angle!=0) + $this->_out('Q'); + $this->angle=$angle; + if($angle!=0) + { + $angle*=M_PI/180; + $c=cos($angle); + $s=sin($angle); + $cx=$x*$this->k; + $cy=($this->h-$y)*$this->k; + $this->_out(sprintf('q %.5F %.5F %.5F %.5F %.2F %.2F cm 1 0 0 1 %.2F %.2F cm',$c,$s,-$s,$c,$cx,$cy,-$cx,-$cy)); + } + } + public function _endpage() + { + if($this->angle!=0) + { + $this->angle=0; + $this->_out('Q'); + } + parent::_endpage(); + } + public function RotatedText($x,$y,$txt,$angle) + { + //Text rotated around its origin + $this->Rotate($angle,$x,$y); + $this->Text($x,$y,$txt); + $this->Rotate(0); + } + public function RotatedImage($file,$x,$y,$w,$h,$angle) + { + //Image rotated around its upper-left corner + $this->Rotate($angle,$x,$y); + $this->Image($file,$x,$y,$w,$h); + $this->Rotate(0); + } + + function SetDash($black=false, $white=false) + { + if($black and $white) + $s=sprintf('[%.3f %.3f] 0 d', $black*$this->k, $white*$this->k); + else + $s='[] 0 d'; + + $this->_out($s); + } + + function CustomMultiCell($widthBeforeCell=0, $width, $height, $text, $border=0, $align='L', $fill=0) + { + if($widthBeforeCell<>0){ + $this->cell($widthBeforeCell); + } + $nb1=$this->NbLines($width,$text); + // var_dump($nb1);exit; + $this->MultiCell($width,3,$text,$border,$align,$fill); + } + + /** + * Function to set permissions as well as user and owner passwords + * + * - permissions is an array with values taken from the following list: + * copy, print, modify, annot-forms + * If a value is present it means that the permission is granted + * - If a user password is set, user will be prompted before document is opened + * - If an owner password is set, document can be opened in privilege mode with no + * restriction if that password is entered + */ + function SetProtection($permissions=array(), $user_pass='', $owner_pass=null) + { + $options = array('print' => 4, 'modify' => 8, 'copy' => 16, 'annot-forms' => 32 ); + $protection = 192; + foreach($permissions as $permission) + { + if (!isset($options[$permission])) + $this->Error('Incorrect permission: '.$permission); + $protection += $options[$permission]; + } + if ($owner_pass === null) + $owner_pass = uniqid(rand()); + $this->encrypted = true; + $this->padding = "\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08". + "\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A"; + $this->_generateencryptionkey($user_pass, $owner_pass, $protection); + } + + function CustomMultiCellResultOnb($widthBeforeCell=0, $width, $height, $text, $border=0, $align='L', $fill=0) + { + if($widthBeforeCell<>0){ + $this->cell($widthBeforeCell); + } + $this->MultiCell($width,$height,$text,$border,$align,$fill); + } + +/**************************************************************************** +* * +* Private methods * +* * +****************************************************************************/ + + function _putstream($s) + { + if ($this->encrypted) { + $s = RC4($this->_objectkey($this->n), $s); + } + parent::_putstream($s); + } + + function _textstring($s) + { + if ($this->encrypted) { + $s = RC4($this->_objectkey($this->n), $s); + } + return parent::_textstring($s); + } + + /** + * Compute key depending on object number where the encrypted data is stored + */ + function _objectkey($n) + { + return substr($this->_md5_16($this->encryption_key.pack('VXxx',$n)),0,10); + } + + function _putresources() + { + parent::_putresources(); + if ($this->encrypted) { + $this->_newobj(); + $this->enc_obj_id = $this->n; + $this->_out('<<'); + $this->_putencryption(); + $this->_out('>>'); + $this->_out('endobj'); + } + } + + function _putencryption() + { + $this->_out('/Filter /Standard'); + $this->_out('/V 1'); + $this->_out('/R 2'); + $this->_out('/O ('.$this->_escape($this->Ovalue).')'); + $this->_out('/U ('.$this->_escape($this->Uvalue).')'); + $this->_out('/P '.$this->Pvalue); + } + + function _puttrailer() + { + parent::_puttrailer(); + if ($this->encrypted) { + $this->_out('/Encrypt '.$this->enc_obj_id.' 0 R'); + $this->_out('/ID [()()]'); + } + } + + /** + * Get MD5 as binary string + */ + function _md5_16($string) + { + return pack('H*',md5($string)); + } + + /** + * Compute O value + */ + function _Ovalue($user_pass, $owner_pass) + { + $tmp = $this->_md5_16($owner_pass); + $owner_RC4_key = substr($tmp,0,5); + return RC4($owner_RC4_key, $user_pass); + } + + /** + * Compute U value + */ + function _Uvalue() + { + return RC4($this->encryption_key, $this->padding); + } + + /** + * Compute encryption key + */ + function _generateencryptionkey($user_pass, $owner_pass, $protection) + { + // Pad passwords + $user_pass = substr($user_pass.$this->padding,0,32); + $owner_pass = substr($owner_pass.$this->padding,0,32); + // Compute O value + $this->Ovalue = $this->_Ovalue($user_pass,$owner_pass); + // Compute encyption key + $tmp = $this->_md5_16($user_pass.$this->Ovalue.chr($protection)."\xFF\xFF\xFF"); + $this->encryption_key = substr($tmp,0,5); + // Compute U value + $this->Uvalue = $this->_Uvalue(); + // Compute P value + $this->Pvalue = -(($protection^255)+1); + } + + function WriteTag($w, $h, $txt, $border=0, $align="J", $fill=false, $padding=0) + { + $this->wLine=$w; + $this->hLine=$h; + $this->Text=trim($txt); + $this->Text=preg_replace("/\n|\r|\t/","",$this->Text); + $this->border=$border; + $this->align=$align; + $this->fill=$fill; + $this->Padding=$padding; + + $this->Xini=$this->GetX(); + $this->href=""; + $this->PileStyle=array(); + $this->TagHref=array(); + $this->LastLine=false; + $this->NextLineBegin=array(); + + $this->SetSpace(); + $this->Padding(); + $this->LineLength(); + + $this->BorderTop(); + + while($this->Text!="") + { + $this->MakeLine(); + $this->PrintLine(); + } + + $this->BorderBottom(); + } + + + function SetStyle($tag, $family, $style, $size, $color, $indent=-1) + { + $tag=trim($tag); + $this->TagStyle[$tag]['family']=trim($family); + $this->TagStyle[$tag]['style']=trim($style); + $this->TagStyle[$tag]['size']=trim($size); + $this->TagStyle[$tag]['color']=trim($color); + $this->TagStyle[$tag]['indent']=$indent; + } + + + // Private Functions + + function SetSpace() // Minimal space between words + { + $tag=$this->Parser($this->Text); + $this->FindStyle($tag[2],0); + $this->DoStyle(0); + $this->Space=$this->GetStringWidth(" "); + } + + + function Padding() + { + if(preg_match("/^.+,/",$this->Padding)) { + $tab=explode(",",$this->Padding); + $this->lPadding=$tab[0]; + $this->tPadding=$tab[1]; + if(isset($tab[2])) + $this->bPadding=$tab[2]; + else + $this->bPadding=$this->tPadding; + if(isset($tab[3])) + $this->rPadding=$tab[3]; + else + $this->rPadding=$this->lPadding; + } + else + { + $this->lPadding=$this->Padding; + $this->tPadding=$this->Padding; + $this->bPadding=$this->Padding; + $this->rPadding=$this->Padding; + } + if($this->tPadding<$this->LineWidth) + $this->tPadding=$this->LineWidth; + } + + + function LineLength() + { + if($this->wLine==0) + $this->wLine=$this->w - $this->Xini - $this->rMargin; + + $this->wTextLine = $this->wLine - $this->lPadding - $this->rPadding; + } + + + function BorderTop() + { + $border=0; + if($this->border==1) + $border="TLR"; + else if(!is_numeric($this->border)) { + $border = $this->border; + if(empty($this->border)) { + $border = 0; + } else { + $border = ''; + $border.=strpos($this->border, 'T') !== false ? 'T' : ''; + $border.=strpos($this->border, 'L') !== false ? 'L' : ''; + $border.=strpos($this->border, 'R') !== false ? 'R' : ''; + } + } + + $this->Cell($this->wLine,$this->tPadding,"",$border,0,'C',$this->fill); + $y=$this->GetY()+$this->tPadding; + $this->SetXY($this->Xini,$y); + } + + + function BorderBottom() + { + $border=0; + if($this->border==1) + $border="BLR"; + else if(!is_numeric($this->border)) { + $border = $this->border; + if(empty($this->border)) { + $border = 0; + } else { + $border = ''; + $border.=strpos($this->border, 'B') !== false ? 'B' : ''; + $border.=strpos($this->border, 'L') !== false ? 'L' : ''; + $border.=strpos($this->border, 'R') !== false ? 'R' : ''; + } + } + + $this->Cell($this->wLine,$this->bPadding,"",$border,0,'C',$this->fill); + } + + + function DoStyle($tag) // Applies a style + { + $tag=trim($tag); + $this->SetFont($this->TagStyle[$tag]['family'], + $this->TagStyle[$tag]['style'], + $this->TagStyle[$tag]['size']); + + $tab=explode(",",$this->TagStyle[$tag]['color']); + if(count($tab)==1) + $this->SetTextColor($tab[0]); + else + $this->SetTextColor($tab[0],$tab[1],$tab[2]); + } + + + function FindStyle($tag, $ind) // Inheritance from parent elements + { + $tag=trim($tag); + + // Family + if($this->TagStyle[$tag]['family']!="") + $family=$this->TagStyle[$tag]['family']; + else + { + foreach($this->PileStyle as $val) + { + $val=trim($val); + if($this->TagStyle[$val]['family']!="") { + $family=$this->TagStyle[$val]['family']; + break; + } + } + } + + // Style + $style=""; + $style1=strtoupper($this->TagStyle[$tag]['style']); + if($style1!="N") + { + $bold=false; + $italic=false; + $underline=false; + foreach($this->PileStyle as $val) + { + $val=trim($val); + $style1=strtoupper($this->TagStyle[$val]['style']); + if($style1=="N") + break; + else + { + if(strpos($style1,"B")!==false) + $bold=true; + if(strpos($style1,"I")!==false) + $italic=true; + if(strpos($style1,"U")!==false) + $underline=true; + } + } + if($bold) + $style.="B"; + if($italic) + $style.="I"; + if($underline) + $style.="U"; + } + + // Size + if($this->TagStyle[$tag]['size']!=0) + $size=$this->TagStyle[$tag]['size']; + else + { + foreach($this->PileStyle as $val) + { + $val=trim($val); + if($this->TagStyle[$val]['size']!=0) { + $size=$this->TagStyle[$val]['size']; + break; + } + } + } + + // Color + if($this->TagStyle[$tag]['color']!="") + $color=$this->TagStyle[$tag]['color']; + else + { + foreach($this->PileStyle as $val) + { + $val=trim($val); + if($this->TagStyle[$val]['color']!="") { + $color=$this->TagStyle[$val]['color']; + break; + } + } + } + + // Result + $this->TagStyle[$ind]['family']=$family; + $this->TagStyle[$ind]['style']=$style; + $this->TagStyle[$ind]['size']=$size; + $this->TagStyle[$ind]['color']=$color; + $this->TagStyle[$ind]['indent']=$this->TagStyle[$tag]['indent']; + } + + + function Parser($text) + { + $tab=array(); + // Closing tag + if(preg_match("|^(]+)>)|",$text,$regs)) { + $tab[1]="c"; + $tab[2]=trim($regs[2]); + } + // Opening tag + else if(preg_match("|^(<([^>]+)>)|",$text,$regs)) { + $regs[2]=preg_replace("/^a/","a ",$regs[2]); + $tab[1]="o"; + $tab[2]=trim($regs[2]); + + // Presence of attributes + if(preg_match("/(.+) (.+)='(.+)'/",$regs[2])) { + $tab1=preg_split("/ +/",$regs[2]); + $tab[2]=trim($tab1[0]); + foreach($tab1 as $i=>$couple) + { + if($i>0) { + $tab2=explode("=",$couple); + $tab2[0]=trim($tab2[0]); + $tab2[1]=trim($tab2[1]); + $end=strlen($tab2[1])-2; + $tab[$tab2[0]]=substr($tab2[1],1,$end); + } + } + } + } + // Space + else if(preg_match("/^( )/",$text,$regs)) { + $tab[1]="s"; + $tab[2]=' '; + } + // Text + else if(preg_match("/^([^< ]+)/",$text,$regs)) { + $tab[1]="t"; + $tab[2]=trim($regs[1]); + } + + $begin=strlen($regs[1]); + $end=strlen($text); + $text=substr($text, $begin, $end); + $tab[0]=$text; + + return $tab; + } + + + function MakeLine() + { + $this->Text.=" "; + $this->LineLength=array(); + $this->TagHref=array(); + $Length=0; + $this->nbSpace=0; + + $i=$this->BeginLine(); + $this->TagName=array(); + + if($i==0) { + $Length=$this->StringLength[0]; + $this->TagName[0]=1; + $this->TagHref[0]=$this->href; + } + + while($Length<$this->wTextLine) + { + $tab=$this->Parser($this->Text); + $this->Text=$tab[0]; + if($this->Text=="") { + $this->LastLine=true; + break; + } + + if($tab[1]=="o") { + array_unshift($this->PileStyle,$tab[2]); + $this->FindStyle($this->PileStyle[0],$i+1); + + $this->DoStyle($i+1); + $this->TagName[$i+1]=1; + if($this->TagStyle[$tab[2]]['indent']!=-1) { + $Length+=$this->TagStyle[$tab[2]]['indent']; + $this->Indent=$this->TagStyle[$tab[2]]['indent']; + } + if($tab[2]=="a") + $this->href=$tab['href']; + } + + if($tab[1]=="c") { + array_shift($this->PileStyle); + if(isset($this->PileStyle[0])) + { + $this->FindStyle($this->PileStyle[0],$i+1); + $this->DoStyle($i+1); + } + $this->TagName[$i+1]=1; + if($this->TagStyle[$tab[2]]['indent']!=-1) { + $this->LastLine=true; + $this->Text=trim($this->Text); + break; + } + if($tab[2]=="a") + $this->href=""; + } + + if($tab[1]=="s") { + $i++; + $Length+=$this->Space; + $this->Line2Print[$i]=""; + if($this->href!="") + $this->TagHref[$i]=$this->href; + } + + if($tab[1]=="t") { + $i++; + $this->StringLength[$i]=$this->GetStringWidth($tab[2]); + $Length+=$this->StringLength[$i]; + $this->LineLength[$i]=$Length; + $this->Line2Print[$i]=$tab[2]; + if($this->href!="") + $this->TagHref[$i]=$this->href; + } + + } + + trim($this->Text); + if($Length>$this->wTextLine || $this->LastLine==true) + $this->EndLine(); + } + + + function BeginLine() + { + $this->Line2Print=array(); + $this->StringLength=array(); + + if(isset($this->PileStyle[0])) + { + $this->FindStyle($this->PileStyle[0],0); + $this->DoStyle(0); + } + + if(count($this->NextLineBegin)>0) { + $this->Line2Print[0]=$this->NextLineBegin['text']; + $this->StringLength[0]=$this->NextLineBegin['length']; + $this->NextLineBegin=array(); + $i=0; + } + else { + preg_match("/^(( *(<([^>]+)>)* *)*)(.*)/",$this->Text,$regs); + $regs[1]=str_replace(" ", "", $regs[1]); + $this->Text=$regs[1].$regs[5]; + $i=-1; + } + + return $i; + } + + + function EndLine() + { + if(end($this->Line2Print)!="" && $this->LastLine==false) { + $this->NextLineBegin['text']=array_pop($this->Line2Print); + $this->NextLineBegin['length']=end($this->StringLength); + array_pop($this->LineLength); + } + + while(end($this->Line2Print)==="") + array_pop($this->Line2Print); + + $this->Delta=$this->wTextLine-end($this->LineLength); + + $this->nbSpace=0; + for($i=0; $iLine2Print); $i++) { + if($this->Line2Print[$i]=="") + $this->nbSpace++; + } + } + + + function PrintLine() + { + $border=0; + if($this->border==1) + $border="LR"; + else if(!is_numeric($this->border)) { + $border = $this->border; + if(empty($this->border)) { + $border = 0; + } else { + $border = ''; + $border.=strpos($this->border, 'L') !== false ? 'L' : ''; + $border.=strpos($this->border, 'R') !== false ? 'R' : ''; + } + } + $this->Cell($this->wLine,$this->hLine,"",$border,0,'C',$this->fill); + $y=$this->GetY(); + $this->SetXY($this->Xini+$this->lPadding,$y); + + if($this->Indent!=-1) { + if($this->Indent!=0) + $this->Cell($this->Indent,$this->hLine); + $this->Indent=-1; + } + + $space=$this->LineAlign(); + $this->DoStyle(0); + for($i=0; $iLine2Print); $i++) + { + if(isset($this->TagName[$i])) + $this->DoStyle($i); + if(isset($this->TagHref[$i])) + $href=$this->TagHref[$i]; + else + $href=''; + if($this->Line2Print[$i]=="") + $this->Cell($space,$this->hLine," ",0,0,'C',false,$href); + else + $this->Cell($this->StringLength[$i],$this->hLine,$this->Line2Print[$i],0,0,'C',false,$href); + } + + $this->LineBreak(); + if($this->LastLine && $this->Text!="") + $this->EndParagraph(); + $this->LastLine=false; + } + + + function LineAlign() + { + $space=$this->Space; + if($this->align=="J") { + if($this->nbSpace!=0) + $space=$this->Space + ($this->Delta/$this->nbSpace); + if($this->LastLine) + $space=$this->Space; + } + + if($this->align=="R") + $this->Cell($this->Delta,$this->hLine); + + if($this->align=="C") + $this->Cell($this->Delta/2,$this->hLine); + + return $space; + } + + + function LineBreak() + { + $x=$this->Xini; + $y=$this->GetY()+$this->hLine; + $this->SetXY($x,$y); + } + + + function EndParagraph() + { + $border=0; + if($this->border==1) + $border="LR"; + $this->Cell($this->wLine,$this->hLine/2,"",$border,0,'C',$this->fill); + $x=$this->Xini; + $y=$this->GetY()+$this->hLine/2; + $this->SetXY($x,$y); + } + + //Cell with horizontal scaling if text is too wide + function CellFit($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='', $scale=false, $force=true) + { + //Get string width + $str_width=$this->GetStringWidth($txt); + + //Calculate ratio to fit cell + if($w==0) + $w = $this->w-$this->rMargin-$this->x; + $ratio = ($w-$this->cMargin*2)/$str_width; + + $fit = ($ratio < 1 || ($ratio > 1 && $force)); + if ($fit) + { + if ($scale) + { + //Calculate horizontal scaling + $horiz_scale=$ratio*100.0; + //Set horizontal scaling + $this->_out(sprintf('BT %.2F Tz ET',$horiz_scale)); + } + else + { + //Calculate character spacing in points + $char_space=($w-$this->cMargin*2-$str_width)/max(strlen($txt)-1,1)*$this->k; + //Set character spacing + $this->_out(sprintf('BT %.2F Tc ET',$char_space)); + } + //Override user alignment (since text will fill up cell) + $align=''; + } + + //Pass on to Cell method + $this->Cell($w,$h,$txt,$border,$ln,$align,$fill,$link); + + //Reset character spacing/horizontal scaling + if ($fit) + $this->_out('BT '.($scale ? '100 Tz' : '0 Tc').' ET'); + } + + //Cell with character spacing only if necessary + function CellFitSpace($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='') + { + $this->CellFit($w,$h,$txt,$border,$ln,$align,$fill,$link,false,false); + } + + public function RowForDownloadAttendance($data,$border=0,$fill=0,$draw=0) + { + //Calculate the height of the row + $nb=0; + for($i=0;$iNbLines($this->widths[$i],$data[$i])); + } + + $h=4*$nb; + //Issue a page break first if needed + $this->CheckPageBreak($h); + //Draw the cells of the row + for($i=0;$iwidths[$i]; + $nb1=$this->NbLines($this->widths[$i],$data[$i]); + $a=isset($this->aligns[$i]) ? $this->aligns[$i] : 'L'; + + //Save the current position + $x=$this->GetX(); + $y=$this->GetY(); + + //Draw the border + $this->Rect($x,$y,$w,$h,$draw); + $this->SetTextColor(0, 0, 0); + + $tempNote = explode(' ',$data[$i]); + if($data[$i]=='Missing'|| $data[$i]=='Missing Finger In' || $data[$i]=='AWN' || $data[$i]=='Late In' || $data[$i]=='time in not in range shift !!' || $data[$i]=='Missing Finger Out' || $data[$i]=='Early Out' || $data[$i]=='Late In Early Out' || $tempNote[0]=='Undisciplined'){ + // $this->SetTextColor(81, 156, 132); + $this->SetTextColor(255, 48, 33); + } + if($i==3&& $data[9]=='Late In'){ + $this->SetTextColor(255, 48, 33); + } + if($i==6&& $data[9]=='Early Out'){ + $this->SetTextColor(255, 48, 33); + } + + if(($i==3||$i==6)&& $data[9]=='Late In Early Out'){ + $this->SetTextColor(255, 48, 33); + } + //Print the text + $this->MultiCell($w,($h/$nb1),$data[$i],$border,$a,$fill); + + //Put the position to the right of the cell + $this->SetXY($x+$w,$y); + } + + //Go to the next line + $this->Ln($h); + } + + function drawTextBox($strText, $w, $h, $align='L', $valign='T', $border=true, $withLine = false) { + $xi=$this->GetX(); + $yi=$this->GetY(); + + $hrow=$this->FontSize; + $textrows=$this->drawRows($w,$hrow,$strText,0,$align,0,0,0); + $maxrows=floor($h/$this->FontSize); + $rows=min($textrows,$maxrows); + + $dy=0; + if (strtoupper($valign)=='M') + $dy=($h-$rows*$this->FontSize)/2; + if (strtoupper($valign)=='B') + $dy=$h-$rows*$this->FontSize; + + $this->SetY($yi+$dy); + $this->SetX($xi); + + $this->drawRows($w,$hrow,$strText,0,$align,false,$rows,1); + + if ($border) + $this->Rect($xi,$yi,$w,$h); + } + + function drawRows($w, $h, $txt, $border=0, $align='J', $fill=false, $maxline=0, $prn=0) + { + if(!isset($this->CurrentFont)) + $this->Error('No font has been set'); + $cw=$this->CurrentFont['cw']; + if($w==0) + $w=$this->w-$this->rMargin-$this->x; + $wmax=($w-2*$this->cMargin)*1000/$this->FontSize; + $s=str_replace("\r",'',(string)$txt); + $nb=strlen($s); + if($nb>0 && $s[$nb-1]=="\n") + $nb--; + $b=0; + if($border) + { + if($border==1) + { + $border='LTRB'; + $b='LRT'; + $b2='LR'; + } + else + { + $b2=''; + if(is_int(strpos($border,'L'))) + $b2.='L'; + if(is_int(strpos($border,'R'))) + $b2.='R'; + $b=is_int(strpos($border,'T')) ? $b2.'T' : $b2; + } + } + $sep=-1; + $i=0; + $j=0; + $l=0; + $ns=0; + $nl=1; + while($i<$nb) + { + //Get next character + $c=$s[$i]; + if($c=="\n") + { + //Explicit line break + if($this->ws>0) + { + $this->ws=0; + if ($prn==1) $this->_out('0 Tw'); + } + if ($prn==1) { + $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill); + } + $i++; + $sep=-1; + $j=$i; + $l=0; + $ns=0; + $nl++; + if($border && $nl==2) + $b=$b2; + if ( $maxline && $nl > $maxline ) + return substr($s,$i); + continue; + } + if($c==' ') + { + $sep=$i; + $ls=$l; + $ns++; + } + $l+=$cw[$c]; + if($l>$wmax) + { + //Automatic line break + if($sep==-1) + { + if($i==$j) + $i++; + if($this->ws>0) + { + $this->ws=0; + if ($prn==1) $this->_out('0 Tw'); + } + if ($prn==1) { + $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill); + } + } + else + { + if($align=='J') + { + $this->ws=($ns>1) ? ($wmax-$ls)/1000*$this->FontSize/($ns-1) : 0; + if ($prn==1) $this->_out(sprintf('%.3F Tw',$this->ws*$this->k)); + } + if ($prn==1){ + $this->Cell($w,$h,substr($s,$j,$sep-$j),$b,2,$align,$fill); + } + $i=$sep+1; + } + $sep=-1; + $j=$i; + $l=0; + $ns=0; + $nl++; + if($border && $nl==2) + $b=$b2; + if ( $maxline && $nl > $maxline ) + return substr($s,$i); + } + else + $i++; + } + //Last chunk + if($this->ws>0) + { + $this->ws=0; + if ($prn==1) $this->_out('0 Tw'); + } + if($border && is_int(strpos($border,'B'))) + $b.='B'; + if ($prn==1) { + $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill); + } + $this->x=$this->lMargin; + return $nl; + } +} + +// if(function_exists('mcrypt_encrypt')) +// { +// function RC4($key, $data) +// { +// return mcrypt_encrypt(MCRYPT_ARCFOUR, $key, $data, MCRYPT_MODE_STREAM, ''); +// } +// } +// else +// { + function RC4($key, $data) + { + static $last_key, $last_state; + + if($key != $last_key) + { + $k = str_repeat($key, 256/strlen($key)+1); + $state = range(0, 255); + $j = 0; + for ($i=0; $i<256; $i++){ + $t = $state[$i]; + $j = ($j + $t + ord($k[$i])) % 256; + $state[$i] = $state[$j]; + $state[$j] = $t; + } + $last_key = $key; + $last_state = $state; + } + else + $state = $last_state; + + $len = strlen($data); + $a = 0; + $b = 0; + $out = ''; + for ($i=0; $i<$len; $i++){ + $a = ($a+1) % 256; + $t = $state[$a]; + $b = ($b+$t) % 256; + $state[$a] = $state[$b]; + $state[$b] = $t; + $k = $state[($state[$a]+$state[$b]) % 256]; + $out .= chr(ord($data[$i]) ^ $k); + } + return $out; + } +// } diff --git a/Aiko/Libs/MyPdf.php:Zone.Identifier b/Aiko/Libs/MyPdf.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Libs/MyPdf.php:Zone.Identifier:Zone.Identifier b/Aiko/Libs/MyPdf.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/MyPdf.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/Mycrypt.php b/Aiko/Libs/Mycrypt.php new file mode 100644 index 0000000..937f824 --- /dev/null +++ b/Aiko/Libs/Mycrypt.php @@ -0,0 +1,35 @@ + \ No newline at end of file diff --git a/Aiko/Libs/Mycrypt.php:Zone.Identifier b/Aiko/Libs/Mycrypt.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Libs/Mycrypt.php:Zone.Identifier:Zone.Identifier b/Aiko/Libs/Mycrypt.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/Mycrypt.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/Query.php b/Aiko/Libs/Query.php new file mode 100644 index 0000000..2e7f793 --- /dev/null +++ b/Aiko/Libs/Query.php @@ -0,0 +1,35 @@ +debug_mode=$debug_mode; + $this->query=$query; + $this->registry=$registry; + } + public function getData($param=array()) + { + try{ + + } catch (PDOException $e) + { + if($this->debug_mode) + { + return $e->getMessage(); + }else + { + return FALSE; + } + + } + + + $this->param=$param; + $obj = new processdata(); + return $obj; + } +} \ No newline at end of file diff --git a/Aiko/Libs/Query.php:Zone.Identifier b/Aiko/Libs/Query.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Libs/Query.php:Zone.Identifier:Zone.Identifier b/Aiko/Libs/Query.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/Query.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/QueryParam.php b/Aiko/Libs/QueryParam.php new file mode 100644 index 0000000..177dfbf --- /dev/null +++ b/Aiko/Libs/QueryParam.php @@ -0,0 +1,41 @@ +dataType=$dataType; + return $this; + } + public function query($query) + { + $this->query=$query; + return $this; + } + public function data($data) + { + $this->data=$data; + return $this; + } + public function placeHolder($placeHolder) + { + $this->placeHolder=$placeHolder; + return $this; + } + public function getDataType() + { + return $this->dataType; + } + public function getData() + { + return $this->data; + } + public function getPlaceHolder() + { + return $this->placeHolder; + } +} \ No newline at end of file diff --git a/Aiko/Libs/QueryParam.php:Zone.Identifier b/Aiko/Libs/QueryParam.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Libs/QueryParam.php:Zone.Identifier:Zone.Identifier b/Aiko/Libs/QueryParam.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/QueryParam.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/QueryProcess.php b/Aiko/Libs/QueryProcess.php new file mode 100644 index 0000000..bcbf346 --- /dev/null +++ b/Aiko/Libs/QueryProcess.php @@ -0,0 +1,24 @@ +lifeTime = get_cfg_var("session.gc_maxlifetime"); + // open database-connection + return true; + } + function close() { + $this->gc(ini_get('session.gc_maxlifetime')); + + } + function read($sessID) { + // fetch session-data + try { + $this->registry->log->error('read :'.$sessID.' :'); + // var_dump($sessID); + $query="SELECT session_data AS d FROM ws_sessions WHERE session_id = '$sessID' AND session_expires > ".time(); + $stmt=$this->registry->db->prepare($query); + $stmt->execute(); + $rs=$stmt->fetchAll(PDO::FETCH_ASSOC); + return (count($rs)>0)?$rs[0]['d']:''; + } catch (PDOException $e) { + + $this->registry->log->error('module session/read :'.$e->getMessage()); + return ''; + } + } + function write($sessID,$sessData) { + // new session-expire-time + + $this->registry->log->error('write :'.$sessID.' :'.$sessData); + $newExp = time() + $this->lifeTime; + // is a session with this id in the database? + $fd=0; + try { + $sql="SELECT count(0) as found FROM ws_sessions + WHERE session_id =:sessionID"; + $stmt=$this->registry->db->prepare($sql); + $stmt->bindValue(':sessionID',$sessID,PDO::PARAM_STR); + $stmt->execute(); + $rs=$stmt->fetchAll(PDO::FETCH_ASSOC); + $fd=$rs[0]['found']; + } catch (PDOException $e) { + $fd=0; + $this->registry->log->error('module session /write :'.$e->getMessage()); + } + + + if($fd>0) + { + if(!empty($sessData)){ + try { + $sql="UPDATE ws_sessions + SET session_expires =:sessionExpired, + session_data =:sessionData + WHERE session_id =:sessionID"; + + $stmt=$this->registry->db->prepare($sql); + $stmt->bindValue(':sessionID',$sessID,PDO::PARAM_STR); + $stmt->bindValue(':sessionExpired',$newExp,PDO::PARAM_INT); + $stmt->bindValue(':sessionData',$sessData,PDO::PARAM_STR); + $stmt->execute(); + $resUpdate=true; + } catch (PDOException $e) { + $this->registry->log->error('module session /write :'.$e->getMessage()); + $resUpdate=false; + } + return $resUpdate; + }else + { + try { + $sql="delete from ws_sessions WHERE session_id =:sessionID"; + $stmt=$this->registry->db->prepare($sql); + $stmt->bindValue(':sessionID',$sessID,PDO::PARAM_STR); + $stmt->execute(); + $resultDelete=true; + } catch (PDOException $e) { + $this->registry->log->error('module session /write :'.$e->getMessage()); + $resultDelete=false; + } + + return $resultDelete; + } + }else + { + $resultInsert=false; + + if(!empty($sessData)){ + try { + $sql="INSERT INTO ws_sessions ( + session_id, + session_expires, + session_data) + VALUES( + :sessionID, + :sessionExpired, + :sessionData)"; + $stmt=$this->registry->db->prepare($sql); + $stmt->bindValue(':sessionID',$sessID,PDO::PARAM_STR); + $stmt->bindValue(':sessionExpired',$newExp,PDO::PARAM_INT); + $stmt->bindValue(':sessionData',$sessData,PDO::PARAM_STR); + $stmt->execute(); + $resultInsert=true; + } catch (PDOException $e) { + $this->registry->log->error('module session /write :'.$e->getMessage()); + $resultInsert=false; + } + + } + return $resultInsert; + } + + + return false; + } + function destroy($sessID) { + + try { + + $sql="DELETE FROM ws_sessions WHERE session_id = '$sessID'"; + $stmt=$this->registry->db->prepare($sql); + $stmt->execute(); + + return true; + } catch (PDOException $exc) { + $this->registry->log->error('module session /write :'.$e->getMessage()); + return false; + } + } + function gc($sessMaxLifeTime) { + + + try{ + + + /** + * sql dibawah ini digunakan untuk ambil session id yang sudah expired dan update data user session nya jika menggunakan sesion user + */ + $sql="select session_id from ws_sessions WHERE session_expires < ".time(); + $stmt=$this->registry->db->prepare($sql); + $stmt->execute(); + $rs=$stmt->fetchAll(PDO::FETCH_ASSOC); + + + $sql="DELETE FROM ws_sessions WHERE session_expires < ".time(); + $stmt=$this->registry->db->prepare($sql); + $stmt->execute(); + return true; + } catch (PDOException $e) + { + $this->registry->log->error('module session /write :'.$e->getMessage()); + return false; + } + + + } +} + + +?> diff --git a/Aiko/Libs/Session.php:Zone.Identifier b/Aiko/Libs/Session.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Libs/Session.php:Zone.Identifier:Zone.Identifier b/Aiko/Libs/Session.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/Session.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/Storage.php b/Aiko/Libs/Storage.php new file mode 100644 index 0000000..4fe5336 --- /dev/null +++ b/Aiko/Libs/Storage.php @@ -0,0 +1,140 @@ +registry = $registry; + $this->isProduction = $this->registry->config->environment === 'production'; + $this->baseStorage = $this->isProduction ? $this->registry->config->base_storage : __SITE_PATH . '/hcportal_docs/'; + } + + public function fromException($e, $action) + { + return Helper::handleException($this->registry, $e, "storage", $action, false, "Storage"); + } + + /** @param UploadedFile $file */ + public function validateFile($file, $maxSize = 2048, $allowedMime = []) + { + if ($file instanceof UploadedFile) { + $mime = $file->getMimeType(); + if (in_array($mime, $allowedMime)) return true; + return false; + } + return false; + } + + // + // + // @param $options = [ + // 'mime' => [], + // 'size' => 0 + // ] + public function store($file, $folderName = 'temp', $prefix = '', $options = []) + { + try { + $storage = $this->trimSlashes($this->baseStorage . '/' . $folderName . '/'); + $default = $this->generateFilename($file); + $filename = $default; + if ($prefix) { + $filename = $prefix . '_' . $default; + } + $file->move($storage, $filename); + return $filename; + } catch (FileException $e) { + return $this->fromException($e, "store"); + } catch (ErrorException $e) { + return $this->fromException($e, "store"); + } + } + + public function delete($filename, $folderName = 'temp') + { + try { + $link = $this->trimSlashes($this->baseStorage . '/' . $folderName . '/' . $filename); + if (file_exists($link)) { + if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { + $fileTmp = $link; + $fileTmp = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR, $fileTmp); + @unlink($fileTmp); + } else { + unlink($link); + } + } + return true; + } catch (Exception $e) { + return $this->fromException($e, "delete"); + } + } + + public function exists($filename, $folderName = 'temp') + { + $link = $this->trimSlashes($this->baseStorage . '/' . $folderName . '/' . $filename); + return file_exists($link); + } + + public function url($filename, $path = 'temp', $isLocal = false) + { + if (!$filename) { + return null; + } + $filePath = $this->trimSlashes('hcportal_docs/' . $path . '/' . $filename); + $prefix = $this->registry->config->server_address; + if($isLocal){ + $prefix = __SITE_PATH.'/'; + } + return $prefix . $filePath; + } + + public function generateFilename($file) + { + $time = time(); + $filename = uniqid() . '_' . $time . '.' . $file->guessExtension(); + return $filename; + } + + public function isValidImage($mimeType) + { + return $this->validateMime($mimeType, [ + 'image/jpeg', + 'image/png', + 'image/jpg' + ]); + return true; + } + + public function isValidDocument($mimeType) + { + return $this->validateMime($mimeType, [ + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'application/vnd.ms-excel', + 'application/pdf' + ]); + } + + private function validateMime($mimeType, $mimeClientAlowed) + { + if (!in_array($mimeType, $mimeClientAlowed)) { + return false; + } + return true; + } + + private function trimSlashes($str) + { + return preg_replace('/(\/+)/', '/', $str); + } +} diff --git a/Aiko/Libs/Storage.php:Zone.Identifier b/Aiko/Libs/Storage.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Libs/Storage.php:Zone.Identifier:Zone.Identifier b/Aiko/Libs/Storage.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/Storage.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/Token.php b/Aiko/Libs/Token.php new file mode 100644 index 0000000..4c3ebbe --- /dev/null +++ b/Aiko/Libs/Token.php @@ -0,0 +1,349 @@ +get_token_from_session('token'); + // var_dump($sessiontoken); + // exit(); + + + $valid = strlen($sessiontoken) == 128 && strlen($token) == 128 && $sessiontoken == $token; + + $this->get_token($area); // refresh token + + return $valid; + } + public function get_token_from_url() + { + $token = isset($_GET['token']) ? $_GET['token'] : ''; + + return $token; + } + + public function get_token_from_session($key) + { + $token = isset($_SESSION[$key]) ? $_SESSION[$key] : ''; + + return $token; + } + public function getTokenAuthUser() + { + $token = hash('sha512', mt_rand(0, mt_getrandmax()) . microtime(true)); + $_SESSION['tokenAuth'] = $token; + + return $token; + } + public function check_tokenAuthUser($token) + { + $sessiontoken = $this->get_token_from_session('tokenAuth'); + $valid = strlen($sessiontoken) == 128 && strlen($token) == 128 && $sessiontoken == $token; + if ($valid) { + return true; + } else { + return false; + } + } + + public function set_cookie() + { + $result = password_hash('4pl1k4s1D1sd1K', PASSWORD_DEFAULT, array('cost' => 10)); + // $res = setcookie('XSRF-TOKEN', $result, time() + 86400, $_SERVER['REQUEST_URI'],'',false,false); + + $res = setcookie('XSRF-TOKEN', $result, time() + 86400, '/'); + if ($res) { + return true; + } else { + return false; + } + } + public function cek_cookie($clientCookie) + { + $result = false; + if (isset($_COOKIE['XSRF-TOKEN'])) { + $serverCookie = $_COOKIE['XSRF-TOKEN']; + $result = $this->cek_hash($clientCookie, $serverCookie); + } + + return $result; + } + + private function cek_hash($clientCookie, $serverCookie) + { + if ($clientCookie == $serverCookie) { + return $this->set_cookie(); + } else { + return false; + } + } + + private static function wrapToken($jwt, $chipper) + { + try { + if (strlen($chipper) <> 6) { + throw new \ErrorException('chipper failed'); + } + $headerPreffix = (int) substr($chipper, 0, 1); + $headerSuffix = (int) substr($chipper, 1, 1); + $payloadPreffix = (int) substr($chipper, 2, 1); + $payloadSuffix = (int) substr($chipper, 3, 1); + $signPreffix = (int) substr($chipper, 4, 1); + $signSuffix = (int) substr($chipper, 5, 1); + + $jwtPart = explode('.', $jwt); + + $newJwt = self::randomChars($headerPreffix) . $jwtPart[0] . self::randomChars($headerSuffix); + + $newJwt .= '.' . self::randomChars($payloadPreffix) . $jwtPart[1] . self::randomChars($payloadSuffix); + + $newJwt .= '.' . self::randomChars($signPreffix) . $jwtPart[2] . self::randomChars($signSuffix); + + return $newJwt; + } catch (\Exception $e) { + return false; + } + } + + private static function unWrapToken($jwt, $chipper) + { + try { + if (strlen($chipper) <> 6) { + throw new \ErrorException('chipper failed'); + } + + $headerPreffix = (int) substr($chipper, 0, 1); + $headerSuffix = (int) substr($chipper, 1, 1); + $payloadPreffix = (int) substr($chipper, 2, 1); + $payloadSuffix = (int) substr($chipper, 3, 1); + $signPreffix = (int) substr($chipper, 4, 1); + $signSuffix = (int) substr($chipper, 5, 1); + + $jwtPart = explode('.', $jwt); + + $newString = self::removePreSuf($jwtPart[0], $headerPreffix, $headerSuffix); + if ($newString == false) { + throw new \ErrorException('failed clean wrapper header'); + } + $header = $newString; + + $newString = self::removePreSuf($jwtPart[1], $payloadPreffix, $payloadSuffix); + if ($newString == false) { + throw new \ErrorException('failed clean wrapper payload'); + } + $payload = $newString; + + $newString = self::removePreSuf($jwtPart[2], $signPreffix, $signSuffix); + if ($newString == false) { + throw new \ErrorException('failed clean wrapper sign'); + } + $sign = $newString; + + return $header . '.' . $payload . '.' . $sign; + } catch (\ErrorException $e) { + return false; + } + } + + private static function removePreSuf($string, $preffix, $suffix) + { + $jum = strlen(trim($string)); + $totWrapper = ($preffix + $suffix); + $tot = $totWrapper + 10; // set minimum text + if ($jum > $tot) { + $total = $jum - $totWrapper; + $newString = substr($string, $preffix, $total); + return $newString; + } + + return false; + } + + private static function randomChars($numChars) + { + $str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuzwxyz'; + return substr(str_shuffle($str), 0, $numChars); + } + + public static function encodeJWT($serverName, $dataUser, $chipper = '000000') + { + + try { + + $log = new Log('1'); + // $publicKey = file_get_contents('/Users/suhendra/mykey/suhendra_rsa.pub'); + + $privateKey = file_get_contents(__SITE_PATH . '/mykey/hcportalprivate.pem'); + + // $privateKey = openssl_get_privatekey('file:///Users/suhendra/mykey/suhendra_rsa','suh3ndr4'); + // var_dump($privateKey); + + //$tokenId = base64_encode(\mcrypt_create_iv(32)); + $tokenId = base64_encode(\openssl_random_pseudo_bytes(64)); + // $random = mt_rand(0, 999999); + // $random_string = sha1($random); + //$tokenId = base64_encode(date('Y-m-d H:i:s')); + $issuedAt = time(); + $notBefore = time(); + $expire = $notBefore + __LIFETIMEJWT; // Adding 10 menit + + /* + * Create the token as an array + */ + $data = [ + 'iat' => $issuedAt, // Issued at: time when the token was generated + 'jti' => $tokenId, // Json Token Id: an unique identifier for the token / A unique string, could be used to validate a token, but goes against not having a centralized issuer authority. + 'iss' => $serverName, // A string containing the name or identifier of the issuer application. Can be a domain name and can be used to discard tokens from other applications. + 'nbf' => $notBefore, // Timestamp of when the token should start being considered valid. Should be equal to or greater than iat. In this case, the token will begin to be valid 10 seconds + 'exp' => $expire, // Timestamp of when the token should cease to be valid. Should be greater than iat and nbf. In this case, the token will expire 60 seconds after being issued. + 'data' => $dataUser, + ]; + + $jwt = JWT::encode( + $data, //Data to be encoded in the JWT + $privateKey, // The signing key + 'RS256' // Algorithm used to sign the token, see https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40#section-3 + ); + + // var_dump($jwt); + + $newJwt = self::wrapToken($jwt, $chipper); + // var_dump($newJwt); + + if ($newJwt == false) { + throw new \ErrorException('Failed wrap Token'); + } + + $dataUser['expired'] = $expire; + $dataHeader = array( + 'jwt' => $newJwt, + 'tokenID' => $tokenId, + 'appID' => $serverName, + 'data' => $dataUser, + 'expired' => $expire + ); + + return $dataHeader; + } catch (\ErrorException $e) { + $log->error('encode token token/decodeJWT' . $e->getMessage()); + return false; + } + } + + public static function decodeJWT($jwt, $chipper = '000000') + { + try { + $log = new Log('1'); + + $publicKey = file_get_contents(__SITE_PATH . '/mykey/hcportalpublic.pem'); + + $newJwt = self::unWrapToken($jwt, $chipper); + + $token = JWT::decode($newJwt, $publicKey, array('RS256')); + + return $token; + } catch (\DomainException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\InvalidArgumentException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\UnexpectedValueException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\DateTime $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\SignatureInvalidException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\BeforeValidException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\Firebase\JWT\ExpiredException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } + } + + public static function decodeJWTNew($jwt, $chipper = '000000') + { + try { + $log = new Log('1'); + + $publicKey = file_get_contents(__SITE_PATH . '/mykey/hcportalpublic.pem'); + + $newJwt = self::unWrapToken($jwt, $chipper); + + $token = JWT::decode($newJwt, $publicKey, array('RS256')); + return $token; + } catch (\DomainException $e) { + $log->error('decode token token/decodeJWT 2 ' . $e->getMessage() . 'JWT |' . $jwt); + return 2; + } catch (\InvalidArgumentException $e) { + $log->error('decode token token/decodeJWT 3' . $e->getMessage() . 'JWT |' . $jwt); + return 3; + } catch (\UnexpectedValueException $e) { + $log->error('decode token token/decodeJWT 4' . $e->getMessage() . 'JWT |' . $jwt); + if ($e->getMessage() == 'Expired token') { + return 8; + } + return 4; + } catch (\DateTime $e) { + $log->error('decode token token/decodeJWT 5' . $e->getMessage() . 'JWT |' . $jwt); + return 5; + } catch (\SignatureInvalidException $e) { + $log->error('decode token token/decodeJWT 6' . $e->getMessage() . 'JWT |' . $jwt); + return 6; + } catch (\BeforeValidException $e) { + $log->error('decode token token/decodeJWT 7' . $e->getMessage() . 'JWT |' . $jwt); + return 7; + } catch (\Firebase\JWT\ExpiredException $e) { + $log->error('decode token token/decodeJWT 8' . $e->getMessage() . 'JWT |' . $jwt); + return 8; + } + } + + public static function decodePlainJWT($jwt, $key = null) + { + try { + $log = new Log('1'); + + $token = JWT::decode($jwt, $key, array('HS256')); + + return $token; + } catch (\DomainException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\InvalidArgumentException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\UnexpectedValueException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\Firebase\JWT\SignatureInvalidException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\Firebase\JWT\BeforeValidException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } catch (\Firebase\JWT\ExpiredException $e) { + $log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt); + return false; + } + } +} diff --git a/Aiko/Libs/Token.php:Zone.Identifier b/Aiko/Libs/Token.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Libs/Token.php:Zone.Identifier:Zone.Identifier b/Aiko/Libs/Token.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/Token.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/TokenSanitation.php b/Aiko/Libs/TokenSanitation.php new file mode 100644 index 0000000..376a270 --- /dev/null +++ b/Aiko/Libs/TokenSanitation.php @@ -0,0 +1,87 @@ +token=$this->unWrapToken($jwt,$clientChipper); + } + + public function getToken(){ + return $this->token; + } + + public function getErros(){ + return $this->errors; + } + + private function unWrapToken($jwt, $chipper) + { + try { + if (strlen($chipper) <> 6) { + throw new \ErrorException('chipper failed'); + } + + $headerPreffix = (int) substr($chipper, 0, 1); + $headerSuffix = (int) substr($chipper, 1, 1); + $payloadPreffix = (int) substr($chipper, 2, 1); + $payloadSuffix = (int) substr($chipper, 3, 1); + $signPreffix = (int) substr($chipper, 4, 1); + $signSuffix = (int) substr($chipper, 5, 1); + + $jwtPart = explode('.', $jwt); + + + + if (count($jwtPart) != 4) { + throw new \ErrorException('token part invalid'); + } + + + $newString = $this->removePreSuf($jwtPart[0], $headerPreffix, $headerSuffix); + if ($newString == false) { + throw new \ErrorException('failed clean wrapper header'); + } + $header = $newString; + + $newString = $this->removePreSuf($jwtPart[1], $payloadPreffix, $payloadSuffix); + if ($newString == false) { + throw new \ErrorException('failed clean wrapper payload'); + } + $payload = $newString; + + $newString = $this->removePreSuf($jwtPart[2], $signPreffix, $signSuffix); + if ($newString == false) { + throw new \ErrorException('failed clean wrapper sign'); + } + $sign = $newString; + + return $header . '.' . $payload . '.' . $sign; + } catch (\ErrorException $e) { + array_push($this->errors,array($e->getMessage())); + return false; + } + } + + private function removePreSuf($string, $preffix, $suffix) + { + $jum = strlen(trim($string)); + $totWrapper = ($preffix + $suffix); + $tot = $totWrapper + 10; // set minimum text + if ($jum > $tot) { + $total = $jum - $totWrapper; + $newString = substr($string, $preffix, $total); + return $newString; + } + + return false; + } + + +} diff --git a/Aiko/Libs/TokenSanitation.php:Zone.Identifier b/Aiko/Libs/TokenSanitation.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Libs/TokenSanitation.php:Zone.Identifier:Zone.Identifier b/Aiko/Libs/TokenSanitation.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/TokenSanitation.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/Trait.php b/Aiko/Libs/Trait.php new file mode 100644 index 0000000..80b2272 --- /dev/null +++ b/Aiko/Libs/Trait.php @@ -0,0 +1,50 @@ +db->beginTransaction(); + + // drop tmp table + $sqlDropExist = "DROP TEMPORARY TABLE IF EXISTS $tblname"; + $stmtDropExist=$this->registry->db->prepare($sqlDropExist); + $stmtDropExist->execute(); + + // create table + $sqlCreate='CREATE TEMPORARY TABLE '.$tblname. ' ( '; + $sqlCreate .=$fields[0]['field'].' '.$fields[0]['type'].'('.$fields[0]['length'].')'; + $jum=count($fields); + for ($i = 1; $i < $jum; $i++) { + $sqlCreate .=' , '.$fields[$i]['field'].' '.$fields[$i]['type'].'('.$fields[$i]['length'].')'; + } + + + $sqlCreate .=')'; + + var_dump($sqlCreate); + + $registry->db->commit(); + + return true; + } catch (PDOException $e) { + $registry->db->rollBack(); + $this->registry->log->error('Main trait in lib /saveToTmpTable :'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + + return false; + } catch (ErrorException $e) { + $registry->db->rollBack(); + $this->registry->log->error('Main trait in lib /saveToTmpTable :'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + + return false; + } + } +} \ No newline at end of file diff --git a/Aiko/Libs/Trait.php:Zone.Identifier b/Aiko/Libs/Trait.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Libs/Trait.php:Zone.Identifier:Zone.Identifier b/Aiko/Libs/Trait.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/Trait.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/Validator.php b/Aiko/Libs/Validator.php new file mode 100644 index 0000000..bc45627 --- /dev/null +++ b/Aiko/Libs/Validator.php @@ -0,0 +1,110 @@ +rules = $rules; + if (!is_array($request) && is_object($request)) { + $this->request = json_decode(json_encode($request), true); + } else { + $this->request = $request; + } + } + + /** + * @param string $paramKey + * @param \Closure($value, $params): string|null $validatorFn + */ + public function addRule($paramKey, $validatorFn, $messages = []) + { + array_push($this->rules, new ValidationRule($this->request, $paramKey, $validatorFn, $messages)); + return $this; + } + + public function fails() + { + return count($this->errorBag) > 0; + } + + public function safe($key = null) + { + if (is_null($key)) { + return $this->valid; + } + if (isset($this->valid[$key])) { + return $this->valid[$key]; + } + return null; + } + + public function all() + { + return $this->request; + } + + public function only($keys = []) + { + $request = []; + foreach ($keys as $key) { + if (array_key_exists($key, $this->request)) { + $request[$key] = $this->request[$key]; + } + } + return $request; + } + + public function errors() + { + return $this->errorBag; + } + + public function validate($throw = false) + { + /** @var ValidationRule $rule */ + foreach ($this->rules as $rule) { + if (!$rule->validate()) { + if ($throw) { + throw new ValidatorException($rule->key, $rule->errorBag); + } + array_push($this->errorBag, $rule->errorBag); + continue; + } + $this->valid[$rule->key] = $rule->getParamValue(); + } + } +} + + +class ValidatorException extends Exception +{ + private $data; + + // Redefine the exception so message isn't optional + public function __construct($message, $data = [], $previous = null) + { + parent::__construct($message, 0, $previous); + $this->data = $data; + } + + // custom string representation of object + public function __toString() + { + return __CLASS__ . ": [{$this->code}]: {$this->message}\n"; + } + + public function getData() + { + return $this->data; + } +} \ No newline at end of file diff --git a/Aiko/Libs/Validator.php:Zone.Identifier b/Aiko/Libs/Validator.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/Validator.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/ValidatorRule.php b/Aiko/Libs/ValidatorRule.php new file mode 100644 index 0000000..e227d1b --- /dev/null +++ b/Aiko/Libs/ValidatorRule.php @@ -0,0 +1,101 @@ +key = $key; + $this->action = $action; + $this->paramBag = $paramBag; + $this->messages = $messages; + } + + public function validate() + { + $param = $this->getParamValue(); + if (is_callable($this->action)) { + $fn = $this->action; + $message = $fn($param, $this->paramBag); + if ($message !== null) { + $this->addError($message); + return false; + } + } else if (is_string($this->action)) { + $repo = new ValidatorRuleCollection(); + $ref = new ReflectionClass($repo); + $method = $this->action; + if (strpos($this->action, '|') != false) { + $exp = explode('|', $this->action); + $method = $exp[0]; + } + try { + $refMethod = $ref->getMethod($method); + $result = $refMethod->invokeArgs(new ValidatorRuleCollection(), [$this->key, $this->action, $param, $this->paramBag]); + if (!is_null($result)) { + $this->addError($result); + return false; + } + return true; + } catch (\ReflectionException $e) { + return false; + } + } else { + // defensive action + return false; + } + return true; + } + + public function parseMessage($messageKey) + { + if (array_key_exists($messageKey, $this->messages)) { + return $this->messages[$messageKey]; + } + return $messageKey; + } + + public function addError($message = null) + { + $this->errorBag = [ + 'key' => $this->key, + 'message' => is_null($message) ? "{$this->key} cant be empty" : $this->parseMessage($message) + ]; + } + + public function getParamValue() + { + if (array_key_exists($this->key, $this->paramBag)) { + return $this->paramBag[$this->key]; + } + return null; + } +} diff --git a/Aiko/Libs/ValidatorRule.php:Zone.Identifier b/Aiko/Libs/ValidatorRule.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/ValidatorRule.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/ValidatorRuleCollection.php b/Aiko/Libs/ValidatorRuleCollection.php new file mode 100644 index 0000000..9ab18a5 --- /dev/null +++ b/Aiko/Libs/ValidatorRuleCollection.php @@ -0,0 +1,136 @@ + '123456', 'password_confirmation' => '123456'] + * new Validator($params)->addRule('password', 'mustMatch|password_confirmation'); + * + */ + public function mustMatch($key, $ruleString, $value, $params) + { + $keys = explode('|', $ruleString); + if (count($keys) < 2) { + throw new Exception("validator rules not valid for $$ruleString"); + } + $compare1 = $this->_getParamValue($keys[1], $params); + $compare2 = $this->_getParamValue($key, $params); + if (is_null($compare1) || is_null($compare2)) { + return "VALIDATOR.MUST_MATCH.MUST_NOT_EMPTY"; + } + if ($compare1 != $compare2) { + return "VALIDATOR.MUST_MATCH.NOT_MATCH"; + } + return null; + } + + /** + * @param string $key pattern : file|image,document|2048 + * + * pattern for | : index 0 must be file, index 1 is file type, for the rest current support only maxSize + * + * @example + * + * $request = ['my_file' => $file, 'others' => '1234'] + * new Validator($params)->addRule('my_file', 'file|image,document|2048'); + * + */ + public function file($key, $ruleString, $value, $params) + { + $log = new Log(0); + + if (!($value instanceof UploadedFile)) { + $log->error("ValidatorRuleCollection [file]: file is not file"); + return 'VALIDATOR.FILE.IS_NOT_FILE'; + } + $keys = explode('|', $ruleString); + if (count($keys) == 0) { + throw new Exception("$key validator rules not valid for $$ruleString"); + } + $validatedMime = []; + if (strpos($keys[1], ',') == false) { + if (!in_array($keys[1], ['image', 'document'])) { + $log->error("ValidatorRuleCollection [file]: mime not supported {$keys[1]}"); + return 'VALIDATOR.FILE.MIME'; + } + $validatedMime = [$keys[1]]; + } else { + $exp = explode(',', $keys[1]); + for ($i = 0; $i < count($exp); $i++) { + if (!in_array($exp[$i], ['image', 'document'])) { + $log->error("ValidatorRuleCollection [file]: mime not supported {$exp[$i]}"); + return 'VALIDATOR.FILE.MIME'; + } + } + $validatedMime = $exp; + } + $maxSize = 4096; + if (isset($keys[2]) && is_numeric($keys[2])) { + $maxSize = (int) $maxSize; + } + $sizeInKb = $value->getSize() / 1024; + if ($sizeInKb > $maxSize) { + $log->error("ValidatorRuleCollection [file]: max size {$sizeInKb} higher than allowed $maxSize"); + return "VALIDATOR.FILE.MAX_SIZE"; + } + $mime = $value->getMimeType(); + if (in_array('image', $validatedMime)) { + if (!in_array($mime, $this->allowedMimeType)) { + $log->error("ValidatorRuleCollection [file]: image mime type not allowed $mime"); + return 'VALIDATOR.FILE.IMAGE_INVALID'; + } + } + if (in_array('document', $validatedMime)) { + if (!in_array($mime, $this->allowedMimeType)) { + $log->error("ValidatorRuleCollection [file]: document mime type not allowed $mime"); + return 'VALIDATOR.FILE.DOCUMENT_INVALID'; + } + } + return null; + } + + public function required($key, $ruleString, $value, $params) + { + if (!isset($value) || strlen($value) == 0) return 'VALIDATOR.REQUIRED'; + return null; + } + + public function _getParamValue($key, $params) + { + if (array_key_exists($key, $params)) { + return $params[$key]; + } + return null; + } +} diff --git a/Aiko/Libs/ValidatorRuleCollection.php:Zone.Identifier b/Aiko/Libs/ValidatorRuleCollection.php:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/ValidatorRuleCollection.php:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Aiko/Libs/WhatsApp.php b/Aiko/Libs/WhatsApp.php new file mode 100644 index 0000000..268c8c1 --- /dev/null +++ b/Aiko/Libs/WhatsApp.php @@ -0,0 +1,570 @@ +init($baseURL); + + + } + + /** + * init component + * + * @param String|null $baseURL + */ + private function init($baseURL = null) + { + $this->sender = $this->registry->config->whatsapp_sender; + $this->client = new Client([ + 'base_uri' => $baseURL ?? $this->registry->config->whatsapp_endpoint, + 'headers' => ['Authorization' => $this->registry->config->whatsapp_api_token, "Accept" => "application/json"], + ]); + } + + public function getTokenAccess(){ + + try{ + $client= new Client(); + $token=''; + if($this->registry->config->wa_token_need_reload){ + $data = array( + 'username'=>$this->registry->config->wa_username, + 'password'=>$this->registry->config->wa_password, + 'grant_type'=>$this->registry->config->wa_grant_type, + 'client_id'=>$this->registry->config->wa_client_id, + 'client_secret'=>$this->registry->config->wa_client_secret, + ); + $response = $client->post($this->registry->config->wa_auth_url, [ + 'headers' => ['Content-Type' => 'application/json', 'Accept' => 'application/json'], + 'body' => json_encode($data) + ]); + $data=json_decode($response->getBody()); + + + $result=$this->_saveTokenAcces($data); + + if(!$result){ + throw new ErrorException('failed save access token to db'); + } + $token=$data->access_token; + }else{ + $stmt=$this->registry->db->prepare('select access_token from wa_qontak_auth where `name`=:name'); + $stmt->bindValue(':name',$this->registry->config->wa_token_name,PDO::PARAM_STR); + $stmt->execute(); + if($stmt->rowCount()==0){ + throw new ErrorException('token access empty'); + } + $rs=$stmt->fetchAll(PDO::FETCH_ASSOC); + $token=$rs[0]['access_token']; + } + + return $token; + }catch(PDOException $e){ + $this->registry->log->error('WhatsApp/getTokenAccess:'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + return false; + }catch(ErrorException $e){ + $this->registry->log->error('WhatsApp/getTokenAccess:'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + return false; + } + + } + + private function _saveTokenAcces($data){ + try{ + // $this->registry->db->beginTransaction(); + $stmtCheck=$this->registry->db->prepare("select id from `wa_qontak_auth` where name=:name"); + $stmtCheck->bindValue(':name',$this->registry->config->wa_token_name,PDO::PARAM_STR); + $stmtCheck->execute(); + if($stmtCheck->rowCount()>0){ + $stmtUpdate=$this->registry->db->prepare('update `wa_qontak_auth` set access_token=:access_token, + token_type=:token_type, + expires_in=:expires_in, + refresh_token=:refresh_token, + created_at=:created_at where `name`=:name'); + $stmtUpdate->bindValue(':access_token',$data->access_token,PDO::PARAM_STR); + $stmtUpdate->bindValue(':token_type',$data->token_type,PDO::PARAM_STR); + $stmtUpdate->bindValue(':expires_in',$data->expires_in,PDO::PARAM_STR); + $stmtUpdate->bindValue(':refresh_token',$data->refresh_token,PDO::PARAM_STR); + $stmtUpdate->bindValue(':created_at',$data->created_at,PDO::PARAM_STR); + $stmtUpdate->bindValue(':name',$this->registry->config->wa_token_name,PDO::PARAM_STR); + $stmtUpdate->execute(); + }else{ + $stmtInsert=$this->registry->db->prepare('insert into `wa_qontak_auth` ( + access_token, + token_type, + expires_in, + refresh_token, + created_at, + name + )values + (:access_token, + :token_type, + :expires_in, + :refresh_token, + :created_at, + :name)'); + $stmtInsert->bindValue(':access_token',$data->access_token,PDO::PARAM_STR); + $stmtInsert->bindValue(':token_type',$data->token_type,PDO::PARAM_STR); + $stmtInsert->bindValue(':expires_in',$data->expires_in,PDO::PARAM_STR); + $stmtInsert->bindValue(':refresh_token',$data->refresh_token,PDO::PARAM_STR); + $stmtInsert->bindValue(':created_at',$data->created_at,PDO::PARAM_STR); + $stmtInsert->bindValue(':name',$this->registry->config->wa_token_name,PDO::PARAM_STR); + $stmtInsert->execute(); + } + // $this->registry->db->commit(); + return true; + + }catch(PDOException $e){ + $this->registry->db->rollBack(); + $this->registry->log->error('WhatsApp/_saveTokenAcces:'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + return false; + }catch(ErrorException $e){ + $this->registry->db->rollBack(); + $this->registry->log->error('WhatsApp/_saveTokenAcces:'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + return false; + } + } + + /** + * set sender + + * @param String $sender phone number + * + * @return Aiko\Whatsapp + * + */ + public function setSender($sender) + { + $this->sender = $sender; + return $this; + } + + /** + * Send message to many recepient + * + * @param Array $payload + * example of param + * [ + * [ + * 'phone' => '081xxx', + * 'message' => 'hi', + * 'link' => 'https://xxxx', + * 'type' => 'image' // default text-only + * ] + * ] + */ + public function sendBulkMessage($payload = []) + { + if (!is_array($payload)) { + $this->registry->log->customError('WhatsApp', "Parameter must be an array"); + return false; + } + + $report = []; + foreach ($payload as $value) { + $send = $this->sendMessage($value['phone'], $value['message'], $value['type'], $value['link']); + array_push($report, $send); + } + + return $report; + } + + public function sendBulkMessageQontak($payload = []) + { + + if (!is_array($payload)) { + $this->registry->log->customError('WhatsApp', "Parameter must be an array"); + return false; + } + + $report = []; + foreach ($payload as $value) { + + $send = $this->sendMessageQontak($value['phone'], $value['name'],$value['parameter'], $value['template']); + array_push($report, $send); + } + + return $report; + } + + public function sendMessage($toNumber, $message, $type = 'text', $link = null) + { + if (!in_array($type, $this->messageType)) { + $this->registry->log->customError('WhatsApp', "Message type not allowed : $type"); + return false; + } + + $endpoint = 'send-message'; + $payload = array( + 'phone' => $toNumber, + 'message' => $message, + 'secret' => false, // or true + 'priority' => false, // or true + ); + switch ($type) { + case 'image': + $endpoint = 'send-image'; + $payload = array( + 'phone' => $toNumber, + 'caption' => $message, + 'image' => $link, + 'secret' => false, // or true + 'priority' => false, // or true + ); + break; + case 'video': + $endpoint = 'send-video'; + $payload = array( + 'phone' => $toNumber, + 'caption' => $message, + 'document' => $link, + 'secret' => false, // or true + 'priority' => false, // or true + ); + break; + case 'document': + $endpoint = 'send-document'; + $payload = array( + 'phone' => $toNumber, + 'document' => $link, + 'secret' => false, // or true + 'priority' => false, // or true + ); + break; + } + + // $request = $this->client->post($endpoint, array('form_params' => $payload)); + // $response = $request->getBody(); + // $contents = json_decode($response->getContents()); + + // if ($contents) { + // $webhook = new Webhook($this->registry); + // if (isset($contents->data)) { + // $data = $contents->data->message; + // foreach ($data as $value) { + // $webhook->create([ + // 'phone' => $value->phone, + // 'status' => $value->status, + // 'note' => $value->text, + // 'id' => $value->id, + // 'deviceId' => $this->registry->config->whatsapp_device_id, + // ]); + // } + // } + // } + + // return $contents; + return true; + } + + public function sendMessageQontak($toNumber, $toName,$parameters, $templateName) + { + // try{ + // // $toNumber='+6282214258200'; + // $tokenAccess=$this->getTokenAccess(); + // $client = new Client(); + // // var_dump($templateName); + // // var_dump($this->_getTemplateId($templateName)); + // // exit(); + // $templateID=$this->_getTemplateId($templateName); + + + // if($templateID===-1){ + // $this->registry->log->error('template tidak active atau belum ada dengan templateName:'.$templateName.', user: '.\Helper::getSessionVar('username')); + // return true; + // } + + // $data=array( + // "to_name"=>$toName, + // "to_number"=>\Helper::formatPhoneNumber($toNumber), + // "message_template_id"=>$templateID, + // "channel_integration_id"=>$this->registry->config->channel_integration_id, + // "language"=> array( + // "code"=> "id" + // ), + // "parameters"=>array( + // "body"=>$parameters + // ) + // ); + + // $client = new Client(); + // $request = $client->request('POST', $this->registry->config->whatsapp_endpoint, [ + // 'headers' => [ + // 'Authorization' => 'Bearer '.$tokenAccess, + // 'Content-Type' => 'application/json', 'Accept' => 'application/json'], + // 'body' => json_encode($data)] + // ); + // $response = $client->send($request); + // dd($response->json()); + + + // $response = $client->post($this->registry->config->whatsapp_endpoint, [ + // 'headers' => [ + // 'Authorization' => 'Bearer '.$tokenAccess, + // 'Content-Type' => 'application/json', 'Accept' => 'application/json'], + // 'body' => json_encode($data) + // ]); + + // var_dump(json_encode($responseData)); + // exit(); + // $responseData=json_decode($response->getBody()); + + // if(property_exists($responseData,'status')){ + // if(!$responseData->status=='success'){ + // throw new ErrorException('Gagal kirim WA'); + // } + // }else{ + // throw new ErrorException('Gagal kirim WA, response undefined'); + // } + // return true; + // }catch(ErrorException $e){ + // $this->registry->log->error('WhatsApp/sendMessageQontak:'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + // return false; + // } + + try { + + $tokenAccess=$this->getTokenAccess(); + $client = new Client(); + $templateID=$this->_getTemplateId($templateName); + + + if($templateID===-1){ + $this->registry->log->error('template tidak active atau belum ada dengan templateName:'.$templateName.', user: '.\Helper::getSessionVar('username')); + return true; + } + + $data=array( + "to_name"=>$toName, + "to_number"=>\Helper::formatPhoneNumber($toNumber), + "message_template_id"=>$templateID, + "channel_integration_id"=>$this->registry->config->channel_integration_id, + "language"=> array( + "code"=> "id" + ), + "parameters"=>array( + "body"=>$parameters + ) + ); + + $request = $client->post($this->registry->config->whatsapp_endpoint, [ + 'headers' => [ + 'Authorization' => 'Bearer '.$tokenAccess, + 'Content-Type' => 'application/json', 'Accept' => 'application/json'], + 'body' => json_encode($data) + ]); + + $this->response = json_decode($request->getBody()->getContents()); + return true; + } catch (\GuzzleHttp\Exception\RequestException $e) { + $this->errors = json_decode($e->getResponse()->getBody()->getContents()); + $this->registry->log->error('WhatsApp/sendMessageQontak:'.$this->errors->error->messages[0].', user: '.\Helper::getSessionVar('username')); + } + + return false; + + } + + private function _getTemplateId($name){ + try{ + $stmt=$this->registry->db->prepare('select id from wa_templates where `name`=:templateName'); + $stmt->bindValue(':templateName',$name,PDO::PARAM_STR); + $stmt->execute(); + if($stmt->rowCount()==0){ + // throw new ErrorException('template id dengan name :'.$name.' kosong'); + //jika template tidak ada return -1 bisa jadi sudah di non activekan + return -1; + } + $rs=$stmt->fetchAll(PDO::FETCH_ASSOC); + return $rs[0]['id']; + }catch(PDOException $e){ + $this->registry->log->error('WhatsApp/_getTemplateId:'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + return false; + }catch(ErrorException $e){ + $this->registry->log->error('WhatsApp/_getTemplateId:'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + return false; + } + } + + public function sendDocumentLocally($toNumber, $filePath, $config) + { + $handle = fopen($filePath, "r"); + $file = fread($handle, filesize($filePath)); + $config['size'] = filesize($filePath); + $endpoint = 'send-document-from-local'; + $payload = array( + 'phone' => $toNumber, + 'file' => base64_encode($file), + 'data' => json_encode($config), + ); + + $request = $this->client->post($endpoint, array('form_params' => $payload)); + $response = $request->getBody(); + $contents = json_decode($response->getContents()); + + return $contents; + } + + /** + * Send message to many recepient in very sumple terms + * + * @param Array $payload + * example of param + * [ + * [ + * 'phone' => '081xxx', + * 'message' => 'hi', + * 'secret' => false, + * 'priority' => false + * ] + * ] + */ + public function simpleBulkMessage($params = []) + { + $endpoint = 'v2/send-bulk/text'; + $request = $this->client->post($endpoint, array('body' => json_encode($params))); + $response = $request->getBody(); + $contents = json_decode($response->getContents()); + + return $contents; + } + public function sendDocument($toNumber, $urlPath, $caption = '') + { + // $endpoint = 'send-document'; + // $payload = array( + // 'phone' => $toNumber, + // 'document' => $urlPath, + // 'caption' => $caption, + // 'isGroup' => false, + // ); + + // $request = $this->client->post($endpoint, array('form_params' => $payload)); + // $response = $request->getBody(); + // $contents = json_decode($response->getContents()); + + // return $contents; + return true; + } + + public function sendDocumentQontak($toNumber, $toName,$parameters, $templateName,$header) + { + try{ + + $tokenAccess=$this->getTokenAccess(); + $client = new Client(); + // var_dump($templateName); + // var_dump($this->_getTemplateId($templateName)); + // exit(); + $data=array( + "to_name"=>$toName, + "to_number"=>\Helper::formatPhoneNumber($toNumber), + "message_template_id"=>$this->_getTemplateId($templateName), + "channel_integration_id"=>$this->registry->config->channel_integration_id, + "language"=> array( + "code"=> "id" + ), + "parameters"=>array( + "header"=> $header, + "body"=>$parameters + ) + ); + $response = $client->post($this->registry->config->whatsapp_endpoint, [ + 'headers' => [ + 'Authorization' => 'Bearer '.$tokenAccess, + 'Content-Type' => 'application/json', 'Accept' => 'application/json'], + 'body' => json_encode($data) + ]); + $responseData=json_decode($response->getBody()); + if(property_exists($responseData,'status')){ + if(!$responseData->status=='success'){ + throw new ErrorException('Gagal kirim WA'); + } + }else{ + throw new ErrorException('Gagal kirim WA, response undefined'); + } + return true; + }catch(ErrorException $e){ + $this->registry->log->error('WhatsApp/sendDocumentQontak:'.$e->getMessage().', user: '.\Helper::getSessionVar('username')); + return false; + } + + } + + public function sendMessageQontakTermination($toNumber, $toName,$parameters, $templateName) + { + try { + + $tokenAccess=$this->getTokenAccess(); + $client = new Client(); + $templateID=$this->_getTemplateId($templateName); + + + if($templateID===-1){ + $this->registry->log->error('template tidak active atau belum ada dengan templateName:'.$templateName.', user: '.\Helper::getSessionVar('username')); + return true; + } + + $data=array( + "to_name"=>$toName, + "to_number"=>\Helper::formatPhoneNumber($toNumber), + "message_template_id"=>$templateID, + "channel_integration_id"=>$this->registry->config->channel_integration_id, + "language"=> array( + "code"=> "id" + ), + "parameters"=>array( + "body"=>$parameters + ) + ); + + $request = $client->post($this->registry->config->whatsapp_endpoint, [ + 'headers' => [ + 'Authorization' => 'Bearer '.$tokenAccess, + 'Content-Type' => 'application/json', 'Accept' => 'application/json'], + 'body' => json_encode($data) + ]); + + $this->response = json_decode($request->getBody()->getContents()); + return $this->response; + } catch (\GuzzleHttp\Exception\RequestException $e) { + // $this->registry->log->error('WhatsApp/sendMessageQontak:'.$this->errors->error->messages[0].', user: '.\Helper::getSessionVar('username')); + $this->errors = json_decode($e->getResponse()->getBody()->getContents()); + return $this->errors; + } + + + } +} diff --git a/Aiko/Libs/WhatsApp.php:Zone.Identifier b/Aiko/Libs/WhatsApp.php:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/Aiko/Libs/WhatsApp.php:Zone.Identifier:Zone.Identifier b/Aiko/Libs/WhatsApp.php:Zone.Identifier:Zone.Identifier new file mode 100644 index 0000000..c64ece3 --- /dev/null +++ b/Aiko/Libs/WhatsApp.php:Zone.Identifier:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=C:\Users\abish\Downloads\Aiko (1).zip diff --git a/Dockerfile.backend b/Dockerfile.backend index e3ed96d..400bd3a 100644 --- a/Dockerfile.backend +++ b/Dockerfile.backend @@ -24,8 +24,9 @@ WORKDIR /app # Copying Config Files COPY ./be/src/api/composer.json ./src/api/composer.json -COPY ./be/src/api/Aiko/ ./src/api/Aiko/ COPY ./be/src/api/Helper/ ./src/api/Helper/ +# Copy Aiko folder from root directory +COPY ./Aiko/ ./src/api/Aiko/ RUN cd /app/src/api && composer install # Copying controllers diff --git a/apache-config.conf b/apache-config.conf index 7a94e32..ee35412 100644 --- a/apache-config.conf +++ b/apache-config.conf @@ -17,6 +17,12 @@ AllowOverride All Require all granted + + + Options Indexes FollowSymLinks + AllowOverride All + Require all granted + # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, # error, crit, alert, emerg. diff --git a/be b/be index 077592a..fbd41d3 160000 --- a/be +++ b/be @@ -1 +1 @@ -Subproject commit 077592a2210714d75578213499170b866b2ff072 +Subproject commit fbd41d34704e9e929b804dad5228f0cc9edaa06c diff --git a/docker-compose.yml b/docker-compose.yml index 1f64c10..4205ab1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -21,6 +21,7 @@ services: - ./be:/app - ./apache-config.conf:/etc/apache2/sites-available/000-default.conf:ro - backend-vendor:/app/src/api/vendor + - ./Aiko:/app/src/api/Aiko:ro owasp: container_name: owasp-hcportal image: owasp/modsecurity-crs:3.3.5-nginx-202401080101 @@ -44,3 +45,4 @@ networks: volumes: backend-vendor: + backend-aiko: