diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4b2ab12 --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +#codeigniter4 +composer.lock +/vendor/ +public/vendors/ +public/tinymce_uploads +.env +google_client_secret.json + +writable/caceh/* +!writable/caceh/index.html +writable/logs/* +!writable/logs/index.html +writable/session/* +!writable/session/index.html +writable/uploads/* +!writable/uploads/index.html +writable/debugbar/* +!writable/debugbar/index.html +writable/excel/* +!writable/excel/index.html \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..7bf3b90 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "php.version": "8.3" +} \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..148e7f7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2014-2019 British Columbia Institute of Technology +Copyright (c) 2019-2024 CodeIgniter Foundation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f5f8ee1 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# Automation + diff --git a/app/.htaccess b/app/.htaccess new file mode 100644 index 0000000..97c65d2 --- /dev/null +++ b/app/.htaccess @@ -0,0 +1,6 @@ + + Require all denied + + + Deny from all + \ No newline at end of file diff --git a/app/CLI/Cloudflare.php b/app/CLI/Cloudflare.php new file mode 100644 index 0000000..d11e265 --- /dev/null +++ b/app/CLI/Cloudflare.php @@ -0,0 +1,75 @@ +_db = \Config\Database::connect(); + } + private function getAuthModel(): AuthModel + { + return new AuthModel(); + } + private function auth_process(): array + { + $this->getAuthModel()->where('status', DEFAULTS["STATUS"]); + return $this->getAuthModel()->getEntitys(); + } + private function account_process(AuthEntity $auth_entity): array + { + $account = new Account($auth_entity); + return $account->reload(); + } + private function zone_process(AccountEntity $account_entity): array + { + $zone = new Zone($account_entity); + return $zone->reload(); + } + private function record_process(ZoneEntity $zone_entity): array + { + $record = new Record($zone_entity); + return $record->reload(); + } + public function reload(): void + { + //Transaction Start + $this->_db->transStart(); + try { + $auths = $this->auth_process(); + $accounts = []; + foreach ($auths as $auth) { + $accounts = $this->account_process($auth); + } + $zones = []; + foreach ($accounts as $account) { + $zones = $this->zone_process($account); + } + $records = []; + foreach ($zones as $zone) { + $records = $this->record_process($zone); + } + log_message("notice", "Reload 작업을 완료하였습니다."); + $this->_db->transCommit(); + } catch (\Exception $e) { + //Transaction Rollback + $this->_db->transRollback(); + log_message( + "error", + "Reload 작업을 실패하였습니다.\n--------------\n" . + $e->getMessage() . + "\n--------------\n" + ); + } + } +} diff --git a/app/Common.php b/app/Common.php new file mode 100644 index 0000000..95f5544 --- /dev/null +++ b/app/Common.php @@ -0,0 +1,15 @@ + + */ + public array $allowedHostnames = []; + + /** + * -------------------------------------------------------------------------- + * Index File + * -------------------------------------------------------------------------- + * + * Typically, this will be your `index.php` file, unless you've renamed it to + * something else. If you have configured your web server to remove this file + * from your site URIs, set this variable to an empty string. + */ + public string $indexPage = 'index.php'; + + /** + * -------------------------------------------------------------------------- + * URI PROTOCOL + * -------------------------------------------------------------------------- + * + * This item determines which server global should be used to retrieve the + * URI string. The default setting of 'REQUEST_URI' works for most servers. + * If your links do not seem to work, try one of the other delicious flavors: + * + * 'REQUEST_URI': Uses $_SERVER['REQUEST_URI'] + * 'QUERY_STRING': Uses $_SERVER['QUERY_STRING'] + * 'PATH_INFO': Uses $_SERVER['PATH_INFO'] + * + * WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded! + */ + public string $uriProtocol = 'REQUEST_URI'; + + /* + |-------------------------------------------------------------------------- + | Allowed URL Characters + |-------------------------------------------------------------------------- + | + | This lets you specify which characters are permitted within your URLs. + | When someone tries to submit a URL with disallowed characters they will + | get a warning message. + | + | As a security measure you are STRONGLY encouraged to restrict URLs to + | as few characters as possible. + | + | By default, only these are allowed: `a-z 0-9~%.:_-` + | + | Set an empty string to allow all characters -- but only if you are insane. + | + | The configured value is actually a regular expression character group + | and it will be used as: '/\A[]+\z/iu' + | + | DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!! + | + */ + public string $permittedURIChars = 'a-z 0-9~%.:_\-'; + + /** + * -------------------------------------------------------------------------- + * Default Locale + * -------------------------------------------------------------------------- + * + * The Locale roughly represents the language and location that your visitor + * is viewing the site from. It affects the language strings and other + * strings (like currency markers, numbers, etc), that your program + * should run under for this request. + */ + public string $defaultLocale = 'en'; + + /** + * -------------------------------------------------------------------------- + * Negotiate Locale + * -------------------------------------------------------------------------- + * + * If true, the current Request object will automatically determine the + * language to use based on the value of the Accept-Language header. + * + * If false, no automatic detection will be performed. + */ + public bool $negotiateLocale = false; + + /** + * -------------------------------------------------------------------------- + * Supported Locales + * -------------------------------------------------------------------------- + * + * If $negotiateLocale is true, this array lists the locales supported + * by the application in descending order of priority. If no match is + * found, the first locale will be used. + * + * IncomingRequest::setLocale() also uses this list. + * + * @var list + */ + public array $supportedLocales = ['en']; + + /** + * -------------------------------------------------------------------------- + * Application Timezone + * -------------------------------------------------------------------------- + * + * The default timezone that will be used in your application to display + * dates with the date helper, and can be retrieved through app_timezone() + * + * @see https://www.php.net/manual/en/timezones.php for list of timezones + * supported by PHP. + */ + public string $appTimezone = 'UTC'; + + /** + * -------------------------------------------------------------------------- + * Default Character Set + * -------------------------------------------------------------------------- + * + * This determines which character set is used by default in various methods + * that require a character set to be provided. + * + * @see http://php.net/htmlspecialchars for a list of supported charsets. + */ + public string $charset = 'UTF-8'; + + /** + * -------------------------------------------------------------------------- + * Force Global Secure Requests + * -------------------------------------------------------------------------- + * + * If true, this will force every request made to this application to be + * made via a secure connection (HTTPS). If the incoming request is not + * secure, the user will be redirected to a secure version of the page + * and the HTTP Strict Transport Security (HSTS) header will be set. + */ + public bool $forceGlobalSecureRequests = false; + + /** + * -------------------------------------------------------------------------- + * Reverse Proxy IPs + * -------------------------------------------------------------------------- + * + * If your server is behind a reverse proxy, you must whitelist the proxy + * IP addresses from which CodeIgniter should trust headers such as + * X-Forwarded-For or Client-IP in order to properly identify + * the visitor's IP address. + * + * You need to set a proxy IP address or IP address with subnets and + * the HTTP header for the client IP address. + * + * Here are some examples: + * [ + * '10.0.1.200' => 'X-Forwarded-For', + * '192.168.5.0/24' => 'X-Real-IP', + * ] + * + * @var array + */ + public array $proxyIPs = []; + + /** + * -------------------------------------------------------------------------- + * Content Security Policy + * -------------------------------------------------------------------------- + * + * Enables the Response's Content Secure Policy to restrict the sources that + * can be used for images, scripts, CSS files, audio, video, etc. If enabled, + * the Response object will populate default values for the policy from the + * `ContentSecurityPolicy.php` file. Controllers can always add to those + * restrictions at run time. + * + * For a better understanding of CSP, see these documents: + * + * @see http://www.html5rocks.com/en/tutorials/security/content-security-policy/ + * @see http://www.w3.org/TR/CSP/ + */ + public bool $CSPEnabled = false; +} diff --git a/app/Config/Autoload.php b/app/Config/Autoload.php new file mode 100644 index 0000000..76cd926 --- /dev/null +++ b/app/Config/Autoload.php @@ -0,0 +1,94 @@ +|string> + */ + public $psr4 = [ + APP_NAMESPACE => APPPATH, + ]; + + /** + * ------------------------------------------------------------------- + * Class Map + * ------------------------------------------------------------------- + * The class map provides a map of class names and their exact + * location on the drive. Classes loaded in this manner will have + * slightly faster performance because they will not have to be + * searched for within one or more directories as they would if they + * were being autoloaded through a namespace. + * + * Prototype: + * $classmap = [ + * 'MyClass' => '/path/to/class/file.php' + * ]; + * + * @var array + */ + public $classmap = []; + + /** + * ------------------------------------------------------------------- + * Files + * ------------------------------------------------------------------- + * The files array provides a list of paths to __non-class__ files + * that will be autoloaded. This can be useful for bootstrap operations + * or for loading functions. + * + * Prototype: + * $files = [ + * '/path/to/my/file.php', + * ]; + * + * @var list + */ + public $files = []; + + /** + * ------------------------------------------------------------------- + * Helpers + * ------------------------------------------------------------------- + * Prototype: + * $helpers = [ + * 'form', + * ]; + * + * @var list + */ + public $helpers = []; +} diff --git a/app/Config/Boot/development.php b/app/Config/Boot/development.php new file mode 100644 index 0000000..a868447 --- /dev/null +++ b/app/Config/Boot/development.php @@ -0,0 +1,34 @@ + + */ + public array $file = [ + 'storePath' => WRITEPATH . 'cache/', + 'mode' => 0640, + ]; + + /** + * ------------------------------------------------------------------------- + * Memcached settings + * ------------------------------------------------------------------------- + * Your Memcached servers can be specified below, if you are using + * the Memcached drivers. + * + * @see https://codeigniter.com/user_guide/libraries/caching.html#memcached + * + * @var array + */ + public array $memcached = [ + 'host' => '127.0.0.1', + 'port' => 11211, + 'weight' => 1, + 'raw' => false, + ]; + + /** + * ------------------------------------------------------------------------- + * Redis settings + * ------------------------------------------------------------------------- + * Your Redis server can be specified below, if you are using + * the Redis or Predis drivers. + * + * @var array + */ + public array $redis = [ + 'host' => '127.0.0.1', + 'password' => null, + 'port' => 6379, + 'timeout' => 0, + 'database' => 0, + ]; + + /** + * -------------------------------------------------------------------------- + * Available Cache Handlers + * -------------------------------------------------------------------------- + * + * This is an array of cache engine alias' and class names. Only engines + * that are listed here are allowed to be used. + * + * @var array> + */ + public array $validHandlers = [ + 'dummy' => DummyHandler::class, + 'file' => FileHandler::class, + 'memcached' => MemcachedHandler::class, + 'predis' => PredisHandler::class, + 'redis' => RedisHandler::class, + 'wincache' => WincacheHandler::class, + ]; + + /** + * -------------------------------------------------------------------------- + * Web Page Caching: Cache Include Query String + * -------------------------------------------------------------------------- + * + * Whether to take the URL query string into consideration when generating + * output cache files. Valid options are: + * + * false = Disabled + * true = Enabled, take all query parameters into account. + * Please be aware that this may result in numerous cache + * files generated for the same page over and over again. + * ['q'] = Enabled, but only take into account the specified list + * of query parameters. + * + * @var bool|list + */ + public $cacheQueryString = false; +} diff --git a/app/Config/Constants.php b/app/Config/Constants.php new file mode 100644 index 0000000..1004f2a --- /dev/null +++ b/app/Config/Constants.php @@ -0,0 +1,297 @@ + "guest", + 'STATUS' => "use", + 'EMPTY' => "", + 'DELIMITER_FILE' => "||", + 'DELIMITER_ROLE' => ",", +]); +//FORM +define('FORMS', [ + 'MODAL' => 'modal_form', + 'IFRAME' => 'iframe_form', + 'DIRECT' => 'direct_form', +]); +//URL +define('URLS', [ + 'LOGIN' => '/user/login', + 'GOOGLE_LOGIN' => '/user/google_login', + 'SIGNUP' => '/user/signup', + 'LOGOUT' => '/user/logout', +]); +//회원ROLE +define('ROLES', [ + 'guest', + 'user', + 'vip', + 'manager', + 'cloudflare', + 'director', + 'master', +]); +//SESSION 관련 +define('SESSION_NAMES', [ + 'RETURN_URL' => "return_url", + 'RETURN_MSG' => "return_message", + 'ISLOGIN' => "islogined", + 'AUTH' => 'auth', +]); +//메신저 관련 +define("MESSENGERS", [ + "skype" => [ + "url" => "//join.skype.com/invite/uKUgXfZThSQC", + "icon" => '스카이프', + "id" => '', + ], + "discord" => [ + "url" => "//discord.gg/k6nQg84N", + "icon" => '디스코드', + "id" => '', + ], + "telegram" => [ + "url" => "//t.me/daemonidc", + "icon" => '텔레그램', + "id" => '@daemonidc', + ], + "kakaotalk" => [ + "url" => "//t.me/daemonidc", + "icon" => '카카오톡', + "id" => '', + ], +]); +//아이콘 및 Sound관련 +define('ICONS', [ + 'LOGO' => '', + 'EXCEL' => '', + 'PDF' => '', + 'GOOGLE' => 'Google', + 'MEMBER' => '', + 'LOGIN' => '', + 'LOGOUT' => '', + 'HOME' => '', + 'MENU' => '', + 'NEW' => '', + 'REPLY' => '', + 'DATABASE' => '', + 'DELETE' => '', + 'REBOOT' => '', + 'RELOAD' => '', + 'SETUP' => '', + 'FLAG' => '', + 'SEARCH' => '', + 'PLAY' => '', + 'CART' => '', + 'CARD' => '', + 'DEPOSIT' => '', + 'DESKTOP' => '', + 'UP' => '', + 'DOWN' => '', + 'LEFT' => '', + 'RIGHT' => '', + 'IMAGE_FILE' => '', + 'CLOUD' => '', + 'SIGNPOST' => '', + 'LOCK' => '', + 'UNLOCK' => '', + 'BOX' => '', + 'BOXS' => '', +]); +//배너관련 +define('TOP_BANNER', [ + 'default' => '', + 'aboutus' => '', + 'member' => '', + 'hosting' => '', + 'serverdevice' => '', + 'service' => '', + 'support' => '', +]); +//소리관련 +define('AUDIOS', [ + 'Alram_GetEmail' => '', +]); +//Layout관련 +define('KEYWORD', '일본IDC 일본서버 일본 서버 일본호스팅 서버호스팅 디도스 공격 해외 호스팅 DDOS 방어 ddos 의뢰 디도스 보안 일본 단독서버 가상서버'); +define('LAYOUTS', [ + 'empty' => [ + 'title' => KEYWORD, + 'path' => 'layouts' . DIRECTORY_SEPARATOR . 'empty', + 'metas' => [ + '', + '', + '', + '', + '', + '', + '', + '', + '', + ], + 'stylesheets' => [ + '', + '', + '', + ], + 'javascripts' => [ + '', + ], + ], + 'front' => [ + 'title' => KEYWORD, + 'path' => 'layouts' . DIRECTORY_SEPARATOR . 'front', + 'topmenus' => ['aboutus', 'hosting', 'service', 'support'], + 'metas' => [ + '', + '', + '', + '', + '', + '', + '', + '', + '', + ], + 'stylesheets' => [ + '', + '', + '', + '', + '', + '', + '', + ], + 'javascripts' => [ + '', + '', + '', + '', + '', + ], + ], + 'admin' => [ + 'title' => '관리자화면', + 'path' => 'layouts' . DIRECTORY_SEPARATOR . 'admin', + 'metas' => [ + '', + '', + '', + '', + '', + '', + '', + '', + '', + ], + 'stylesheets' => [ + '', + '', + '', + '', + '', + '', + '', + ], + 'javascripts' => [ + '', + '', + '', + '', + '', + ], + ], +]); diff --git a/app/Config/ContentSecurityPolicy.php b/app/Config/ContentSecurityPolicy.php new file mode 100644 index 0000000..2ac41a7 --- /dev/null +++ b/app/Config/ContentSecurityPolicy.php @@ -0,0 +1,176 @@ +|string|null + */ + public $defaultSrc; + + /** + * Lists allowed scripts' URLs. + * + * @var list|string + */ + public $scriptSrc = 'self'; + + /** + * Lists allowed stylesheets' URLs. + * + * @var list|string + */ + public $styleSrc = 'self'; + + /** + * Defines the origins from which images can be loaded. + * + * @var list|string + */ + public $imageSrc = 'self'; + + /** + * Restricts the URLs that can appear in a page's `` element. + * + * Will default to self if not overridden + * + * @var list|string|null + */ + public $baseURI; + + /** + * Lists the URLs for workers and embedded frame contents + * + * @var list|string + */ + public $childSrc = 'self'; + + /** + * Limits the origins that you can connect to (via XHR, + * WebSockets, and EventSource). + * + * @var list|string + */ + public $connectSrc = 'self'; + + /** + * Specifies the origins that can serve web fonts. + * + * @var list|string + */ + public $fontSrc; + + /** + * Lists valid endpoints for submission from `
` tags. + * + * @var list|string + */ + public $formAction = 'self'; + + /** + * Specifies the sources that can embed the current page. + * This directive applies to ``, ` + + \ No newline at end of file diff --git a/app/Views/templates/admin/iframe_form_close.php b/app/Views/templates/admin/iframe_form_close.php new file mode 100644 index 0000000..48dc854 --- /dev/null +++ b/app/Views/templates/admin/iframe_form_close.php @@ -0,0 +1,8 @@ +extend("layouts/empty") ?> +section('content') ?> +
+
+

작업 완료 후 아래 버튼을 클릭하면 모달이 닫힙니다.

+ +
+endSection() ?> \ No newline at end of file diff --git a/app/Views/templates/admin/modal_form.php b/app/Views/templates/admin/modal_form.php new file mode 100644 index 0000000..b7753f0 --- /dev/null +++ b/app/Views/templates/admin/modal_form.php @@ -0,0 +1,61 @@ + + + + + \ No newline at end of file diff --git a/app/Views/templates/admin/modal_form_close.php b/app/Views/templates/admin/modal_form_close.php new file mode 100644 index 0000000..a48a201 --- /dev/null +++ b/app/Views/templates/admin/modal_form_close.php @@ -0,0 +1,8 @@ +extend("layouts/empty") ?> +section('content') ?> +
+
+

작업 완료 후 아래 버튼을 클릭하면 모달이 닫힙니다.

+ +
+endSection() ?> \ No newline at end of file diff --git a/app/Views/templates/download.php b/app/Views/templates/download.php new file mode 100644 index 0000000..3c52984 --- /dev/null +++ b/app/Views/templates/download.php @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + +
$field ?>
\ No newline at end of file diff --git a/app/Views/templates/front/footer.php b/app/Views/templates/front/footer.php new file mode 100644 index 0000000..7cdbd2f --- /dev/null +++ b/app/Views/templates/front/footer.php @@ -0,0 +1 @@ +getFlashdata(SESSION_NAMES['RETURN_MSG']) ? $viewDatas['helper']->alert($viewDatas['session']->getFlashdata(SESSION_NAMES['RETURN_MSG'])) : "" ?> \ No newline at end of file diff --git a/app/Views/templates/front/header.php b/app/Views/templates/front/header.php new file mode 100644 index 0000000..e35fef7 --- /dev/null +++ b/app/Views/templates/front/header.php @@ -0,0 +1,87 @@ + + \ No newline at end of file diff --git a/app/Views/templates/front/iframe_form.php b/app/Views/templates/front/iframe_form.php new file mode 100644 index 0000000..dd9bf7e --- /dev/null +++ b/app/Views/templates/front/iframe_form.php @@ -0,0 +1,29 @@ + + +
+ +
+ \ No newline at end of file diff --git a/app/Views/templates/front/iframe_form_close.php b/app/Views/templates/front/iframe_form_close.php new file mode 100644 index 0000000..48dc854 --- /dev/null +++ b/app/Views/templates/front/iframe_form_close.php @@ -0,0 +1,8 @@ +extend("layouts/empty") ?> +section('content') ?> +
+
+

작업 완료 후 아래 버튼을 클릭하면 모달이 닫힙니다.

+ +
+endSection() ?> \ No newline at end of file diff --git a/app/Views/templates/front/index_top.php b/app/Views/templates/front/index_top.php new file mode 100644 index 0000000..07de259 --- /dev/null +++ b/app/Views/templates/front/index_top.php @@ -0,0 +1,24 @@ + "get")) ?> + + \ No newline at end of file diff --git a/app/Views/templates/front/modal_form.php b/app/Views/templates/front/modal_form.php new file mode 100644 index 0000000..b7753f0 --- /dev/null +++ b/app/Views/templates/front/modal_form.php @@ -0,0 +1,61 @@ + + + + + \ No newline at end of file diff --git a/app/Views/templates/front/modal_form_close.php b/app/Views/templates/front/modal_form_close.php new file mode 100644 index 0000000..a48a201 --- /dev/null +++ b/app/Views/templates/front/modal_form_close.php @@ -0,0 +1,8 @@ +extend("layouts/empty") ?> +section('content') ?> +
+
+

작업 완료 후 아래 버튼을 클릭하면 모달이 닫힙니다.

+ +
+endSection() ?> \ No newline at end of file diff --git a/app/Views/welcome_message.php b/app/Views/welcome_message.php new file mode 100644 index 0000000..c18eca3 --- /dev/null +++ b/app/Views/welcome_message.php @@ -0,0 +1,331 @@ + + + + + Welcome to CodeIgniter 4! + + + + + + + + + + + +
+ + + +
+ +

Welcome to CodeIgniter

+ +

The small framework with powerful features

+ +
+ +
+ + + +
+ +

About this page

+ +

The page you are looking at is being generated dynamically by CodeIgniter.

+ +

If you would like to edit this page you will find it located at:

+ +
app/Views/welcome_message.php
+ +

The corresponding controller for this page can be found at:

+ +
app/Controllers/Home.php
+ +
+ +
+ +
+ +

Go further

+ +

+ + Learn +

+ +

The User Guide contains an introduction, tutorial, a number of "how to" + guides, and then reference documentation for the components that make up + the framework. Check the User Guide !

+ +

+ + Discuss +

+ +

CodeIgniter is a community-developed open source project, with several + venues for the community members to gather and exchange ideas. View all + the threads on CodeIgniter's forum, or chat on Slack !

+ +

+ + Contribute +

+ +

CodeIgniter is a community driven project and accepts contributions + of code and documentation from the community. Why not + + join us ?

+ +
+ +
+ + + +
+
+ +

Page rendered in {elapsed_time} seconds using {memory_usage} MB of memory.

+ +

Environment:

+ +
+ +
+ +

© CodeIgniter Foundation. CodeIgniter is open source project released under the MIT + open source licence.

+ +
+ +
+ + + + + + + + + diff --git a/app/index.html b/app/index.html new file mode 100644 index 0000000..69df4e1 --- /dev/null +++ b/app/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/builds b/builds new file mode 100644 index 0000000..cc2ca08 --- /dev/null +++ b/builds @@ -0,0 +1,125 @@ +#!/usr/bin/env php + 'vcs', + 'url' => GITHUB_URL, + ]; + } + + $array['require']['codeigniter4/codeigniter4'] = 'dev-develop'; + unset($array['require']['codeigniter4/framework']); + } else { + unset($array['minimum-stability']); + + if (isset($array['repositories'])) { + foreach ($array['repositories'] as $i => $repository) { + if ($repository['url'] === GITHUB_URL) { + unset($array['repositories'][$i]); + break; + } + } + + if (empty($array['repositories'])) { + unset($array['repositories']); + } + } + + $array['require']['codeigniter4/framework'] = LATEST_RELEASE; + unset($array['require']['codeigniter4/codeigniter4']); + } + + file_put_contents($file, json_encode($array, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . PHP_EOL); + + $modified[] = $file; + } else { + echo 'Warning: Unable to decode composer.json! Skipping...' . PHP_EOL; + } + } else { + echo 'Warning: Unable to read composer.json! Skipping...' . PHP_EOL; + } +} + +$files = [ + __DIR__ . DIRECTORY_SEPARATOR . 'app/Config/Paths.php', + __DIR__ . DIRECTORY_SEPARATOR . 'phpunit.xml.dist', + __DIR__ . DIRECTORY_SEPARATOR . 'phpunit.xml', +]; + +foreach ($files as $file) { + if (is_file($file)) { + $contents = file_get_contents($file); + + if ($dev) { + $contents = str_replace('vendor/codeigniter4/framework', 'vendor/codeigniter4/codeigniter4', $contents); + } else { + $contents = str_replace('vendor/codeigniter4/codeigniter4', 'vendor/codeigniter4/framework', $contents); + } + + file_put_contents($file, $contents); + + $modified[] = $file; + } +} + +if ($modified === []) { + echo 'No files modified.' . PHP_EOL; +} else { + echo 'The following files were modified:' . PHP_EOL; + + foreach ($modified as $file) { + echo " * {$file}" . PHP_EOL; + } + + echo 'Run `composer update` to sync changes with your vendor folder.' . PHP_EOL; +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..2dd91b8 --- /dev/null +++ b/composer.json @@ -0,0 +1,51 @@ +{ + "name": "codeigniter4/appstarter", + "description": "CodeIgniter4 starter app", + "license": "MIT", + "type": "project", + "homepage": "https://codeigniter.com", + "support": { + "forum": "https://forum.codeigniter.com/", + "source": "https://github.com/codeigniter4/CodeIgniter4", + "slack": "https://codeigniterchat.slack.com" + }, + "require": { + "php": "^8.3", + "cloudflare/sdk": "^1.3", + "codeigniter4/framework": "^4.5", + "google/apiclient": "^2.15.0", + "guzzlehttp/guzzle": "^7.9", + "phpoffice/phpspreadsheet": "^1.27", + "symfony/css-selector": "^7.1", + "symfony/dom-crawler": "^7.1", + "tinymce/tinymce": "^7.3" + }, + "require-dev": { + "fakerphp/faker": "^1.9", + "mikey179/vfsstream": "^1.6", + "phpunit/phpunit": "^10.5.16" + }, + "autoload": { + "psr-4": { + "App\\": "app/", + "Config\\": "app/Config/" + }, + "exclude-from-classmap": [ + "**/Database/Migrations/**" + ] + }, + "autoload-dev": { + "psr-4": { + "Tests\\Support\\": "tests/_support" + } + }, + "config": { + "optimize-autoloader": true, + "preferred-install": "dist", + "sort-packages": true, + "process-timeout": 600 + }, + "scripts": { + "test": "phpunit" + } +} \ No newline at end of file diff --git a/env b/env new file mode 100644 index 0000000..f359ec2 --- /dev/null +++ b/env @@ -0,0 +1,69 @@ +#-------------------------------------------------------------------- +# Example Environment Configuration file +# +# This file can be used as a starting point for your own +# custom .env files, and contains most of the possible settings +# available in a default install. +# +# By default, all of the settings are commented out. If you want +# to override the setting, you must un-comment it by removing the '#' +# at the beginning of the line. +#-------------------------------------------------------------------- + +#-------------------------------------------------------------------- +# ENVIRONMENT +#-------------------------------------------------------------------- + +# CI_ENVIRONMENT = production + +#-------------------------------------------------------------------- +# APP +#-------------------------------------------------------------------- + +# app.baseURL = '' +# If you have trouble with `.`, you could also use `_`. +# app_baseURL = '' +# app.forceGlobalSecureRequests = false +# app.CSPEnabled = false + +#-------------------------------------------------------------------- +# DATABASE +#-------------------------------------------------------------------- + +# database.default.hostname = localhost +# database.default.database = ci4 +# database.default.username = root +# database.default.password = root +# database.default.DBDriver = MySQLi +# database.default.DBPrefix = +# database.default.port = 3306 + +# If you use MySQLi as tests, first update the values of Config\Database::$tests. +# database.tests.hostname = localhost +# database.tests.database = ci4_test +# database.tests.username = root +# database.tests.password = root +# database.tests.DBDriver = MySQLi +# database.tests.DBPrefix = +# database.tests.charset = utf8mb4 +# database.tests.DBCollat = utf8mb4_general_ci +# database.tests.port = 3306 + +#-------------------------------------------------------------------- +# ENCRYPTION +#-------------------------------------------------------------------- + +# encryption.key = + +#-------------------------------------------------------------------- +# SESSION +#-------------------------------------------------------------------- + +# session.driver = 'CodeIgniter\Session\Handlers\FileHandler' +# session.savePath = null + +#-------------------------------------------------------------------- +# LOGGER +#-------------------------------------------------------------------- + +# logger.threshold = 4 diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..b408a99 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,63 @@ + + + + + + + + + + + + + ./tests + + + + + + + + + + ./app + + + ./app/Views + ./app/Config/Routes.php + + + + + + + + + + + + + + + diff --git a/preload.php b/preload.php new file mode 100644 index 0000000..75d86f5 --- /dev/null +++ b/preload.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +/* + *--------------------------------------------------------------- + * Sample file for Preloading + *--------------------------------------------------------------- + * See https://www.php.net/manual/en/opcache.preloading.php + * + * How to Use: + * 0. Copy this file to your project root folder. + * 1. Set the $paths property of the preload class below. + * 2. Set opcache.preload in php.ini. + * php.ini: + * opcache.preload=/path/to/preload.php + */ + +// Load the paths config file +require __DIR__ . '/app/Config/Paths.php'; + +// Path to the front controller +define('FCPATH', __DIR__ . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR); + +class preload +{ + /** + * @var array Paths to preload. + */ + private array $paths = [ + [ + 'include' => __DIR__ . '/vendor/codeigniter4/framework/system', // Change this path if using manual installation + 'exclude' => [ + '/system/bootstrap.php', + // Not needed if you don't use them. + '/system/Database/OCI8/', + '/system/Database/Postgre/', + '/system/Database/SQLite3/', + '/system/Database/SQLSRV/', + // Not needed. + '/system/Database/Seeder.php', + '/system/Test/', + '/system/Language/', + '/system/CLI/', + '/system/Commands/', + '/system/Publisher/', + '/system/ComposerScripts.php', + '/Views/', + // Errors occur. + '/system/Config/Routes.php', + '/system/ThirdParty/', + ], + ], + ]; + + public function __construct() + { + $this->loadAutoloader(); + } + + private function loadAutoloader(): void + { + $paths = new Config\Paths(); + require rtrim($paths->systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'Boot.php'; + + CodeIgniter\Boot::preload($paths); + } + + /** + * Load PHP files. + */ + public function load(): void + { + foreach ($this->paths as $path) { + $directory = new RecursiveDirectoryIterator($path['include']); + $fullTree = new RecursiveIteratorIterator($directory); + $phpFiles = new RegexIterator( + $fullTree, + '/.+((? $file) { + foreach ($path['exclude'] as $exclude) { + if (str_contains($file[0], $exclude)) { + continue 2; + } + } + + require_once $file[0]; + echo 'Loaded: ' . $file[0] . "\n"; + } + } + } +} + +(new preload())->load(); diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..abac3cb --- /dev/null +++ b/public/.htaccess @@ -0,0 +1,49 @@ +# Disable directory browsing +Options -Indexes + +# ---------------------------------------------------------------------- +# Rewrite engine +# ---------------------------------------------------------------------- + +# Turning on the rewrite engine is necessary for the following rules and features. +# FollowSymLinks must be enabled for this to work. + + Options +FollowSymlinks + RewriteEngine On + + # If you installed CodeIgniter in a subfolder, you will need to + # change the following line to match the subfolder you need. + # http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritebase + # RewriteBase / + + # Redirect Trailing Slashes... + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_URI} (.+)/$ + RewriteRule ^ %1 [L,R=301] + + # Rewrite "www.example.com -> example.com" + RewriteCond %{HTTPS} !=on + RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] + RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L] + + # Checks to see if the user is attempting to access a valid file, + # such as an image or css document, if this isn't true it sends the + # request to the front controller, index.php + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule ^([\s\S]*)$ index.php/$1 [L,NC,QSA] + + # Ensure Authorization header is passed along + RewriteCond %{HTTP:Authorization} . + RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] + + + + # If we don't have mod_rewrite installed, all 404's + # can be sent to index.php, and everything works as normal. + ErrorDocument 404 index.php + + +# Disable server signature start +ServerSignature Off +# Disable server signature end diff --git a/public/css/admin.css b/public/css/admin.css new file mode 100644 index 0000000..b1cbc75 --- /dev/null +++ b/public/css/admin.css @@ -0,0 +1,83 @@ +/* ------------------------------------------------------------ + * Name : admin.css + * Desc : Admin StyleSheet + * Created : 2016/9/11 Tri-aBility by Junheum,Choi + * Updated : + ------------------------------------------------------------ */ +* { + margin: 0px; + padding: 0px; + border: 0px; + /* font-size: 15px; */ +} + +html, +body { + height: 100%; +} + +div.top { + height: 51px; + margin-bottom: 10px; + border-top: 1px solid gray; + border-bottom: 1px solid gray; + background-color: #e8e9ea; +} + +div.middle { + /* border: 1px solid blue; */ +} + +/* div.middle div.left { + border: 1px solid red; +} */ + +div.middle div.right { + width: 100%; + /* overflow: auto; */ + /* border: 1px solid blue; */ +} + +div.middle div.right div.header { + /*content 헤더라인*/ + height: 55px; + padding-top: 15px; + background-color: #e7e7e7; + border-top: 1px solid gray; + border-left: 1px solid gray; + border-right: 1px solid gray; + border-radius: 15px 15px 0px 0px; +} + +div.middle div.right div.header li.nav-item { + height: 40px; +} + +div.middle div.right div.content { + /*content 부분*/ + padding-top: 15px; + padding-left: 23px; + padding-right: 15px; + padding-bottom: 15px; + border-left: 1px solid gray; + border-right: 1px solid gray; + background-color: white; +} + +div.middle div.right div.footer { + /*content 하단라인*/ + height: 20px; + border-left: 1px solid gray; + border-right: 1px solid gray; + border-bottom: 1px solid gray; + border-radius: 0px 0px 15px 15px; +} + +div.bottom { + height: 51px; + margin-top: 10px; + border-top: 1px solid gray; + border-bottom: 1px solid gray; + background-color: #efefef; + background-color: #e8e9ea; +} \ No newline at end of file diff --git a/public/css/admin/form.css b/public/css/admin/form.css new file mode 100644 index 0000000..7440ad5 --- /dev/null +++ b/public/css/admin/form.css @@ -0,0 +1,28 @@ +/* create,modify,view 페이지용 */ +div.action_form { + /* 블록 요소로 변경 */ + margin-left: auto; + /* 자동 여백을 이용한 가로 가운데 정렬 */ + margin-right: auto; + /* 자동 여백을 이용한 가로 가운데 정렬 */ + /* border: 1px solid blue; */ + /* table-layout: fixed; 고정 레이아웃 */ + border-collapse: collapse; + /* 테두리 결합 */ +} + +div.action_form table {} + +div.action_form table th { + background-color: #f0f0f0; +} + +div.action_form table td { + text-align: center; + word-wrap: break-word; + /* 긴 단어 강제 줄바꿈 */ + white-space: normal; + /* 자동 줄바꿈 */ +} + +/* create,modify,view 페이지용 */ \ No newline at end of file diff --git a/public/css/admin/index.css b/public/css/admin/index.css new file mode 100644 index 0000000..c759c4b --- /dev/null +++ b/public/css/admin/index.css @@ -0,0 +1,157 @@ +/* create,modify,view 페이지용 */ +table.action_form { + /* 블록 요소로 변경 */ + margin-left: auto; + /* 자동 여백을 이용한 가로 가운데 정렬 */ + margin-right: auto; + /* 자동 여백을 이용한 가로 가운데 정렬 */ + /* border: 1px solid blue; */ + /* table-layout: fixed; 고정 레이아웃 */ + border-collapse: collapse; + /* 테두리 결합 */ +} + +table.action_form th { + text-align: center; + background-color: #f5f5f5; +} + +table.action_form td { + text-align: center; + word-wrap: break-word; + /* 긴 단어 강제 줄바꿈 */ + white-space: normal; + /* 자동 줄바꿈 */ +} + +/* create,modify,view 페이지용 */ + +/*조건검색*/ +nav.index_top nav.condition { + border-color: 1px solid red; +} + +/*검색*/ +nav.index_top nav.search { + position: relative; + height: 30px; + border-color: 1px solid red; +} + +nav.index_top nav.search input[type="text"] { + width: 200px; + height: 30px; +} + +/*검색submit*/ +nav.index_top nav.search input[type="submit"] { + font-weight: bold; + width: 80px; + height: 30px; + color: white; + background-color: #555555; +} + +/*검색submit*/ +nav.index_top nav.search a.excel { + position: absolute; + top: -9px; + right: -45px; + /* border-color: 1px solid red; */ +} + +/*페이지정보*/ +nav.index_top nav.pageinfo { + font-weight: bold; + /* border-color: 1px solid red; */ +} + +/* Table 부분 */ +table.index_table { + width: 100%; + /* table-layout: fixed; */ + border-collapse: collapse; +} + +table.index_table thead th { + white-space: nowrap; + padding-top: 15px; + padding-bottom: 15px; + font-weight: bold; + border-top: 2px solid black; + border-bottom: 1px solid silver; + background-color: #f5f5f5; + text-align: center; + /* border:1px solid silver; */ +} + +table.index_table thead th.index_head_short_column { + width: 80px; +} + +table.index_table thead th:active { + cursor: grabbing; +} + +div.index_batchjob { + padding-top: 15px; + text-align: center; + /* border: 1px solid red; */ +} + +div.index_pagination { + margin-top: 20px; + /* border: 1px solid red; */ +} + +div.index_pagination ul.pagination { + /* border: 1px solid green; */ + width: fit-content; + /* UL의 너비를 내용에 맞춤 */ + margin: 0 auto; + /* 좌우 마진을 자동으로 설정하여 중앙 배치 */ + padding: 0; + list-style: none; + /* 기본 점 스타일 제거 (옵션) */ +} + +div.index_pagination ul.pagination li { + margin-left: 5px; +} + +div.index_pagination ul.pagination li a { + padding: 5px 10px 5px 10px; + font-size: 1.5rem; + color: white; + background-color: #808080; +} + +div.index_pagination ul.pagination li a:hover { + border: 1px solid black; +} + +div.index_pagination ul.pagination li.active a { + color: black; + border: 1px solid #808080; +} + +div.index_bottom { + padding-top: 15px; + text-align: center; + word-wrap: break-word; + /* 긴 단어 강제 줄바꿈 */ + white-space: normal; + /* 자동 줄바꿈 */ + /* border: 1px solid red; */ +} + +div.index_bottom div.index_action_form { + margin-top: 20px; + /* border: 1px solid red; */ +} + +div.index_bottom div.index_action_form iframe { + width: 100%; + border: none; + /* border: 1px solid blue; */ +} \ No newline at end of file diff --git a/public/css/admin/left_menu.css b/public/css/admin/left_menu.css new file mode 100644 index 0000000..cc89e40 --- /dev/null +++ b/public/css/admin/left_menu.css @@ -0,0 +1,56 @@ +div#left_menu { + position: fixed; + margin-top: 60px; + z-index: 100; + border: 1px solid silver; +} + +div#left_menu div#menu_button { + position: absolute; + top: -1px; + right: -21px; + width: 20px; + height: 160px; + cursor: pointer; + writing-mode: vertical-rl; + /* 세로로 글자를 출력 */ + text-orientation: upright; + /* 글자가 직립되도록 설정 */ + border-top: 1px solid silver; + border-right: 1px solid silver; + border-bottom: 1px solid silver; + border-radius: 0px 5px 5px 0px; + background-color: #e8e9ea; +} + +div#left_menu div.accordion { + display: none; + width: 20px; +} + +div#left_menu div.accordion div.main { + height: 50px; + padding-top: 15px; + padding-left: 10px; + background-color: white; + border-bottom: 1px solid silver; +} + +div#left_menu div.accordion div.accordion-item { + height: 50px; + padding-top: 15px; + background-color: #eeeeee; + border-bottom: 1px solid silver; +} + +div#left_menu div.accordion div.accordion-item:hover { + background-color: silver; +} + +div#left_menu div.accordion div.accordion-item a { + padding-left: 20px; +} + +div#left_menu div.accordion div.accordion-collapse a { + padding-left: 30px; +} \ No newline at end of file diff --git a/public/css/admin/member_link.css b/public/css/admin/member_link.css new file mode 100644 index 0000000..38ed839 --- /dev/null +++ b/public/css/admin/member_link.css @@ -0,0 +1,17 @@ +nav.top_menu ul.member-link{ + /* border:1px solid red; */ + color:#3a37f3; + padding-right:20px; +} + +nav.top_menu ul.member-link a{ + color:#3a37f3; +} + +nav.top_menu ul.member-link ul.dropdown-menu li:hover{ + background-color: #eaeaea; +} + +nav.top_menu ul.member-link ul.dropdown-menu li a{ + padding-left:10px; +} \ No newline at end of file diff --git a/public/css/common/resizeTable.css b/public/css/common/resizeTable.css new file mode 100644 index 0000000..8c4e075 --- /dev/null +++ b/public/css/common/resizeTable.css @@ -0,0 +1,67 @@ +.rtc-wrapper table.rtc-table { + border-collapse: collapse; + white-space: nowrap; + margin: 0; +} + +.rtc-wrapper table.rtc-table thead, +.rtc-wrapper table.rtc-table tbody, +.rtc-wrapper table.rtc-table tfoot { + margin: 0; +} + +.rtc-wrapper table.rtc-table thead tr, +.rtc-wrapper table.rtc-table tbody tr, +.rtc-wrapper table.rtc-table tfoot tr { + margin: 0; +} + +.rtc-wrapper table.rtc-table thead tr th, +.rtc-wrapper table.rtc-table thead tr td, +.rtc-wrapper table.rtc-table tbody tr th, +.rtc-wrapper table.rtc-table tbody tr td, +.rtc-wrapper table.rtc-table tfoot tr th, +.rtc-wrapper table.rtc-table tfoot tr td { + margin: 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.rtc-wrapper table.rtc-table.rtc-table-resizing { + cursor: col-resize; +} + +.rtc-wrapper table.rtc-table.rtc-table-resizing thead, +.rtc-wrapper table.rtc-table.rtc-table-resizing thead > th, +.rtc-wrapper table.rtc-table.rtc-table-resizing thead > th > a { + cursor: col-resize; +} + +.rtc-wrapper table.rtc-table thead tr.invisible, +.rtc-wrapper table.rtc-table thead tr.invisible th { + border: none; + margin: 0; + padding: 0; + height: 0 !important; +} + +.rtc-wrapper .rtc-handle-container { + position: relative; + padding: 0; + margin: 0; + border: 0; +} + +.rtc-wrapper .rtc-handle-container .rtc-handle { + position: absolute; + width: 6.5px; + margin-left: -3.575px; + z-index: 2; + cursor: col-resize; +} + +.rtc-wrapper .rtc-handle-container .rtc-handle:last-of-type { + width: 4.5px; + margin-left: -4.95px; +} \ No newline at end of file diff --git a/public/css/common/style.css b/public/css/common/style.css new file mode 100644 index 0000000..54b28ae --- /dev/null +++ b/public/css/common/style.css @@ -0,0 +1,55 @@ +/* ------------------------------------------------------------ + * Name : admin.css + * Desc : Admin StyleSheet + * Created : 2016/9/11 Tri-aBility by Junheum,Choi + * Updated : + ------------------------------------------------------------ */ +@charset "utf-8"; + +/* user class */ +h1, +h2, +h3, +h4, +h5, +h6, +strong, +th, +.bold { + font-weight: 500; +} + +input[type=text], +input[type=password] { + display: inline-block; + border: 1px solid #ccc; + border-radius: 4px; + box-sizing: border-box; + white-space: nowrap; +} + +select, +textarea, +button { + display: inline-block; + border: 1px solid #ccc; + border-radius: 4px; + box-sizing: border-box; + white-space: nowrap; +} + +a:link { + text-decoration: none; +} + +a:visited { + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a:active { + text-decoration: underline; +} \ No newline at end of file diff --git a/public/css/empty.css b/public/css/empty.css new file mode 100644 index 0000000..c110333 --- /dev/null +++ b/public/css/empty.css @@ -0,0 +1,12 @@ +/* ------------------------------------------------------------ + * Name : admin.css + * Desc : Admin StyleSheet + * Created : 2016/9/11 Tri-aBility by Junheum,Choi + * Updated : + ------------------------------------------------------------ */ +* { + margin: 0px; + padding: 0px; + border: 0px; + /* font-size: 15px; */ +} \ No newline at end of file diff --git a/public/css/front.css b/public/css/front.css new file mode 100644 index 0000000..403d3ad --- /dev/null +++ b/public/css/front.css @@ -0,0 +1,74 @@ +/* ------------------------------------------------------------ + * Name : admin.css + * Desc : Admin StyleSheet + * Created : 2016/9/11 Tri-aBility by Junheum,Choi + * Updated : + ------------------------------------------------------------ */ +* { + margin: 0px; + padding: 0px; + border: 0px; + /* font-size: 15px; */ +} + +html, +body { + height: 100%; +} + +div.top { + height: 51px; + margin-bottom: 10px; + border-top: 1px solid gray; + border-bottom: 1px solid gray; + background-color: #e8e9ea; +} + +div.middle { + /* border: 1px solid red; */ +} + +div.middle div.header { + /*content 헤더라인*/ + height: 55px; + padding-top: 15px; + background-color: #e7e7e7; + border-top: 1px solid gray; + border-left: 1px solid gray; + border-right: 1px solid gray; + border-radius: 15px 15px 0px 0px; +} + +div.middle div.header li.nav-item { + height: 40px; +} + +div.middle div.content { + /*content 부분*/ + padding-top: 15px; + padding-left: 23px; + padding-right: 15px; + padding-bottom: 15px; + border-left: 1px solid gray; + border-right: 1px solid gray; + background-color: white; + border: 1px solid red; +} + +div.middle div.footer { + /*content 하단라인*/ + height: 20px; + border-left: 1px solid gray; + border-right: 1px solid gray; + border-bottom: 1px solid gray; + border-radius: 0px 0px 15px 15px; +} + +div.bottom { + height: 51px; + margin-top: 10px; + border-top: 1px solid gray; + border-bottom: 1px solid gray; + background-color: #efefef; + background-color: #e8e9ea; +} \ No newline at end of file diff --git a/public/css/front/copyright.css b/public/css/front/copyright.css new file mode 100644 index 0000000..45a4a77 --- /dev/null +++ b/public/css/front/copyright.css @@ -0,0 +1,29 @@ +div#copyright{ + width:100%; + height:300px; + padding-top:30px; + padding-bottom:30px; + background-color:#2d2e2e; + color:white; +} + +div#copyright div#content_bottom{ + color:white; + text-align:left; + /* border-left:1px solid silver; + border-right:1px solid silver; */ +} + +div#copyright div#content_bottom .item{ + padding-top:5px; + padding-left:5px; + padding-right:5px; + border-top:1px solid silver; + border-left:1px solid silver; + border-right:1px solid silver; +} + +div#copyright div#content_bottom div.company_info{ + padding:10px; + border:1px solid silver; +} diff --git a/public/css/front/form.css b/public/css/front/form.css new file mode 100644 index 0000000..7440ad5 --- /dev/null +++ b/public/css/front/form.css @@ -0,0 +1,28 @@ +/* create,modify,view 페이지용 */ +div.action_form { + /* 블록 요소로 변경 */ + margin-left: auto; + /* 자동 여백을 이용한 가로 가운데 정렬 */ + margin-right: auto; + /* 자동 여백을 이용한 가로 가운데 정렬 */ + /* border: 1px solid blue; */ + /* table-layout: fixed; 고정 레이아웃 */ + border-collapse: collapse; + /* 테두리 결합 */ +} + +div.action_form table {} + +div.action_form table th { + background-color: #f0f0f0; +} + +div.action_form table td { + text-align: center; + word-wrap: break-word; + /* 긴 단어 강제 줄바꿈 */ + white-space: normal; + /* 자동 줄바꿈 */ +} + +/* create,modify,view 페이지용 */ \ No newline at end of file diff --git a/public/css/front/index.css b/public/css/front/index.css new file mode 100644 index 0000000..c759c4b --- /dev/null +++ b/public/css/front/index.css @@ -0,0 +1,157 @@ +/* create,modify,view 페이지용 */ +table.action_form { + /* 블록 요소로 변경 */ + margin-left: auto; + /* 자동 여백을 이용한 가로 가운데 정렬 */ + margin-right: auto; + /* 자동 여백을 이용한 가로 가운데 정렬 */ + /* border: 1px solid blue; */ + /* table-layout: fixed; 고정 레이아웃 */ + border-collapse: collapse; + /* 테두리 결합 */ +} + +table.action_form th { + text-align: center; + background-color: #f5f5f5; +} + +table.action_form td { + text-align: center; + word-wrap: break-word; + /* 긴 단어 강제 줄바꿈 */ + white-space: normal; + /* 자동 줄바꿈 */ +} + +/* create,modify,view 페이지용 */ + +/*조건검색*/ +nav.index_top nav.condition { + border-color: 1px solid red; +} + +/*검색*/ +nav.index_top nav.search { + position: relative; + height: 30px; + border-color: 1px solid red; +} + +nav.index_top nav.search input[type="text"] { + width: 200px; + height: 30px; +} + +/*검색submit*/ +nav.index_top nav.search input[type="submit"] { + font-weight: bold; + width: 80px; + height: 30px; + color: white; + background-color: #555555; +} + +/*검색submit*/ +nav.index_top nav.search a.excel { + position: absolute; + top: -9px; + right: -45px; + /* border-color: 1px solid red; */ +} + +/*페이지정보*/ +nav.index_top nav.pageinfo { + font-weight: bold; + /* border-color: 1px solid red; */ +} + +/* Table 부분 */ +table.index_table { + width: 100%; + /* table-layout: fixed; */ + border-collapse: collapse; +} + +table.index_table thead th { + white-space: nowrap; + padding-top: 15px; + padding-bottom: 15px; + font-weight: bold; + border-top: 2px solid black; + border-bottom: 1px solid silver; + background-color: #f5f5f5; + text-align: center; + /* border:1px solid silver; */ +} + +table.index_table thead th.index_head_short_column { + width: 80px; +} + +table.index_table thead th:active { + cursor: grabbing; +} + +div.index_batchjob { + padding-top: 15px; + text-align: center; + /* border: 1px solid red; */ +} + +div.index_pagination { + margin-top: 20px; + /* border: 1px solid red; */ +} + +div.index_pagination ul.pagination { + /* border: 1px solid green; */ + width: fit-content; + /* UL의 너비를 내용에 맞춤 */ + margin: 0 auto; + /* 좌우 마진을 자동으로 설정하여 중앙 배치 */ + padding: 0; + list-style: none; + /* 기본 점 스타일 제거 (옵션) */ +} + +div.index_pagination ul.pagination li { + margin-left: 5px; +} + +div.index_pagination ul.pagination li a { + padding: 5px 10px 5px 10px; + font-size: 1.5rem; + color: white; + background-color: #808080; +} + +div.index_pagination ul.pagination li a:hover { + border: 1px solid black; +} + +div.index_pagination ul.pagination li.active a { + color: black; + border: 1px solid #808080; +} + +div.index_bottom { + padding-top: 15px; + text-align: center; + word-wrap: break-word; + /* 긴 단어 강제 줄바꿈 */ + white-space: normal; + /* 자동 줄바꿈 */ + /* border: 1px solid red; */ +} + +div.index_bottom div.index_action_form { + margin-top: 20px; + /* border: 1px solid red; */ +} + +div.index_bottom div.index_action_form iframe { + width: 100%; + border: none; + /* border: 1px solid blue; */ +} \ No newline at end of file diff --git a/public/css/front/left_menu.css b/public/css/front/left_menu.css new file mode 100644 index 0000000..cc89e40 --- /dev/null +++ b/public/css/front/left_menu.css @@ -0,0 +1,56 @@ +div#left_menu { + position: fixed; + margin-top: 60px; + z-index: 100; + border: 1px solid silver; +} + +div#left_menu div#menu_button { + position: absolute; + top: -1px; + right: -21px; + width: 20px; + height: 160px; + cursor: pointer; + writing-mode: vertical-rl; + /* 세로로 글자를 출력 */ + text-orientation: upright; + /* 글자가 직립되도록 설정 */ + border-top: 1px solid silver; + border-right: 1px solid silver; + border-bottom: 1px solid silver; + border-radius: 0px 5px 5px 0px; + background-color: #e8e9ea; +} + +div#left_menu div.accordion { + display: none; + width: 20px; +} + +div#left_menu div.accordion div.main { + height: 50px; + padding-top: 15px; + padding-left: 10px; + background-color: white; + border-bottom: 1px solid silver; +} + +div#left_menu div.accordion div.accordion-item { + height: 50px; + padding-top: 15px; + background-color: #eeeeee; + border-bottom: 1px solid silver; +} + +div#left_menu div.accordion div.accordion-item:hover { + background-color: silver; +} + +div#left_menu div.accordion div.accordion-item a { + padding-left: 20px; +} + +div#left_menu div.accordion div.accordion-collapse a { + padding-left: 30px; +} \ No newline at end of file diff --git a/public/css/front/login.css b/public/css/front/login.css new file mode 100644 index 0000000..2001247 --- /dev/null +++ b/public/css/front/login.css @@ -0,0 +1,17 @@ +.login-wrapper { + display: flex; + justify-content: center; + align-items: center; + height: 100vh; +} + +.login-container { + width: 400px; + height: 400px; + overflow-y: auto; + /* 추가된 스타일 */ + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} \ No newline at end of file diff --git a/public/css/front/member_link.css b/public/css/front/member_link.css new file mode 100644 index 0000000..38ed839 --- /dev/null +++ b/public/css/front/member_link.css @@ -0,0 +1,17 @@ +nav.top_menu ul.member-link{ + /* border:1px solid red; */ + color:#3a37f3; + padding-right:20px; +} + +nav.top_menu ul.member-link a{ + color:#3a37f3; +} + +nav.top_menu ul.member-link ul.dropdown-menu li:hover{ + background-color: #eaeaea; +} + +nav.top_menu ul.member-link ul.dropdown-menu li a{ + padding-left:10px; +} \ No newline at end of file diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..7ecfce2 Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/images/auth/google_login_button.png b/public/images/auth/google_login_button.png new file mode 100644 index 0000000..c19f257 Binary files /dev/null and b/public/images/auth/google_login_button.png differ diff --git a/public/images/banner/sub_visual1.jpg b/public/images/banner/sub_visual1.jpg new file mode 100644 index 0000000..df85468 Binary files /dev/null and b/public/images/banner/sub_visual1.jpg differ diff --git a/public/images/banner/sub_visual2.jpg b/public/images/banner/sub_visual2.jpg new file mode 100644 index 0000000..8699f2b Binary files /dev/null and b/public/images/banner/sub_visual2.jpg differ diff --git a/public/images/banner/sub_visual3.jpg b/public/images/banner/sub_visual3.jpg new file mode 100644 index 0000000..4ee3220 Binary files /dev/null and b/public/images/banner/sub_visual3.jpg differ diff --git a/public/images/banner/sub_visual4.jpg b/public/images/banner/sub_visual4.jpg new file mode 100644 index 0000000..6708503 Binary files /dev/null and b/public/images/banner/sub_visual4.jpg differ diff --git a/public/images/common/adminbg.png b/public/images/common/adminbg.png new file mode 100644 index 0000000..68c6a93 Binary files /dev/null and b/public/images/common/adminbg.png differ diff --git a/public/images/common/btn_login.png b/public/images/common/btn_login.png new file mode 100644 index 0000000..c0b2782 Binary files /dev/null and b/public/images/common/btn_login.png differ diff --git a/public/images/common/discord.png b/public/images/common/discord.png new file mode 100644 index 0000000..4a2233c Binary files /dev/null and b/public/images/common/discord.png differ diff --git a/public/images/common/excel.png b/public/images/common/excel.png new file mode 100644 index 0000000..e67fc00 Binary files /dev/null and b/public/images/common/excel.png differ diff --git a/public/images/common/kakaotalk.png b/public/images/common/kakaotalk.png new file mode 100644 index 0000000..cf7a87c Binary files /dev/null and b/public/images/common/kakaotalk.png differ diff --git a/public/images/common/menu_on.gif b/public/images/common/menu_on.gif new file mode 100644 index 0000000..b6216bb Binary files /dev/null and b/public/images/common/menu_on.gif differ diff --git a/public/images/common/pdf.png b/public/images/common/pdf.png new file mode 100644 index 0000000..bb18a19 Binary files /dev/null and b/public/images/common/pdf.png differ diff --git a/public/images/common/telegram.png b/public/images/common/telegram.png new file mode 100644 index 0000000..c88f3fa Binary files /dev/null and b/public/images/common/telegram.png differ diff --git a/public/images/common/top.png b/public/images/common/top.png new file mode 100644 index 0000000..84d194d Binary files /dev/null and b/public/images/common/top.png differ diff --git a/public/images/common/top_skype.png b/public/images/common/top_skype.png new file mode 100644 index 0000000..90355c0 Binary files /dev/null and b/public/images/common/top_skype.png differ diff --git a/public/images/logo/android-icon-144x144.png b/public/images/logo/android-icon-144x144.png new file mode 100644 index 0000000..3e09df3 Binary files /dev/null and b/public/images/logo/android-icon-144x144.png differ diff --git a/public/images/logo/android-icon-192x192.png b/public/images/logo/android-icon-192x192.png new file mode 100644 index 0000000..1aacd55 Binary files /dev/null and b/public/images/logo/android-icon-192x192.png differ diff --git a/public/images/logo/android-icon-36x36.png b/public/images/logo/android-icon-36x36.png new file mode 100644 index 0000000..701b1b6 Binary files /dev/null and b/public/images/logo/android-icon-36x36.png differ diff --git a/public/images/logo/android-icon-48x48.png b/public/images/logo/android-icon-48x48.png new file mode 100644 index 0000000..9d526d3 Binary files /dev/null and b/public/images/logo/android-icon-48x48.png differ diff --git a/public/images/logo/android-icon-72x72.png b/public/images/logo/android-icon-72x72.png new file mode 100644 index 0000000..15896b5 Binary files /dev/null and b/public/images/logo/android-icon-72x72.png differ diff --git a/public/images/logo/android-icon-96x96.png b/public/images/logo/android-icon-96x96.png new file mode 100644 index 0000000..627d135 Binary files /dev/null and b/public/images/logo/android-icon-96x96.png differ diff --git a/public/images/logo/apple-icon-114x114.png b/public/images/logo/apple-icon-114x114.png new file mode 100644 index 0000000..5e38c56 Binary files /dev/null and b/public/images/logo/apple-icon-114x114.png differ diff --git a/public/images/logo/apple-icon-120x120.png b/public/images/logo/apple-icon-120x120.png new file mode 100644 index 0000000..590102a Binary files /dev/null and b/public/images/logo/apple-icon-120x120.png differ diff --git a/public/images/logo/apple-icon-144x144.png b/public/images/logo/apple-icon-144x144.png new file mode 100644 index 0000000..e57cbfe Binary files /dev/null and b/public/images/logo/apple-icon-144x144.png differ diff --git a/public/images/logo/apple-icon-152x152.png b/public/images/logo/apple-icon-152x152.png new file mode 100644 index 0000000..28c2e43 Binary files /dev/null and b/public/images/logo/apple-icon-152x152.png differ diff --git a/public/images/logo/apple-icon-180x180.png b/public/images/logo/apple-icon-180x180.png new file mode 100644 index 0000000..f620e91 Binary files /dev/null and b/public/images/logo/apple-icon-180x180.png differ diff --git a/public/images/logo/apple-icon-57x57.png b/public/images/logo/apple-icon-57x57.png new file mode 100644 index 0000000..112e893 Binary files /dev/null and b/public/images/logo/apple-icon-57x57.png differ diff --git a/public/images/logo/apple-icon-60x60.png b/public/images/logo/apple-icon-60x60.png new file mode 100644 index 0000000..9f74028 Binary files /dev/null and b/public/images/logo/apple-icon-60x60.png differ diff --git a/public/images/logo/apple-icon-72x72.png b/public/images/logo/apple-icon-72x72.png new file mode 100644 index 0000000..336828b Binary files /dev/null and b/public/images/logo/apple-icon-72x72.png differ diff --git a/public/images/logo/apple-icon-76x76.png b/public/images/logo/apple-icon-76x76.png new file mode 100644 index 0000000..d6e83f0 Binary files /dev/null and b/public/images/logo/apple-icon-76x76.png differ diff --git a/public/images/logo/apple-icon-precomposed.png b/public/images/logo/apple-icon-precomposed.png new file mode 100644 index 0000000..c54f500 Binary files /dev/null and b/public/images/logo/apple-icon-precomposed.png differ diff --git a/public/images/logo/apple-icon.png b/public/images/logo/apple-icon.png new file mode 100644 index 0000000..c54f500 Binary files /dev/null and b/public/images/logo/apple-icon.png differ diff --git a/public/images/logo/favicon-16x16.png b/public/images/logo/favicon-16x16.png new file mode 100644 index 0000000..d467493 Binary files /dev/null and b/public/images/logo/favicon-16x16.png differ diff --git a/public/images/logo/favicon-32x32.png b/public/images/logo/favicon-32x32.png new file mode 100644 index 0000000..67d0fb9 Binary files /dev/null and b/public/images/logo/favicon-32x32.png differ diff --git a/public/images/logo/favicon-96x96.png b/public/images/logo/favicon-96x96.png new file mode 100644 index 0000000..9b931ec Binary files /dev/null and b/public/images/logo/favicon-96x96.png differ diff --git a/public/images/logo/favicon.ico b/public/images/logo/favicon.ico new file mode 100644 index 0000000..7de9353 Binary files /dev/null and b/public/images/logo/favicon.ico differ diff --git a/public/images/logo/logo-small.png b/public/images/logo/logo-small.png new file mode 100644 index 0000000..0b33a25 Binary files /dev/null and b/public/images/logo/logo-small.png differ diff --git a/public/images/logo/ms-icon-144x144.png b/public/images/logo/ms-icon-144x144.png new file mode 100644 index 0000000..e57cbfe Binary files /dev/null and b/public/images/logo/ms-icon-144x144.png differ diff --git a/public/images/logo/ms-icon-150x150.png b/public/images/logo/ms-icon-150x150.png new file mode 100644 index 0000000..0c02de9 Binary files /dev/null and b/public/images/logo/ms-icon-150x150.png differ diff --git a/public/images/logo/ms-icon-310x310.png b/public/images/logo/ms-icon-310x310.png new file mode 100644 index 0000000..a1c230b Binary files /dev/null and b/public/images/logo/ms-icon-310x310.png differ diff --git a/public/images/logo/ms-icon-70x70.png b/public/images/logo/ms-icon-70x70.png new file mode 100644 index 0000000..500895a Binary files /dev/null and b/public/images/logo/ms-icon-70x70.png differ diff --git a/public/images/main/bg_bnr.jpg b/public/images/main/bg_bnr.jpg new file mode 100644 index 0000000..70e0e16 Binary files /dev/null and b/public/images/main/bg_bnr.jpg differ diff --git a/public/images/main/bg_notice.gif b/public/images/main/bg_notice.gif new file mode 100644 index 0000000..8eaf4f4 Binary files /dev/null and b/public/images/main/bg_notice.gif differ diff --git a/public/images/main/icon1.png b/public/images/main/icon1.png new file mode 100644 index 0000000..dbdb2c7 Binary files /dev/null and b/public/images/main/icon1.png differ diff --git a/public/images/main/icon2.png b/public/images/main/icon2.png new file mode 100644 index 0000000..bc56142 Binary files /dev/null and b/public/images/main/icon2.png differ diff --git a/public/images/main/icon3.png b/public/images/main/icon3.png new file mode 100644 index 0000000..ccdcecf Binary files /dev/null and b/public/images/main/icon3.png differ diff --git a/public/images/main/visual1.jpg b/public/images/main/visual1.jpg new file mode 100644 index 0000000..e9c72fa Binary files /dev/null and b/public/images/main/visual1.jpg differ diff --git a/public/images/main/visual2.jpg b/public/images/main/visual2.jpg new file mode 100644 index 0000000..b78e8c4 Binary files /dev/null and b/public/images/main/visual2.jpg differ diff --git a/public/images/main/visual3.jpg b/public/images/main/visual3.jpg new file mode 100644 index 0000000..0911c90 Binary files /dev/null and b/public/images/main/visual3.jpg differ diff --git a/public/images/sub/com_icon1.png b/public/images/sub/com_icon1.png new file mode 100644 index 0000000..bd7b57a Binary files /dev/null and b/public/images/sub/com_icon1.png differ diff --git a/public/images/sub/com_icon2.png b/public/images/sub/com_icon2.png new file mode 100644 index 0000000..fa77ce2 Binary files /dev/null and b/public/images/sub/com_icon2.png differ diff --git a/public/images/sub/com_icon3.png b/public/images/sub/com_icon3.png new file mode 100644 index 0000000..eb662cd Binary files /dev/null and b/public/images/sub/com_icon3.png differ diff --git a/public/images/sub/com_icon4.png b/public/images/sub/com_icon4.png new file mode 100644 index 0000000..0da8ec0 Binary files /dev/null and b/public/images/sub/com_icon4.png differ diff --git a/public/images/sub/product_img1.jpg b/public/images/sub/product_img1.jpg new file mode 100644 index 0000000..132c31c Binary files /dev/null and b/public/images/sub/product_img1.jpg differ diff --git a/public/images/sub/product_img2.jpg b/public/images/sub/product_img2.jpg new file mode 100644 index 0000000..14e5914 Binary files /dev/null and b/public/images/sub/product_img2.jpg differ diff --git a/public/images/sub/product_img3.jpg b/public/images/sub/product_img3.jpg new file mode 100644 index 0000000..c045f4a Binary files /dev/null and b/public/images/sub/product_img3.jpg differ diff --git a/public/images/sub/sub1_1.jpg b/public/images/sub/sub1_1.jpg new file mode 100644 index 0000000..36e9c46 Binary files /dev/null and b/public/images/sub/sub1_1.jpg differ diff --git a/public/images/sub/sub2_1.jpg b/public/images/sub/sub2_1.jpg new file mode 100644 index 0000000..cc46724 Binary files /dev/null and b/public/images/sub/sub2_1.jpg differ diff --git a/public/images/sub/sub2_1_icon.gif b/public/images/sub/sub2_1_icon.gif new file mode 100644 index 0000000..fc1dcd0 Binary files /dev/null and b/public/images/sub/sub2_1_icon.gif differ diff --git a/public/images/sub/sub2_1_skype.gif b/public/images/sub/sub2_1_skype.gif new file mode 100644 index 0000000..0789ce6 Binary files /dev/null and b/public/images/sub/sub2_1_skype.gif differ diff --git a/public/images/sub/sub2_2_tit.png b/public/images/sub/sub2_2_tit.png new file mode 100644 index 0000000..6ded24c Binary files /dev/null and b/public/images/sub/sub2_2_tit.png differ diff --git a/public/images/sub/sub3_1.jpg b/public/images/sub/sub3_1.jpg new file mode 100644 index 0000000..28fecdc Binary files /dev/null and b/public/images/sub/sub3_1.jpg differ diff --git a/public/images/sub/sub_visual1.jpg b/public/images/sub/sub_visual1.jpg new file mode 100644 index 0000000..df85468 Binary files /dev/null and b/public/images/sub/sub_visual1.jpg differ diff --git a/public/images/sub/sub_visual2.jpg b/public/images/sub/sub_visual2.jpg new file mode 100644 index 0000000..8699f2b Binary files /dev/null and b/public/images/sub/sub_visual2.jpg differ diff --git a/public/images/sub/sub_visual3.jpg b/public/images/sub/sub_visual3.jpg new file mode 100644 index 0000000..4ee3220 Binary files /dev/null and b/public/images/sub/sub_visual3.jpg differ diff --git a/public/images/sub/sub_visual4.jpg b/public/images/sub/sub_visual4.jpg new file mode 100644 index 0000000..6708503 Binary files /dev/null and b/public/images/sub/sub_visual4.jpg differ diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..5ec58a7 --- /dev/null +++ b/public/index.php @@ -0,0 +1,56 @@ +systemDirectory . '/Boot.php'; + +exit(CodeIgniter\Boot::bootWeb($paths)); diff --git a/public/js/admin.js b/public/js/admin.js new file mode 100644 index 0000000..f1993c7 --- /dev/null +++ b/public/js/admin.js @@ -0,0 +1,81 @@ +/* ------------------------------------------------------------ + * Name : admin.js + * Desc : Admin Javascrip + * Created : 2016/9/11 Tri-aBility by Junheum,Choi + * Updated : + ------------------------------------------------------------ */ + +function is_NumericKey(evt,obj){ + var charCode = (evt.which) ? evt.which : event.keyCode; + switch(charCode){ + case 48://0 + case 49://1 + case 50://2 + case 51://3 + case 52://4 + case 53://5 + case 54://6 + case 55://7 + case 56://8 + case 57://9 + case 96://KeyPad:0 + case 97://KeyPad:1 + case 98://KeyPad:2 + case 99://KeyPad:3 + case 100://KeyPad:4 + case 101://KeyPad:5 + case 102://KeyPad:6 + case 103://KeyPad:7 + case 104://KeyPad:8 + case 105://KeyPad:9 + break; + default: + alert('숫자만 가능합니다['+charCode+']'); + obj.value = obj.value.substring(0,obj.value.length-1); + break; + } +} +function is_NumericType(data){ + if(!data.match(/^[0-9]+$/)){ + throw (new Error('숫자가 아닌값['+data+']이 있습니다')); + } + return true; +}// +function change_CurrencyFormat(obj,currencies){ + //var currencies = document.getElementsByClassName("currency"); + var total_currency = 0; + for(i=0; i { alert("복사가 완료되었습니다."); }) + .catch(err => { console.log('복사가 오류', err); }) +} + +//해당 URL의 페이지를 접속해서 targ의 위치에 표시한다. +function loadContentForm(url,target) { + fetch(url) + .then(response => response.text()) + .then(data => {target.innerHTML = data}) + .catch(error => console.error('Error loading form:', error)); +} \ No newline at end of file diff --git a/public/js/admin/index.js b/public/js/admin/index.js new file mode 100644 index 0000000..ea76567 --- /dev/null +++ b/public/js/admin/index.js @@ -0,0 +1,61 @@ +$(document).ready(function () { + //class가 calender인 inputbox용,날짜field용 + $(".calender").datepicker({ + changeYear: true, + changeMonth: true, + yearRange: "-10:+0", + dateFormat: "yy-mm-dd" + }); + //id가 batchjobuids_checkbox인 버튼을 클릭시 class가 batchjobuids_checkboxs인 checkbox용 + $('#batchjobuids_checkbox').click(function (event) { + if (this.checked) { + $('.batchjobuids_checkboxs').each(function () { //loop checkbox + $(this).prop('checked', true); //check + }); + } else { + $('.batchjobuids_checkboxs').each(function () { //loop checkbox + $(this).prop('checked', false); //uncheck + }); + } + }); + //class가 select-field인 SelectBox용 + $(".select-field").select2({ + theme: "classic", + width: 'style', + dropdownAutoWidth: true + }); + // text editor 초기화 + //참고: https://phppot.com/menu/php/learn-php/ + // class가 editor인 textarea용 + tinymce.init({ + selector: 'textarea.tinymce', + plugins: ['code', 'image', 'preview', 'table', 'emoticons', 'autoresize'], + height: 600, + // content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:16px }' + automatic_uploads: false, + images_upload_url: '/tinymce_upload.php', + // images_upload_base_path: '/upload_images', + images_upload_handler: function (blobInfo, success, failure) { + var xhr, formData; + xhr = new XMLHttpRequest(); + xhr.withCredentials = false; + xhr.open('POST', '/tinymce_upload.php'); + xhr.onload = function () { + var json; + if (xhr.status != 200) { + failure('HTTP Error: ' + xhr.status); + return; + } + json = JSON.parse(xhr.responseText); + if (!json || typeof json.file_path != 'string') { + failure('Invalid JSON: ' + xhr.responseText); + return; + } + success(json.file_path); + }; + formData = new FormData(); + formData.append('file', blobInfo.blob(), blobInfo.filename()); + xhr.send(formData); + }, + }); +}); \ No newline at end of file diff --git a/public/js/admin/left_menu.js b/public/js/admin/left_menu.js new file mode 100644 index 0000000..1cfc98e --- /dev/null +++ b/public/js/admin/left_menu.js @@ -0,0 +1,13 @@ +function sideMenuToggle(left_menu) { + $accordion = $("#accordion")[0]; + if (accordion.clientWidth == 0){ + accordion.style.display = "block"; + $("#accordion").css({ "width": '217px' }) + $("#menu_button").html("메뉴닫기"); + } + else { + accordion.style.display = "none"; + $("#accordion").css({"width":'20px'}) + $("#menu_button").html("메뉴열기"); + } +}//toggleMenu \ No newline at end of file diff --git a/public/js/common/resizeTable.js b/public/js/common/resizeTable.js new file mode 100644 index 0000000..58a8c6b --- /dev/null +++ b/public/js/common/resizeTable.js @@ -0,0 +1,843 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.validide_resizableTableColumns = {})); +})(this, (function (exports) { + 'use strict'; + + var ResizableConstants = /** @class */ (function () { + function ResizableConstants() { + } + ResizableConstants.dataPropertyName = 'validide_rtc_data_object'; + ResizableConstants.classes = { + table: 'rtc-table', + wrapper: 'rtc-wrapper', + handleContainer: 'rtc-handle-container', + handle: 'rtc-handle', + tableResizing: 'rtc-table-resizing', + columnResizing: 'rtc-column-resizing', + }; + ResizableConstants.attributes = { + dataResizable: 'data-rtc-resizable', + dataResizableTable: 'data-rtc-resizable-table' + }; + ResizableConstants.data = { + resizable: 'rtcResizable', + resizableTable: 'rtcResizableTable' + }; + ResizableConstants.events = { + pointerDown: ['mousedown', 'touchstart'], + pointerMove: ['mousemove', 'touchmove'], + pointerUp: ['mouseup', 'touchend'], + windowResize: ['resize'], + eventResizeStart: 'eventResizeStart.rtc', + eventResize: 'eventResize.rtc', + eventResizeStop: 'eventResizeStop.rtc' + }; + return ResizableConstants; + }()); + + var WidthsData = /** @class */ (function () { + function WidthsData() { + this.column = 0; + this.table = 0; + } + return WidthsData; + }()); + var PointerData = /** @class */ (function () { + function PointerData() { + this.x = null; + this.isDoubleClick = false; + } + return PointerData; + }()); + var ResizableEventData = /** @class */ (function () { + function ResizableEventData(column, dragHandler) { + this.pointer = new PointerData(); + this.originalWidths = new WidthsData(); + this.newWidths = new WidthsData(); + this.column = column; + this.dragHandler = dragHandler; + } + return ResizableEventData; + }()); + + var Utilities = /** @class */ (function () { + function Utilities() { + } + Utilities.kebabCaseToCamelCase = function (str) { + return str.replace(Utilities.kebabCaseRegex, function (m) { return m[1].toUpperCase(); }); + }; + Utilities.parseStringToType = function (str) { + if (str.length == 0 || Utilities.onlyWhiteSpace.test(str)) + return str; + if (Utilities.trueRegex.test(str)) + return true; + if (Utilities.falseRegex.test(str)) + return false; + if (Utilities.notEmptyOrWhiteSpace.test(str)) { + var temp = +str; + if (!isNaN(temp)) + return temp; + } + return str; + }; + Utilities.regexEscapeRegex = /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g; + Utilities.kebabCaseRegex = /(\-\w)/g; + Utilities.trueRegex = /^true$/i; + Utilities.falseRegex = /^false$/i; + Utilities.onlyWhiteSpace = /^\s$/; + Utilities.notEmptyOrWhiteSpace = /\S/; + return Utilities; + }()); + + var UtilitiesDOM = /** @class */ (function () { + function UtilitiesDOM() { + } + UtilitiesDOM.getDataAttributesValues = function (el) { + if (!el) + return null; + var returnValue = {}; + if (el.dataset) { + for (var prop in el.dataset) { + if (el.dataset.hasOwnProperty(prop)) { + returnValue[prop] = Utilities.parseStringToType(el.dataset[prop] || ''); + } + } + } + else { + for (var i = 0; i < el.attributes.length; i++) { + if (!/^data\-/.test(el.attributes[i].name)) + continue; + var name_1 = Utilities.kebabCaseToCamelCase(el.attributes[i].name.replace('data-', '')); + returnValue[name_1] = Utilities.parseStringToType(el.attributes[i].value); + } + } + return returnValue; + }; + return UtilitiesDOM; + }()); + + var ResizableOptions = /** @class */ (function () { + function ResizableOptions(options, element) { + if (options === void 0) { options = null; } + if (element === void 0) { element = null; } + this.resizeFromBody = true; + this.minWidth = 40; + this.maxWidth = null; + this.doubleClickDelay = 500; + this.maxInitialWidthHint = null; + this.store = null; + this.overrideValues(options); + this.overrideValuesFromElement(element); + } + ResizableOptions.prototype.overrideValues = function (options) { + if (options === void 0) { options = null; } + if (!options) + return; + for (var prop in options) { + if (this.hasOwnProperty(prop)) { + this[prop] = options[prop]; + } + } + }; + ResizableOptions.prototype.overrideValuesFromElement = function (element) { + if (element === void 0) { element = null; } + if (!element) + return; + var elementOptions = UtilitiesDOM.getDataAttributesValues(element); + this.overrideValues(elementOptions); + }; + return ResizableOptions; + }()); + + var ResizableTableColumns = /** @class */ (function () { + function ResizableTableColumns(table, options) { + if (typeof table !== 'object' || table === null || table.toString() !== '[object HTMLTableElement]') + throw 'Invalid argument: "table".\nResizableTableColumns requires that the table element is a not null HTMLTableElement object!'; + if (typeof table[ResizableConstants.dataPropertyName] !== 'undefined') + throw "Existing \"".concat(ResizableConstants.dataPropertyName, "\" property.\nTable element already has a '").concat(ResizableConstants.dataPropertyName, "' attached object!"); + this.id = ResizableTableColumns.getInstanceId(); + this.table = table; + this.options = new ResizableOptions(options, table); + this.wrapper = null; + this.ownerDocument = table.ownerDocument; + this.tableHeaders = []; + this.dragHandlesContainer = null; + this.originalWidths = []; + this.eventData = null; + this.lastPointerDown = 0; + this.init(); + this.table[ResizableConstants.dataPropertyName] = this; + } + ResizableTableColumns.prototype.init = function () { + this.validateMarkup(); + this.createHandlerReferences(); + this.wrapTable(); + this.assignTableHeaders(); + this.storeOriginalWidths(); + this.setHeaderWidths(); + this.createDragHandles(); + this.restoreColumnWidths(); + this.checkTableWidth(); + this.syncHandleWidths(); + this.registerWindowResizeHandler(); + }; + ResizableTableColumns.prototype.dispose = function () { + this.destroyDragHandles(); + this.restoreOriginalWidths(); + this.unwrapTable(); + this.onPointerDownRef = null; + this.onPointerMoveRef = null; + this.onPointerUpRef = null; + this.table[ResizableConstants.dataPropertyName] = void (0); + }; + ResizableTableColumns.prototype.validateMarkup = function () { + var theadCount = 0; + var tbodyCount = 0; + var thead = null; + for (var index = 0; index < this.table.childNodes.length; index++) { + var element = this.table.childNodes[index]; + if (element.nodeName === 'THEAD') { + theadCount++; + thead = element; + } + else if (element.nodeName === 'TBODY') { + tbodyCount++; + } + } + if (thead === null || theadCount !== 1) + throw "Markup validation: thead count.\nResizableTableColumns requires that the table element has one(1) table head element. Current count: ".concat(theadCount); + if (tbodyCount !== 1) + throw "Markup validation: tbody count.\nResizableTableColumns requires that the table element has one(1) table body element. Current count: ".concat(tbodyCount); + var theadRowCount = 0; + var firstRow = null; + for (var index = 0; index < thead.childNodes.length; index++) { + var element = thead.childNodes[index]; + if (element.nodeName === 'TR') { + theadRowCount++; + if (firstRow === null) { + firstRow = element; + } + } + } + if (firstRow === null || theadRowCount < 1) + throw "Markup validation: thead row count.\nResizableTableColumns requires that the table head element has at least one(1) table row element. Current count: ".concat(theadRowCount); + var headerCellsCount = 0; + var invalidHeaderCellsCount = 0; + for (var index = 0; index < firstRow.childNodes.length; index++) { + var element = firstRow.childNodes[index]; + if (element.nodeName === 'TH') { + headerCellsCount++; + } + else if (element.nodeName === 'TD') { + invalidHeaderCellsCount++; + } + } + if (headerCellsCount < 1) + throw "Markup validation: thead first row cells count.\nResizableTableColumns requires that the table head's first row element has at least one(1) table header cell element. Current count: ".concat(headerCellsCount); + if (invalidHeaderCellsCount !== 0) + throw "Markup validation: thead first row invalid.\nResizableTableColumns requires that the table head's first row element has no(0) table cell(TD) elements. Current count: ".concat(invalidHeaderCellsCount); + }; + ResizableTableColumns.prototype.wrapTable = function () { + if (this.wrapper) + return; + this.wrapper = this.ownerDocument.createElement('div'); + this.wrapper.classList.add(ResizableConstants.classes.wrapper); + var tableOriginalParent = this.table.parentNode; + tableOriginalParent.insertBefore(this.wrapper, this.table); + tableOriginalParent.removeChild(this.table); + this.wrapper.appendChild(this.table); + this.table.classList.add(ResizableConstants.classes.table); + }; + ResizableTableColumns.prototype.unwrapTable = function () { + this.table.classList.remove(ResizableConstants.classes.table); + if (!this.wrapper) + return; + var tableOriginalParent = this.wrapper.parentNode; + tableOriginalParent.insertBefore(this.table, this.wrapper); + tableOriginalParent.removeChild(this.wrapper); + this.wrapper = null; + }; + ResizableTableColumns.prototype.assignTableHeaders = function () { + var tableHeader; + var firstTableRow; + for (var index = 0; index < this.table.childNodes.length; index++) { + var element = this.table.childNodes[index]; + if (element.nodeName === 'THEAD') { + tableHeader = element; + break; + } + } + if (!tableHeader) + return; + for (var index = 0; index < tableHeader.childNodes.length; index++) { + var element = tableHeader.childNodes[index]; + if (element.nodeName === 'TR') { + firstTableRow = element; + break; + } + } + if (!firstTableRow) + return; + for (var index = 0; index < firstTableRow.childNodes.length; index++) { + var element = firstTableRow.childNodes[index]; + if (element.nodeName === 'TH') { + this.tableHeaders.push(element); + } + } + }; + ResizableTableColumns.prototype.storeOriginalWidths = function () { + var _this = this; + this.tableHeaders + .forEach(function (el) { + _this.originalWidths.push({ + el: el, + detail: el.style.width + }); + }); + this.originalWidths.push({ + el: this.table, + detail: this.table.style.width + }); + }; + ResizableTableColumns.prototype.restoreOriginalWidths = function () { + this.originalWidths + .forEach(function (itm) { + itm.el.style.width = itm.detail; + }); + }; + ResizableTableColumns.prototype.setHeaderWidths = function () { + var _this = this; + this.tableHeaders + .forEach(function (el) { + var width = el.offsetWidth; + var constrainedWidth = _this.constrainWidth(el, width); + if (typeof _this.options.maxInitialWidthHint === 'number') { + constrainedWidth = Math.min(constrainedWidth, _this.options.maxInitialWidthHint); + } + _this.updateWidth(el, constrainedWidth, true, false); + }); + }; + ResizableTableColumns.prototype.constrainWidth = function (el, width) { + var result = width; + result = Math.max(result, this.options.minWidth || -Infinity); + result = Math.min(result, this.options.maxWidth || +Infinity); + return result; + }; + ResizableTableColumns.prototype.createDragHandles = function () { + var _this = this; + var _a; + if (this.dragHandlesContainer != null) + throw 'Drag handlers already created. Call if you wish to recreate them'; + this.dragHandlesContainer = this.ownerDocument.createElement('div'); + (_a = this.wrapper) === null || _a === void 0 ? void 0 : _a.insertBefore(this.dragHandlesContainer, this.table); + this.dragHandlesContainer.classList.add(ResizableConstants.classes.handleContainer); + this.getResizableHeaders() + .forEach(function () { + var _a; + var handler = _this.ownerDocument.createElement('div'); + handler.classList.add(ResizableConstants.classes.handle); + (_a = _this.dragHandlesContainer) === null || _a === void 0 ? void 0 : _a.appendChild(handler); + }); + ResizableConstants.events.pointerDown + .forEach(function (evt, evtIdx) { + var _a; + (_a = _this.dragHandlesContainer) === null || _a === void 0 ? void 0 : _a.addEventListener(evt, _this.onPointerDownRef, false); + }); + }; + ResizableTableColumns.prototype.destroyDragHandles = function () { + var _this = this; + var _a, _b; + if (this.dragHandlesContainer !== null) { + ResizableConstants.events.pointerDown + .forEach(function (evt, evtIdx) { + var _a; + (_a = _this.dragHandlesContainer) === null || _a === void 0 ? void 0 : _a.removeEventListener(evt, _this.onPointerDownRef, false); + }); + (_b = (_a = this.dragHandlesContainer) === null || _a === void 0 ? void 0 : _a.parentElement) === null || _b === void 0 ? void 0 : _b.removeChild(this.dragHandlesContainer); + } + }; + ResizableTableColumns.prototype.getDragHandlers = function () { + var nodes = this.dragHandlesContainer == null + ? null + : this.dragHandlesContainer.querySelectorAll(".".concat(ResizableConstants.classes.handle)); + return nodes + ? Array.prototype.slice.call(nodes).filter(function (el) { return el.nodeName === 'DIV'; }) + : new Array(); + }; + ResizableTableColumns.prototype.restoreColumnWidths = function () { + if (!this.options.store) + return; + var tableId = ResizableTableColumns.generateTableId(this.table); + if (tableId.length === 0) + return; + var data = this.options.store.get(tableId); + if (!data) + return; + this.getResizableHeaders() + .forEach(function (el) { + var width = data.columns[ResizableTableColumns.generateColumnId(el)]; + if (typeof width !== 'undefined') { + ResizableTableColumns.setWidth(el, width); + } + }); + if (typeof data.table !== 'undefined') { + ResizableTableColumns.setWidth(this.table, data.table); + } + }; + ResizableTableColumns.prototype.checkTableWidth = function () { + var _a; + var wrapperWidth = this.wrapper.clientWidth; + var tableWidth = this.table.offsetWidth; + var difference = wrapperWidth - tableWidth; + if (difference <= 0) + return; + var resizableWidth = 0; + var addedWidth = 0; + var headersDetails = []; + this.tableHeaders + .forEach(function (el, idx) { + if (el.hasAttribute(ResizableConstants.attributes.dataResizable)) { + var detail = { + el: el, + detail: el.offsetWidth + }; + headersDetails.push(detail); + resizableWidth += detail.detail; + } + }); + var leftToAdd = 0; + var lastResizableCell = null; + var currentDetail; + while ((currentDetail = headersDetails.shift())) { + leftToAdd = difference - addedWidth; + lastResizableCell = currentDetail.el; + var extraWidth = Math.floor((currentDetail.detail / resizableWidth) * difference); + extraWidth = Math.min(extraWidth, leftToAdd); + var newWidth = this.updateWidth(currentDetail.el, currentDetail.detail + extraWidth, false, true); + addedWidth += (newWidth - currentDetail.detail); + if (addedWidth >= difference) + break; + } + leftToAdd = difference - addedWidth; + if (leftToAdd > 0) { + var lastCell = ((_a = headersDetails[0]) === null || _a === void 0 ? void 0 : _a.el) || lastResizableCell || this.tableHeaders[this.tableHeaders.length - 1]; + var lastCellWidth = lastCell.offsetWidth; + this.updateWidth(lastCell, lastCellWidth, true, true); + } + ResizableTableColumns.setWidth(this.table, wrapperWidth); + }; + ResizableTableColumns.prototype.syncHandleWidths = function () { + var _this = this; + var tableWidth = this.table.clientWidth; + ResizableTableColumns.setWidth(this.dragHandlesContainer, tableWidth); + this.dragHandlesContainer.style.minWidth = "".concat(tableWidth, "px"); + var headers = this.getResizableHeaders(); + this.getDragHandlers() + .forEach(function (el, idx) { + var height = (_this.options.resizeFromBody ? _this.table : _this.table.tHead).clientHeight; + if (idx < headers.length) { + var th = headers[idx]; + var left = th.offsetWidth; + left += ResizableTableColumns.getOffset(th).left; + left -= ResizableTableColumns.getOffset(_this.dragHandlesContainer).left; + el.style.left = "".concat(left, "px"); + el.style.height = "".concat(height, "px"); + } + }); + }; + ResizableTableColumns.prototype.getResizableHeaders = function () { + return this.tableHeaders + .filter(function (el, idx) { + return el.hasAttribute(ResizableConstants.attributes.dataResizable); + }); + }; + ResizableTableColumns.prototype.handlePointerDown = function (event) { + this.handlePointerUp(); + var target = event ? event.target : null; + if (target == null) + return; + if (target.nodeName !== 'DIV' || !target.classList.contains(ResizableConstants.classes.handle)) + return; + if (typeof event.button === 'number' && event.button !== 0) + return; // this is not a left click + var dragHandler = target; + var gripIndex = this.getDragHandlers().indexOf(dragHandler); + var resizableHeaders = this.getResizableHeaders(); + if (gripIndex >= resizableHeaders.length) + return; + var millisecondsNow = (new Date()).getTime(); + var isDoubleClick = (millisecondsNow - this.lastPointerDown) < this.options.doubleClickDelay; + var column = resizableHeaders[gripIndex]; + var columnWidth = column.offsetWidth; + var widths = { + column: columnWidth, + table: this.table.offsetWidth + }; + var eventData = new ResizableEventData(column, dragHandler); + eventData.pointer = { + x: ResizableTableColumns.getPointerX(event), + isDoubleClick: isDoubleClick + }; + eventData.originalWidths = widths; + eventData.newWidths = widths; + this.detachHandlers(); //make sure we do not have extra handlers + this.attachHandlers(); + this.table.classList.add(ResizableConstants.classes.tableResizing); + this.wrapper.classList.add(ResizableConstants.classes.tableResizing); + dragHandler.classList.add(ResizableConstants.classes.columnResizing); + column.classList.add(ResizableConstants.classes.columnResizing); + this.lastPointerDown = millisecondsNow; + this.eventData = eventData; + var eventToDispatch = new CustomEvent(ResizableConstants.events.eventResizeStart, { + detail: { + column: column, + columnWidth: columnWidth, + table: this.table, + tableWidth: this.table.clientWidth + } + }); + this.table.dispatchEvent(eventToDispatch); + event.preventDefault(); + }; + ResizableTableColumns.prototype.handlePointerMove = function (event) { + if (!this.eventData || !event) + return; + var difference = (ResizableTableColumns.getPointerX(event) || 0) - (this.eventData.pointer.x || 0); + if (difference === 0) { + return; + } + var tableWidth = this.eventData.originalWidths.table + difference; + var columnWidth = this.constrainWidth(this.eventData.column, this.eventData.originalWidths.column + difference); + ResizableTableColumns.setWidth(this.table, tableWidth); + ResizableTableColumns.setWidth(this.eventData.column, columnWidth); + this.eventData.newWidths = { + column: columnWidth, + table: tableWidth + }; + var eventToDispatch = new CustomEvent(ResizableConstants.events.eventResize, { + detail: { + column: this.eventData.column, + columnWidth: columnWidth, + table: this.table, + tableWidth: tableWidth + } + }); + this.table.dispatchEvent(eventToDispatch); + }; + ResizableTableColumns.prototype.handlePointerUp = function () { + this.detachHandlers(); + if (!this.eventData) + return; + if (this.eventData.pointer.isDoubleClick) { + this.handleDoubleClick(); + } + this.table.classList.remove(ResizableConstants.classes.tableResizing); + this.wrapper.classList.remove(ResizableConstants.classes.tableResizing); + this.eventData.dragHandler.classList.remove(ResizableConstants.classes.columnResizing); + this.eventData.column.classList.remove(ResizableConstants.classes.columnResizing); + this.checkTableWidth(); + this.syncHandleWidths(); + this.refreshWrapperStyle(); + this.saveColumnWidths(); + var widths = this.eventData.newWidths || this.eventData.originalWidths; + var eventToDispatch = new CustomEvent(ResizableConstants.events.eventResizeStop, { + detail: { + column: this.eventData.column, + columnWidth: widths.column, + table: this.table, + tableWidth: widths.table + } + }); + this.table.dispatchEvent(eventToDispatch); + this.eventData = null; + }; + ResizableTableColumns.prototype.handleDoubleClick = function () { + if (!this.eventData || !this.eventData.column) + return; + var column = this.eventData.column; + var colIndex = this.tableHeaders.indexOf(column); + var maxWidth = 0; + var indicesToSkip = []; + this.tableHeaders + .forEach(function (el, idx) { + if (!el.hasAttribute(ResizableConstants.attributes.dataResizable)) { + indicesToSkip.push(idx); + } + }); + var span = this.ownerDocument.createElement('span'); + span.style.position = 'absolute'; + span.style.left = '-99999px'; + span.style.top = '-99999px'; + span.style.visibility = 'hidden'; + this.ownerDocument.body.appendChild(span); + var rows = this.table.querySelectorAll('tr'); + for (var rowIndex = 0; rowIndex < rows.length; rowIndex++) { + var element = rows[rowIndex]; + var cells = element.querySelectorAll('td, th'); + var currentIndex = 0; + for (var cellIndex = 0; cellIndex < cells.length; cellIndex++) { + var cell = cells[cellIndex]; + var colSpan = 1; + if (cell.hasAttribute('colspan')) { + var colSpanString = cell.getAttribute('colspan') || '1'; + var parsed = parseInt(colSpanString); + if (!isNaN(parsed)) { + colSpan = parsed; + } + else { + colSpan = 1; + } + } + if (indicesToSkip.indexOf(cellIndex) === -1 + && colSpan === 1 + && currentIndex === colIndex) { + maxWidth = Math.max(maxWidth, ResizableTableColumns.getTextWidth(cell, span)); + break; + } + currentIndex += colSpan; + } + } + this.ownerDocument.body.removeChild(span); + var difference = maxWidth - column.offsetWidth; + if (difference === 0) { + return; + } + var tableWidth = this.eventData.originalWidths.table + difference; + var columnWidth = this.constrainWidth(this.eventData.column, this.eventData.originalWidths.column + difference); + ResizableTableColumns.setWidth(this.table, tableWidth); + ResizableTableColumns.setWidth(this.eventData.column, columnWidth); + this.eventData.newWidths = { + column: columnWidth, + table: tableWidth, + }; + var eventToDispatch = new CustomEvent(ResizableConstants.events.eventResize, { + detail: { + column: this.eventData.column, + columnWidth: columnWidth, + table: this.table, + tableWidth: tableWidth + } + }); + this.table.dispatchEvent(eventToDispatch); + this.checkTableWidth(); + this.syncHandleWidths(); + this.saveColumnWidths(); + }; + ResizableTableColumns.prototype.attachHandlers = function () { + var _this = this; + ResizableConstants.events.pointerMove + .forEach(function (evt, evtIdx) { + _this.ownerDocument.addEventListener(evt, _this.onPointerMoveRef, false); + }); + ResizableConstants.events.pointerUp + .forEach(function (evt, evtIdx) { + _this.ownerDocument.addEventListener(evt, _this.onPointerUpRef, false); + }); + }; + ResizableTableColumns.prototype.detachHandlers = function () { + var _this = this; + ResizableConstants.events.pointerMove + .forEach(function (evt, evtIdx) { + _this.ownerDocument.removeEventListener(evt, _this.onPointerMoveRef, false); + }); + ResizableConstants.events.pointerUp + .forEach(function (evt, evtIdx) { + _this.ownerDocument.removeEventListener(evt, _this.onPointerUpRef, false); + }); + }; + ResizableTableColumns.prototype.refreshWrapperStyle = function () { + if (this.wrapper == null) + return; + var original = this.wrapper.style.overflowX; + this.wrapper.style.overflowX = 'hidden'; + this.wrapper.style.overflowX = original; + }; + ResizableTableColumns.prototype.saveColumnWidths = function () { + if (!this.options.store) + return; + var tableId = ResizableTableColumns.generateTableId(this.table); + if (tableId.length === 0) + return; + var data = { + table: this.table.offsetWidth, + columns: {} + }; + this.getResizableHeaders() + .forEach(function (el) { + data.columns[ResizableTableColumns.generateColumnId(el)] = el.offsetWidth; + }); + this.options.store.set(tableId, data); + }; + ResizableTableColumns.prototype.createHandlerReferences = function () { + var _this = this; + if (!this.onPointerDownRef) { + this.onPointerDownRef = ResizableTableColumns.debounce(function (evt) { + _this.handlePointerDown(evt); + }, 100, true); + } + if (!this.onPointerMoveRef) { + this.onPointerMoveRef = ResizableTableColumns.debounce(function (evt) { + _this.handlePointerMove(evt); + }, 5, false); + } + if (!this.onPointerUpRef) { + this.onPointerUpRef = ResizableTableColumns.debounce(function (evt) { + _this.handlePointerUp(); + }, 100, true); + } + }; + ResizableTableColumns.prototype.registerWindowResizeHandler = function () { + var win = this.ownerDocument.defaultView; + if (ResizableTableColumns.windowResizeHandlerRef) + return; + ResizableTableColumns.windowResizeHandlerRef = ResizableTableColumns.debounce(ResizableTableColumns.onWindowResize, 50, false); + ResizableConstants.events.windowResize + .forEach(function (evt, idx) { + win === null || win === void 0 ? void 0 : win.addEventListener(evt, ResizableTableColumns.windowResizeHandlerRef, false); + }); + }; + ResizableTableColumns.prototype.handleWindowResize = function () { + this.checkTableWidth(); + this.syncHandleWidths(); + this.saveColumnWidths(); + }; + ResizableTableColumns.prototype.updateWidth = function (cell, suggestedWidth, skipConstrainCheck, skipTableResize) { + var originalCellWidth = cell.offsetWidth; + var columnWidth = skipConstrainCheck + ? suggestedWidth + : this.constrainWidth(cell, suggestedWidth); + ResizableTableColumns.setWidth(cell, columnWidth); + if (!skipTableResize) { + var difference = columnWidth - originalCellWidth; + var tableWidth = this.table.offsetWidth + difference; + ResizableTableColumns.setWidth(this.table, tableWidth); + } + return columnWidth; + }; + ResizableTableColumns.onWindowResize = function (event) { + var win = event ? event.target : null; + if (win == null) + return; + var tables = win.document.querySelectorAll(".".concat(ResizableConstants.classes.table)); + for (var index = 0; index < tables.length; index++) { + var table = tables[index]; + if (typeof table[ResizableConstants.dataPropertyName] !== 'object') + continue; + table[ResizableConstants.dataPropertyName].handleWindowResize(); + } + }; + ResizableTableColumns.generateColumnId = function (el) { + var columnId = (el.getAttribute(ResizableConstants.attributes.dataResizable) || '') + .trim() + .replace(/\./g, '_'); + return columnId; + }; + ResizableTableColumns.generateTableId = function (table) { + var tableId = (table.getAttribute(ResizableConstants.attributes.dataResizableTable) || '') + .trim() + .replace(/\./g, '_'); + return tableId.length + ? "rtc/".concat(tableId) + : tableId; + }; + ResizableTableColumns.setWidth = function (element, width) { + var strWidth = width.toFixed(2); + strWidth = width > 0 ? strWidth : '0'; + element.style.width = "".concat(strWidth, "px"); + }; + ResizableTableColumns.getInstanceId = function () { + return ResizableTableColumns.instancesCount++; + }; + ResizableTableColumns.getPointerX = function (event) { + if (event.type.indexOf('touch') === 0) { + var tEvent = event; + if (tEvent.touches && tEvent.touches.length) { + return tEvent.touches[0].pageX; + } + if (tEvent.changedTouches && tEvent.changedTouches.length) { + return tEvent.changedTouches[0].pageX; + } + } + return event.pageX; + }; + ResizableTableColumns.getTextWidth = function (contentElement, measurementElement) { + var _a, _b; + if (!contentElement || !measurementElement) + return 0; + var text = ((_a = contentElement.textContent) === null || _a === void 0 ? void 0 : _a.trim().replace(/\s/g, ' ')) + ' '; //add extra space to ensure we are not add the `...` + var styles = (_b = contentElement.ownerDocument.defaultView) === null || _b === void 0 ? void 0 : _b.getComputedStyle(contentElement); + ['fontFamily', 'fontSize', 'fontWeight', 'padding', 'border', 'boxSizing'] + .forEach(function (prop) { + measurementElement.style[prop] = styles[prop]; + }); + measurementElement.innerHTML = text; + return measurementElement.offsetWidth; + }; + ResizableTableColumns.getOffset = function (el) { + if (!el) + return { top: 0, left: 0 }; + var rect = el.getBoundingClientRect(); + return { + top: rect.top + el.ownerDocument.body.scrollTop, + left: rect.left + el.ownerDocument.body.scrollLeft + }; + }; + ResizableTableColumns.instancesCount = 0; + ResizableTableColumns.windowResizeHandlerRef = null; + ResizableTableColumns.debounce = function (func, wait, immediate) { + var timeout = null; + var debounced = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var later = function () { + timeout = null; + if (!immediate) { + func.apply(void 0, args); + } + }; + var callNow = immediate && !timeout; + if (timeout) { + clearTimeout(timeout); + } + timeout = setTimeout(later, wait); + if (callNow) { + func.apply(void 0, args); + } + }; + return debounced; + }; + return ResizableTableColumns; + }()); + + exports.PointerData = PointerData; + exports.ResizableConstants = ResizableConstants; + exports.ResizableEventData = ResizableEventData; + exports.ResizableOptions = ResizableOptions; + exports.ResizableTableColumns = ResizableTableColumns; + exports.Utilities = Utilities; + exports.UtilitiesDOM = UtilitiesDOM; + exports.WidthsData = WidthsData; + +})); +(function (window, ResizableTableColumns, undefined) { + var store = window.store && window.store.enabled ? window.store : null; + var els = document.querySelectorAll('table.data'); + for (var index = 0; index < els.length; index++) { + var table = els[index]; + if (table['rtc_data_object']) { + continue; + } + var options = { + store: store + }; + if (table.querySelectorAll('thead > tr').length > 1) { + options.resizeFromBody = false; + } + new ResizableTableColumns(els[index], options); + } +})(window, window.validide_resizableTableColumns.ResizableTableColumns, void (0)); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/public/js/empty.js b/public/js/empty.js new file mode 100644 index 0000000..f973e71 --- /dev/null +++ b/public/js/empty.js @@ -0,0 +1,6 @@ +/* ------------------------------------------------------------ + * Name : front.js + * Desc : Front Javascrip + * Created : 2016/9/11 Tri-aBility by Junheum,Choi + * Updated : + ------------------------------------------------------------ */ diff --git a/public/js/front.js b/public/js/front.js new file mode 100644 index 0000000..6bea8a4 --- /dev/null +++ b/public/js/front.js @@ -0,0 +1,93 @@ +/* ------------------------------------------------------------ + * Name : front.js + * Desc : Front Javascrip + * Created : 2016/9/11 Tri-aBility by Junheum,Choi + * Updated : + ------------------------------------------------------------ */ + +function trim(str){ + return this.replace(/(^\s*)|(\s*$)/gi, ""); +}// + +function bookmarksite(title,url) { + if (window.sidebar) // firefox + window.sidebar.addPanel(title, url, ""); + else if(window.opera && window.print){ // opera + var elem = document.createElement('a'); + elem.setAttribute('href',url); + elem.setAttribute('title',title); + elem.setAttribute('rel','sidebar'); + elem.click(); + } + else if(document.all) // ie + window.external.AddFavorite(url, title); +}// + +function captcha_refresh(refresh_url) { + $.ajax({ + type: 'POST', + url: refresh_url, + success: function(data, status, xhr){ + if(data) + $('#captcha_span').html(data); + }, + error: function(jqXHR, textStatus, errorThrown) { + console.log(jqXHR.responseText); + console.log(textStatus+'=>'+errorThrown); + } + });//ajax +}// + +function is_NumericKey(evt,obj){ + var charCode = (evt.which) ? evt.which : event.keyCode; + switch(charCode){ + case 48://0 + case 49://1 + case 50://2 + case 51://3 + case 52://4 + case 53://5 + case 54://6 + case 55://7 + case 56://8 + case 57://9 + case 96://KeyPad:0 + case 97://KeyPad:1 + case 98://KeyPad:2 + case 99://KeyPad:3 + case 100://KeyPad:4 + case 101://KeyPad:5 + case 102://KeyPad:6 + case 103://KeyPad:7 + case 104://KeyPad:8 + case 105://KeyPad:9 + break; + default: + alert('숫자만 가능합니다['+charCode+']'); + obj.value = obj.value.substring(0,obj.value.length-1); + break; + } +} +function is_NumericType(data){ + if(!data.match(/^[0-9]+$/)){ + throw (new Error('숫자가 아닌값['+data+']이 있습니다')); + } + return true; +}// +function change_CurrencyFormat(obj,currencies){ + //var currencies = document.getElementsByClassName("currency"); + var total_currency = 0; + for(i=0; i'+errorThrown); + } + });//ajax +}// + +function is_NumericKey(evt,obj){ + var charCode = (evt.which) ? evt.which : event.keyCode; + switch(charCode){ + case 48://0 + case 49://1 + case 50://2 + case 51://3 + case 52://4 + case 53://5 + case 54://6 + case 55://7 + case 56://8 + case 57://9 + case 96://KeyPad:0 + case 97://KeyPad:1 + case 98://KeyPad:2 + case 99://KeyPad:3 + case 100://KeyPad:4 + case 101://KeyPad:5 + case 102://KeyPad:6 + case 103://KeyPad:7 + case 104://KeyPad:8 + case 105://KeyPad:9 + break; + default: + alert('숫자만 가능합니다['+charCode+']'); + obj.value = obj.value.substring(0,obj.value.length-1); + break; + } +} +function is_NumericType(data){ + if(!data.match(/^[0-9]+$/)){ + throw (new Error('숫자가 아닌값['+data+']이 있습니다')); + } + return true; +}// +function change_CurrencyFormat(obj,currencies){ + //var currencies = document.getElementsByClassName("currency"); + var total_currency = 0; + for(i=0; i + + + + + + + + + + + + + diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..9e60f97 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/public/test.php b/public/test.php new file mode 100644 index 0000000..04180a1 --- /dev/null +++ b/public/test.php @@ -0,0 +1,3 @@ + $fileName + )); +} diff --git a/spark b/spark new file mode 100644 index 0000000..992d044 --- /dev/null +++ b/spark @@ -0,0 +1,84 @@ +#!/usr/bin/env php + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +/* + * -------------------------------------------------------------------- + * CODEIGNITER COMMAND-LINE TOOLS + * -------------------------------------------------------------------- + * The main entry point into the CLI system and allows you to run + * commands and perform maintenance on your application. + */ + +/* + *--------------------------------------------------------------- + * CHECK SERVER API + *--------------------------------------------------------------- + */ + +// Refuse to run when called from php-cgi +if (str_starts_with(PHP_SAPI, 'cgi')) { + exit("The cli tool is not supported when running php-cgi. It needs php-cli to function!\n\n"); +} + +/* + *--------------------------------------------------------------- + * CHECK PHP VERSION + *--------------------------------------------------------------- + */ + +$minPhpVersion = '8.1'; // If you update this, don't forget to update `public/index.php`. +if (version_compare(PHP_VERSION, $minPhpVersion, '<')) { + $message = sprintf( + 'Your PHP version must be %s or higher to run CodeIgniter. Current version: %s', + $minPhpVersion, + PHP_VERSION + ); + + exit($message); +} + +// We want errors to be shown when using it from the CLI. +error_reporting(E_ALL); +ini_set('display_errors', '1'); + +/* + *--------------------------------------------------------------- + * SET THE CURRENT DIRECTORY + *--------------------------------------------------------------- + */ + +// Path to the front controller +define('FCPATH', __DIR__ . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR); + +// Ensure the current directory is pointing to the front controller's directory +chdir(FCPATH); + +/* + *--------------------------------------------------------------- + * BOOTSTRAP THE APPLICATION + *--------------------------------------------------------------- + * This process sets up the path constants, loads and registers + * our autoloader, along with Composer's, loads our constants + * and fires up an environment-specific bootstrapping. + */ + +// LOAD OUR PATHS CONFIG FILE +// This is the line that might need to be changed, depending on your folder structure. +require FCPATH . '../app/Config/Paths.php'; +// ^^^ Change this line if you move your application folder + +$paths = new Config\Paths(); + +// LOAD THE FRAMEWORK BOOTSTRAP FILE +require $paths->systemDirectory . '/Boot.php'; + +exit(CodeIgniter\Boot::bootSpark($paths)); diff --git a/tests/.htaccess b/tests/.htaccess new file mode 100644 index 0000000..3462048 --- /dev/null +++ b/tests/.htaccess @@ -0,0 +1,6 @@ + + Require all denied + + + Deny from all + diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..fc40e44 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,118 @@ +# Running Application Tests + +This is the quick-start to CodeIgniter testing. Its intent is to describe what +it takes to set up your application and get it ready to run unit tests. +It is not intended to be a full description of the test features that you can +use to test your application. Those details can be found in the documentation. + +## Resources + +* [CodeIgniter 4 User Guide on Testing](https://codeigniter.com/user_guide/testing/index.html) +* [PHPUnit docs](https://phpunit.de/documentation.html) +* [Any tutorials on Unit testing in CI4?](https://forum.codeigniter.com/showthread.php?tid=81830) + +## Requirements + +It is recommended to use the latest version of PHPUnit. At the time of this +writing, we are running version 9.x. Support for this has been built into the +**composer.json** file that ships with CodeIgniter and can easily be installed +via [Composer](https://getcomposer.org/) if you don't already have it installed globally. + +```console +> composer install +``` + +If running under macOS or Linux, you can create a symbolic link to make running tests a touch nicer. + +```console +> ln -s ./vendor/bin/phpunit ./phpunit +``` + +You also need to install [XDebug](https://xdebug.org/docs/install) in order +for code coverage to be calculated successfully. After installing `XDebug`, you must add `xdebug.mode=coverage` in the **php.ini** file to enable code coverage. + +## Setting Up + +A number of the tests use a running database. +In order to set up the database edit the details for the `tests` group in +**app/Config/Database.php** or **.env**. +Make sure that you provide a database engine that is currently running on your machine. +More details on a test database setup are in the +[Testing Your Database](https://codeigniter.com/user_guide/testing/database.html) section of the documentation. + +## Running the tests + +The entire test suite can be run by simply typing one command-line command from the main directory. + +```console +> ./phpunit +``` + +If you are using Windows, use the following command. + +```console +> vendor\bin\phpunit +``` + +You can limit tests to those within a single test directory by specifying the +directory name after phpunit. + +```console +> ./phpunit app/Models +``` + +## Generating Code Coverage + +To generate coverage information, including HTML reports you can view in your browser, +you can use the following command: + +```console +> ./phpunit --colors --coverage-text=tests/coverage.txt --coverage-html=tests/coverage/ -d memory_limit=1024m +``` + +This runs all of the tests again collecting information about how many lines, +functions, and files are tested. It also reports the percentage of the code that is covered by tests. +It is collected in two formats: a simple text file that provides an overview as well +as a comprehensive collection of HTML files that show the status of every line of code in the project. + +The text file can be found at **tests/coverage.txt**. +The HTML files can be viewed by opening **tests/coverage/index.html** in your favorite browser. + +## PHPUnit XML Configuration + +The repository has a ``phpunit.xml.dist`` file in the project root that's used for +PHPUnit configuration. This is used to provide a default configuration if you +do not have your own configuration file in the project root. + +The normal practice would be to copy ``phpunit.xml.dist`` to ``phpunit.xml`` +(which is git ignored), and to tailor it as you see fit. +For instance, you might wish to exclude database tests, or automatically generate +HTML code coverage reports. + +## Test Cases + +Every test needs a *test case*, or class that your tests extend. CodeIgniter 4 +provides one class that you may use directly: +* `CodeIgniter\Test\CIUnitTestCase` + +Most of the time you will want to write your own test cases that extend `CIUnitTestCase` +to hold functions and services common to your test suites. + +## Creating Tests + +All tests go in the **tests/** directory. Each test file is a class that extends a +**Test Case** (see above) and contains methods for the individual tests. These method +names must start with the word "test" and should have descriptive names for precisely what +they are testing: +`testUserCanModifyFile()` `testOutputColorMatchesInput()` `testIsLoggedInFailsWithInvalidUser()` + +Writing tests is an art, and there are many resources available to help learn how. +Review the links above and always pay attention to your code coverage. + +### Database Tests + +Tests can include migrating, seeding, and testing against a mock or live database. +Be sure to modify the test case (or create your own) to point to your seed and migrations +and include any additional steps to be run before tests in the `setUp()` method. +See [Testing Your Database](https://codeigniter.com/user_guide/testing/database.html) +for details. diff --git a/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php b/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php new file mode 100644 index 0000000..a73356d --- /dev/null +++ b/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php @@ -0,0 +1,37 @@ +forge->addField('id'); + $this->forge->addField([ + 'name' => ['type' => 'varchar', 'constraint' => 31], + 'uid' => ['type' => 'varchar', 'constraint' => 31], + 'class' => ['type' => 'varchar', 'constraint' => 63], + 'icon' => ['type' => 'varchar', 'constraint' => 31], + 'summary' => ['type' => 'varchar', 'constraint' => 255], + 'created_at' => ['type' => 'datetime', 'null' => true], + 'updated_at' => ['type' => 'datetime', 'null' => true], + 'deleted_at' => ['type' => 'datetime', 'null' => true], + ]); + + $this->forge->addKey('name'); + $this->forge->addKey('uid'); + $this->forge->addKey(['deleted_at', 'id']); + $this->forge->addKey('created_at'); + + $this->forge->createTable('factories'); + } + + public function down(): void + { + $this->forge->dropTable('factories'); + } +} diff --git a/tests/_support/Database/Seeds/ExampleSeeder.php b/tests/_support/Database/Seeds/ExampleSeeder.php new file mode 100644 index 0000000..619fc27 --- /dev/null +++ b/tests/_support/Database/Seeds/ExampleSeeder.php @@ -0,0 +1,41 @@ + 'Test Factory', + 'uid' => 'test001', + 'class' => 'Factories\Tests\NewFactory', + 'icon' => 'fas fa-puzzle-piece', + 'summary' => 'Longer sample text for testing', + ], + [ + 'name' => 'Widget Factory', + 'uid' => 'widget', + 'class' => 'Factories\Tests\WidgetPlant', + 'icon' => 'fas fa-puzzle-piece', + 'summary' => 'Create widgets in your factory', + ], + [ + 'name' => 'Evil Factory', + 'uid' => 'evil-maker', + 'class' => 'Factories\Evil\MyFactory', + 'icon' => 'fas fa-book-dead', + 'summary' => 'Abandon all hope, ye who enter here', + ], + ]; + + $builder = $this->db->table('factories'); + + foreach ($factories as $factory) { + $builder->insert($factory); + } + } +} diff --git a/tests/_support/Libraries/ConfigReader.php b/tests/_support/Libraries/ConfigReader.php new file mode 100644 index 0000000..40d057a --- /dev/null +++ b/tests/_support/Libraries/ConfigReader.php @@ -0,0 +1,17 @@ +findAll(); + + // Make sure the count is as expected + $this->assertCount(3, $objects); + } + + public function testSoftDeleteLeavesRow(): void + { + $model = new ExampleModel(); + $this->setPrivateProperty($model, 'useSoftDeletes', true); + $this->setPrivateProperty($model, 'tempUseSoftDeletes', true); + + /** @var stdClass $object */ + $object = $model->first(); + $model->delete($object->id); + + // The model should no longer find it + $this->assertNull($model->find($object->id)); + + // ... but it should still be in the database + $result = $model->builder()->where('id', $object->id)->get()->getResult(); + + $this->assertCount(1, $result); + } +} diff --git a/tests/index.html b/tests/index.html new file mode 100644 index 0000000..b702fbc --- /dev/null +++ b/tests/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/tests/session/ExampleSessionTest.php b/tests/session/ExampleSessionTest.php new file mode 100644 index 0000000..6ada0c5 --- /dev/null +++ b/tests/session/ExampleSessionTest.php @@ -0,0 +1,18 @@ +set('logged_in', 123); + $this->assertSame(123, $session->get('logged_in')); + } +} diff --git a/tests/unit/HealthTest.php b/tests/unit/HealthTest.php new file mode 100644 index 0000000..25f229b --- /dev/null +++ b/tests/unit/HealthTest.php @@ -0,0 +1,50 @@ +assertTrue(defined('APPPATH')); + } + + public function testBaseUrlHasBeenSet(): void + { + $validation = Services::validation(); + + $env = false; + + // Check the baseURL in .env + if (is_file(HOMEPATH . '.env')) { + $env = preg_grep('/^app\.baseURL = ./', file(HOMEPATH . '.env')) !== false; + } + + if ($env) { + // BaseURL in .env is a valid URL? + // phpunit.xml.dist sets app.baseURL in $_SERVER + // So if you set app.baseURL in .env, it takes precedence + $config = new App(); + $this->assertTrue( + $validation->check($config->baseURL, 'valid_url'), + 'baseURL "' . $config->baseURL . '" in .env is not valid URL' + ); + } + + // Get the baseURL in app/Config/App.php + // You can't use Config\App, because phpunit.xml.dist sets app.baseURL + $reader = new ConfigReader(); + + // BaseURL in app/Config/App.php is a valid URL? + $this->assertTrue( + $validation->check($reader->baseURL, 'valid_url'), + 'baseURL "' . $reader->baseURL . '" in app/Config/App.php is not valid URL' + ); + } +} diff --git a/writable/.htaccess b/writable/.htaccess new file mode 100644 index 0000000..a94c5b0 --- /dev/null +++ b/writable/.htaccess @@ -0,0 +1,12 @@ + + Require all denied + + + Deny from all + + + RewriteEngine On + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule ^(.*)$ index.php/$1 [L] + \ No newline at end of file diff --git a/writable/cache/index.html b/writable/cache/index.html new file mode 100644 index 0000000..b702fbc --- /dev/null +++ b/writable/cache/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/writable/excel/index.html b/writable/excel/index.html new file mode 100644 index 0000000..b702fbc --- /dev/null +++ b/writable/excel/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/writable/index.html b/writable/index.html new file mode 100644 index 0000000..b702fbc --- /dev/null +++ b/writable/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/writable/logs/index.html b/writable/logs/index.html new file mode 100644 index 0000000..b702fbc --- /dev/null +++ b/writable/logs/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/writable/uploads/index.html b/writable/uploads/index.html new file mode 100644 index 0000000..b702fbc --- /dev/null +++ b/writable/uploads/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + +