diff --git a/README.md b/README.md
index 5095dd3..c9056ab 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,5 @@
# IOcornerstone PHP 8.5 Framework
-Author Robert Strutts
-Copyright (c) 2010-2026 MIT
+## Author Robert Strutts
+## Copyright (c) 2010-2026 Robert Strutts
+## License MIT
diff --git a/src/Framework/Arrays/CommonStuff.php b/src/Framework/Arrays/CommonStuff.php
new file mode 100644
index 0000000..d828e30
--- /dev/null
+++ b/src/Framework/Arrays/CommonStuff.php
@@ -0,0 +1,102 @@
+ 'January',
+ '2' => 'February',
+ '3' => 'March',
+ '4' => 'April',
+ '5' => 'May',
+ '6' => 'June',
+ '7' => 'July',
+ '8' => 'August',
+ '9' => 'September',
+ '10' => 'October',
+ '11' => 'November',
+ '12' => 'December'
+ );
+ }
+
+ /**
+ * Fetch States in USA
+ * @return array of states
+ */
+ public static function statesArray(): array {
+ return array(
+ 'AL' => 'Alabama',
+ 'AK' => 'Alaska',
+ 'AZ' => 'Arizona',
+ 'AR' => 'Arkansas',
+ 'CA' => 'California',
+ 'CO' => 'Colorado',
+ 'CT' => 'Connecticut',
+ 'DE' => 'Delaware',
+ 'DC' => 'District of Columbia',
+ 'FL' => 'Florida',
+ 'GA' => 'Georgia',
+ 'HI' => 'Hawaii',
+ 'ID' => 'Idaho',
+ 'IL' => 'Illinois',
+ 'IN' => 'Indiana',
+ 'IA' => 'Iowa',
+ 'KS' => 'Kansas',
+ 'KY' => 'Kentucky',
+ 'LA' => 'Louisiana',
+ 'ME' => 'Maine',
+ 'MD' => 'Maryland',
+ 'MA' => 'Massachusetts',
+ 'MI' => 'Michigan',
+ 'MN' => 'Minnesota',
+ 'MS' => 'Mississippi',
+ 'MO' => 'Missouri',
+ 'MT' => 'Montana',
+ 'NE' => 'Nebraska',
+ 'NV' => 'Nevada',
+ 'NH' => 'New Hampshire',
+ 'NJ' => 'New Jersey',
+ 'NM' => 'New Mexico',
+ 'NY' => 'New York',
+ 'NC' => 'North Carolina',
+ 'ND' => 'North Dakota',
+ 'OH' => 'Ohio',
+ 'OK' => 'Oklahoma',
+ 'OR' => 'Oregon',
+ 'PA' => 'Pennsylvania',
+ 'RI' => 'Rhode Island',
+ 'SC' => 'South Carolina',
+ 'SD' => 'South Dakota',
+ 'TN' => 'Tennessee',
+ 'TX' => 'Texas',
+ 'UT' => 'Utah',
+ 'VT' => 'Vermont',
+ 'VA' => 'Virginia',
+ 'WA' => 'Washington',
+ 'WV' => 'West Virginia',
+ 'WI' => 'Wisconsin',
+ 'WY' => 'Wyoming',
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/src/Framework/Arrays/Countries.php b/src/Framework/Arrays/Countries.php
new file mode 100644
index 0000000..381413d
--- /dev/null
+++ b/src/Framework/Arrays/Countries.php
@@ -0,0 +1,262 @@
+ 'Aland Islands',
+ 'AF' => 'Afghanistan',
+ 'AL' => 'Albania',
+ 'DZ' => 'Algeria',
+ 'AS' => 'American Samoa',
+ 'AD' => 'Andorra',
+ 'AO' => 'Angola',
+ 'AI' => 'Anguilla',
+ 'AQ' => 'Antarctica',
+ 'AG' => 'Antigua And Barbuda',
+ 'AR' => 'Argentina',
+ 'AM' => 'Armenia',
+ 'AW' => 'Aruba',
+ 'AU' => 'Australia',
+ 'AT' => 'Austria',
+ 'AZ' => 'Azerbaijan',
+ 'BS' => 'Bahamas',
+ 'BH' => 'Bahrain',
+ 'BD' => 'Bangladesh',
+ 'BB' => 'Barbados',
+ 'BY' => 'Belarus',
+ 'BE' => 'Belgium',
+ 'BZ' => 'Belize',
+ 'BJ' => 'Benin',
+ 'BM' => 'Bermuda',
+ 'BT' => 'Bhutan',
+ 'BO' => 'Bolivia',
+ 'BA' => 'Bosnia And Herzegovina',
+ 'BW' => 'Botswana',
+ 'BV' => 'Bouvet Island',
+ 'BR' => 'Brazil',
+ 'IO' => 'British Indian Ocean Territory',
+ 'BN' => 'Brunei',
+ 'BG' => 'Bulgaria',
+ 'BF' => 'Burkina Faso',
+ 'AR' => 'Burma',
+ 'BI' => 'Burundi',
+ 'KH' => 'Cambodia',
+ 'CM' => 'Cameroon',
+ 'CA' => 'Canada',
+ 'CV' => 'Cape Verde',
+ 'KY' => 'Cayman Islands',
+ 'CF' => 'Central African Republic',
+ 'TD' => 'Chad',
+ 'CL' => 'Chile',
+ 'CN' => 'China',
+ 'CX' => 'Christmas Island',
+ 'CC' => 'Cocos (Keeling) Islands',
+ 'CO' => 'Columbia',
+ 'KM' => 'Comoros',
+ 'CG' => 'Congo',
+ 'CK' => 'Cook Islands',
+ 'CR' => 'Costa Rica',
+ 'CI' => 'Cote D\'Ivorie (Ivory Coast)',
+ 'HR' => 'Croatia (Hrvatska)',
+ 'CU' => 'Cuba',
+ 'CY' => 'Cyprus',
+ 'CZ' => 'Czech Republic static',
+ 'CD' => 'Democratic Republic Of Congo (Zaire)',
+ 'DK' => 'Denmark',
+ 'DJ' => 'Djibouti',
+ 'DM' => 'Dominica',
+ 'DO' => 'Dominican Republic',
+ 'TP' => 'East Timor',
+ 'EC' => 'Ecuador',
+ 'EG' => 'Egypt',
+ 'SV' => 'El Salvador',
+ 'GB' => 'England',
+ 'GQ' => 'Equatorial Guinea',
+ 'ER' => 'Eritrea',
+ 'EE' => 'Estonia',
+ 'ET' => 'Ethiopia',
+ 'EU' => 'European Union',
+ 'FK' => 'Falkland Islands (Malvinas)',
+ 'FO' => 'Faroe Islands',
+ 'FJ' => 'Fiji',
+ 'FI' => 'Finland',
+ 'FR' => 'France',
+ 'FX' => 'France, Metropolitan',
+ 'GF' => 'French Guinea',
+ 'PF' => 'French Polynesia',
+ 'TF' => 'French Southern Territories',
+ 'GA' => 'Gabon',
+ 'GM' => 'Gambia',
+ 'GE' => 'Georgia',
+ 'DE' => 'Germany',
+ 'GH' => 'Ghana',
+ 'GI' => 'Gibraltar',
+ 'GR' => 'Greece',
+ 'GL' => 'Greenland',
+ 'GD' => 'Grenada',
+ 'GP' => 'Guadeloupe',
+ 'GU' => 'Guam',
+ 'GT' => 'Guatemala',
+ 'GN' => 'Guinea',
+ 'GW' => 'Guinea-Bissau',
+ 'GY' => 'Guyana',
+ 'HT' => 'Haiti',
+ 'HM' => 'Heard And McDonald Islands',
+ 'HN' => 'Honduras',
+ 'HK' => 'Hong Kong',
+ 'HU' => 'Hungary',
+ 'IS' => 'Iceland',
+ 'IN' => 'India',
+ 'ID' => 'Indonesia',
+ 'IR' => 'Iran',
+ 'IQ' => 'Iraq',
+ 'IE' => 'Ireland',
+ 'IL' => 'Israel',
+ 'IT' => 'Italy',
+ 'JM' => 'Jamaica',
+ 'JP' => 'Japan',
+ 'JO' => 'Jordan',
+ 'KZ' => 'Kazakhstan',
+ 'KE' => 'Kenya',
+ 'KI' => 'Kiribati',
+ 'KW' => 'Kuwait',
+ 'KG' => 'Kyrgyzstan',
+ 'LA' => 'Laos',
+ 'LV' => 'Latvia',
+ 'LB' => 'Lebanon',
+ 'LS' => 'Lesotho',
+ 'LR' => 'Liberia',
+ 'LY' => 'Libya',
+ 'LI' => 'Liechtenstein',
+ 'LT' => 'Lithuania',
+ 'LU' => 'Luxembourg',
+ 'MO' => 'Macau',
+ 'MK' => 'Macedonia',
+ 'MG' => 'Madagascar',
+ 'MW' => 'Malawi',
+ 'MY' => 'Malaysia',
+ 'MV' => 'Maldives',
+ 'ML' => 'Mali',
+ 'MT' => 'Malta',
+ 'MH' => 'Marshall Islands',
+ 'MQ' => 'Martinique',
+ 'MR' => 'Mauritania',
+ 'MU' => 'Mauritius',
+ 'YT' => 'Mayotte',
+ 'MX' => 'Mexico',
+ 'FM' => 'Micronesia',
+ 'MD' => 'Moldova',
+ 'MC' => 'Monaco',
+ 'MN' => 'Mongolia',
+ 'ME' => 'Montenegro',
+ 'MS' => 'Montserrat',
+ 'MA' => 'Morocco',
+ 'MZ' => 'Mozambique',
+ 'MM' => 'Myanmar (Burma)',
+ 'NA' => 'Namibia',
+ 'NR' => 'Nauru',
+ 'NP' => 'Nepal',
+ 'NL' => 'Netherlands',
+ 'AN' => 'Netherlands Antilles',
+ 'NC' => 'New Caledonia',
+ 'NZ' => 'New Zealand',
+ 'NI' => 'Nicaragua',
+ 'NE' => 'Niger',
+ 'NG' => 'Nigeria',
+ 'NU' => 'Niue',
+ 'NF' => 'Norfolk Island',
+ 'KP' => 'North Korea',
+ 'MP' => 'Northern Mariana Islands',
+ 'NO' => 'Norway',
+ 'OM' => 'Oman',
+ 'PK' => 'Pakistan',
+ 'PW' => 'Palau',
+ 'PS' => 'Palestine',
+ 'PA' => 'Panama',
+ 'PG' => 'Papua New Guinea',
+ 'PY' => 'Paraguay',
+ 'PE' => 'Peru',
+ 'PH' => 'Philippines',
+ 'PN' => 'Pitcairn',
+ 'PL' => 'Poland',
+ 'PT' => 'Portugal',
+ 'PR' => 'Puerto Rico',
+ 'QA' => 'Qatar',
+ 'RE' => 'Reunion',
+ 'RO' => 'Romania',
+ 'RU' => 'Russia',
+ 'RW' => 'Rwanda',
+ 'SH' => 'Saint Helena',
+ 'KN' => 'Saint Kitts And Nevis',
+ 'LC' => 'Saint Lucia',
+ 'PM' => 'Saint Pierre And Miquelon',
+ 'VC' => 'Saint Vincent And The Grenadines',
+ 'SM' => 'San Marino',
+ 'ST' => 'Sao Tome And Principe',
+ 'SA' => 'Saudi Arabia',
+ 'SN' => 'Senegal',
+ 'SC' => 'Seychelles',
+ 'SL' => 'Sierra Leone',
+ 'SG' => 'Singapore',
+ 'SK' => 'Slovakia',
+ 'SI' => 'Slovenia',
+ 'SB' => 'Solomon Islands',
+ 'SO' => 'Somalia',
+ 'ZA' => 'South Africa',
+ 'GS' => 'South Georgia And South Sandwich Islands',
+ 'KR' => 'South Korea',
+ 'ES' => 'Spain',
+ 'LK' => 'Sri Lanka',
+ 'SD' => 'Sudan',
+ 'SR' => 'Suriname',
+ 'SJ' => 'Svalbard And Jan Mayen',
+ 'SZ' => 'Swaziland',
+ 'SE' => 'Sweden',
+ 'CH' => 'Switzerland',
+ 'SY' => 'Syria',
+ 'TW' => 'Taiwan',
+ 'TJ' => 'Tajikistan',
+ 'TZ' => 'Tanzania',
+ 'TH' => 'Thailand',
+ 'TG' => 'Togo',
+ 'TK' => 'Tokelau',
+ 'TO' => 'Tonga',
+ 'TT' => 'Trinidad And Tobago',
+ 'TN' => 'Tunisia',
+ 'TR' => 'Turkey',
+ 'TM' => 'Turkmenistan',
+ 'TC' => 'Turks And Caicos Islands',
+ 'TV' => 'Tuvalu',
+ 'UG' => 'Uganda',
+ 'UA' => 'Ukraine',
+ 'AE' => 'United Arab Emirates',
+ 'UK' => 'United Kingdom',
+ 'US' => 'United States',
+ 'UM' => 'United States Minor Outlying Islands',
+ 'UY' => 'Uruguay',
+ 'UZ' => 'Uzbekistan',
+ 'VU' => 'Vanuatu',
+ 'VA' => 'Vatican City',
+ 'VE' => 'Venezuela',
+ 'VN' => 'Vietnam',
+ 'VG' => 'Virgin Islands (British)',
+ 'VI' => 'Virgin Islands (US)',
+ 'WF' => 'Wallis And Futuna Islands',
+ 'EH' => 'Western Sahara',
+ 'WS' => 'Western Samoa',
+ 'YE' => 'Yemen',
+ 'YU' => 'Yugoslavia',
+ 'ZM' => 'Zambia',
+ 'ZW' => 'Zimbabwe'
+ );
+ }
+}
\ No newline at end of file
diff --git a/src/Framework/Arrays/Mimes.php b/src/Framework/Arrays/Mimes.php
new file mode 100644
index 0000000..66b24bc
--- /dev/null
+++ b/src/Framework/Arrays/Mimes.php
@@ -0,0 +1,166 @@
+ [
+ 'txt' => 'text/plain',
+ ],
+ 'web' => [
+ 'htm' => 'text/html',
+ 'html' => 'text/html',
+ 'css' => 'text/css',
+ 'json' => 'application/json',
+ 'xml' => 'application/xml'
+ ],
+ 'images' => [
+ 'png' => 'image/png',
+ 'jpe' => 'image/jpeg',
+ 'jpeg' => 'image/jpeg',
+ 'jpg' => 'image/jpeg',
+ 'gif' => 'image/gif',
+ 'bmp' => 'image/bmp',
+ 'ico' => 'image/vnd.microsoft.icon',
+ 'tiff' => 'image/tiff',
+ 'tif' => 'image/tiff',
+ 'svg' => 'image/svg+xml',
+ 'svgz' => 'image/svg+xml',
+ 'webp' => 'image/webp'
+ ],
+ 'archives' => [
+ 'zip' => 'application/zip',
+ 'rar' => 'application/x-rar-compressed',
+ 'cab' => 'application/vnd.ms-cab-compressed',
+ 'gz' => 'application/gzip',
+ 'tgz' => 'application/x-compressed',
+ 'tar' => 'application/x-tar',
+ 'iso' => 'application/x-iso9660-image',
+ 'bz2' => 'application/x-bzip2',
+ 'lz' => 'application/x-lzip',
+ 'xz' => 'application/x-xz',
+ '7z' => 'application/x-7z-compressed',
+ ],
+ 'audio' => [
+ 'oga' => 'audio/ogg', 'ogg' => 'audio/ogg', 'opus' => 'audio/ogg', 'spx' => 'audio/ogg',
+ 'mp3' => 'audio/mpeg',
+ 'wav' => 'audio/x-wav'
+ ],
+ 'video' => [
+ 'mpeg' => 'video/mpeg', 'mpg' => 'video/mpeg', 'mpe' => 'video/mpeg',
+ 'mp4' => 'video/mp4',
+ 'qt' => 'video/quicktime',
+ 'mov' => 'video/quicktime',
+ 'ogv' => 'video/ogg'
+ ],
+ 'adobe' => [
+ 'pdf' => 'application/pdf',
+ 'psd' => 'image/vnd.adobe.photoshop',
+ 'ai' => 'application/postscript',
+ 'eps' => 'application/postscript',
+ 'ps' => 'application/postscript'
+ ],
+ 'office' => [
+ 'doc' => 'application/msword',
+ 'rtf' => 'application/rtf',
+ 'xls' => 'application/vnd.ms-excel',
+ 'ppt' => 'application/vnd.ms-powerpoint',
+ 'odt' => 'application/vnd.oasis.opendocument.text',
+ 'ods' => 'application/vnd.oasis.opendocument.spreadsheet'
+ ]
+ ];
+ }
+
+ public static function mimesDangerious(): array {
+ return [
+ // Programming
+ 'js' => 'application/javascript',
+ 'php' => 'application/x-php-code',
+ 'py' => 'application/x-python-code',
+ 'pyc' => 'application/x-python-code',
+ 'pyo' => 'application/x-python-code',
+ 'torrent' => 'application/x-bittorrent',
+ // Linux
+ 'deb' => 'application/vnd.debian.binary-package',
+ 'rpm' => 'application/x-redhat-package-manager',
+ 'bash' => 'application/x-shellscript',
+ 'sh' => 'application/x-sh',
+ 'jar' => 'application/java',
+ 'java' => 'application/java',
+ // Windows
+ 'swf' => 'application/x-shockwave-flash', 'swfl' => 'application/x-shockwave-flash',
+ 'reg' => 'application/registry',
+ 'lnk' => 'application/shortcut',
+ 'inf' => 'application/config',
+ 'scf' => 'application/explorer',
+ // A Monad script file. Monad was later renamed PowerShell.
+ 'msh' => 'shell', 'msh1' => 'shell', 'msh2' => 'shell', 'mshxml' => 'shell', 'msh1xml' => 'shell', 'msh2xml' => 'shell',
+ // Power Shell
+ 'ps1' => 'shell', 'ps1xml' => 'shell', 'ps2' => 'shell', 'ps2xml' => 'shell', 'psc1' => 'shell', 'psc2' => 'shell',
+ 'wsc' => 'application/scripting-component', 'wsh' => 'application/scripting-host', 'ws' => 'application/scripting', 'wsf' => 'application/scripting',
+ 'jse' => 'application/javascript-encrypted',
+ 'vbe' => 'application/vbscript-encrypted',
+ 'vb' => 'application/visualbasic',
+ 'vbs' => 'application/visualbasic',
+ 'bat' => 'application/batch',
+ 'cmd' => 'application/batch',
+ 'exe' => 'application/x-msdownload',
+ 'pif' => 'application/executiable',
+ 'application' => 'application/oneclick',
+ 'gadget' => 'vista/desktop',
+ 'msi' => 'application/x-msdownload',
+ 'msp' => 'application/patch',
+ 'com' => 'application/dos',
+ 'scr' => 'application/screen-saver',
+ 'hta' => 'html/application',
+ 'cpl' => 'application/control-panel',
+ 'msc' => 'application/m-console',
+ // Office 2007 Macros
+ 'docm' => 'macro/msword',
+ 'dotm' => 'macro/template',
+ 'xlsm' => 'macro/excel',
+ 'xltm' => 'macro', 'xlam' => 'macro', 'pptm' => 'macro', 'potm' => 'macro', 'ppam' => 'macro', 'ppsm' => 'macro', 'sldm' => 'marco'
+ ];
+ }
+
+ public static function getMimeType(string $filename, array $allowed = ['all']) {
+ $ext = strtolower(array_pop(explode('.', $filename)));
+ $bad = self::mimesDangerious();
+
+ if (array_key_exists($ext, $bad)) {
+ return false;
+ }
+
+ $mime_types = self::mimesArray();
+
+ $everyone = in_array('all', $allowed);
+
+ foreach ($mime_types as $key => $mime) {
+ if (($everyone || in_array($key, $allowed) ) && array_key_exists($ext, $mime)) {
+ return $mime[$ext];
+ }
+ }
+
+ if ($everyone) {
+ if (function_exists('finfo_open')) {
+ $finfo = finfo_open(FILEINFO_MIME);
+ $mimetype = finfo_file($finfo, $filename);
+ finfo_close($finfo);
+ return $mimetype;
+ } else {
+ return 'application/octet-stream';
+ }
+ }
+
+ return false;
+ }
+
+}
diff --git a/src/Framework/Arrays/Mocking/Address.php b/src/Framework/Arrays/Mocking/Address.php
new file mode 100644
index 0000000..2ef743f
--- /dev/null
+++ b/src/Framework/Arrays/Mocking/Address.php
@@ -0,0 +1,45 @@
+ 'Ave',
+ 'BOULEVARD' => 'Blvd',
+ 'DRIVE' => 'Dr',
+ 'LANE' => 'Ln',
+ 'MOUNT' => 'Mt',
+ 'ROAD' => 'Rd',
+ 'STREET' => 'St',
+ ' NORTH ' => ' N. ',
+ ' SOUTH ' => ' S. ',
+ ' EAST ' => ' E. ',
+ ' WEST ' => ' W. '
+ ];
+ foreach ($uspsAbbreviations as $key => $value) {
+ $text = str_ireplace($key, $value, $text);
+ }
+ return $text;
+ }
+
+}
\ No newline at end of file
diff --git a/src/Framework/Arrays/ZipCodes.php b/src/Framework/Arrays/ZipCodes.php
new file mode 100644
index 0000000..85dbedc
--- /dev/null
+++ b/src/Framework/Arrays/ZipCodes.php
@@ -0,0 +1,185 @@
+= 35000 && $zipcode <= 36999) {
+ $st = 'AL';
+ $state = 'Alabama';
+ } else if ($zipcode >= 99500 && $zipcode <= 99999) {
+ $st = 'AK';
+ $state = 'Alaska';
+ } else if ($zipcode >= 85000 && $zipcode <= 86999) {
+ $st = 'AZ';
+ $state = 'Arizona';
+ } else if ($zipcode >= 71600 && $zipcode <= 72999) {
+ $st = 'AR';
+ $state = 'Arkansas';
+ } else if ($zipcode >= 90000 && $zipcode <= 96699) {
+ $st = 'CA';
+ $state = 'California';
+ } else if ($zipcode >= 80000 && $zipcode <= 81999) {
+ $st = 'CO';
+ $state = 'Colorado';
+ } else if (($zipcode >= 6000 && $zipcode <= 6389) || ($zipcode >= 6391 && $zipcode <= 6999)) {
+ $st = 'CT';
+ $state = 'Connecticut';
+ } else if ($zipcode >= 19700 && $zipcode <= 19999) {
+ $st = 'DE';
+ $state = 'Delaware';
+ } else if ($zipcode >= 32000 && $zipcode <= 34999) {
+ $st = 'FL';
+ $state = 'Florida';
+ } else if (($zipcode >= 30000 && $zipcode <= 31999) || ($zipcode >= 39800 && $zipcode <= 39999)) {
+ $st = 'GA';
+ $state = 'Georgia';
+ } else if ($zipcode >= 96700 && $zipcode <= 96999) {
+ $st = 'HI';
+ $state = 'Hawaii';
+ } else if ($zipcode >= 83200 && $zipcode <= 83999) {
+ $st = 'ID';
+ $state = 'Idaho';
+ } else if ($zipcode >= 60000 && $zipcode <= 62999) {
+ $st = 'IL';
+ $state = 'Illinois';
+ } else if ($zipcode >= 46000 && $zipcode <= 47999) {
+ $st = 'IN';
+ $state = 'Indiana';
+ } else if ($zipcode >= 50000 && $zipcode <= 52999) {
+ $st = 'IA';
+ $state = 'Iowa';
+ } else if ($zipcode >= 66000 && $zipcode <= 67999) {
+ $st = 'KS';
+ $state = 'Kansas';
+ } else if ($zipcode >= 40000 && $zipcode <= 42999) {
+ $st = 'KY';
+ $state = 'Kentucky';
+ } else if ($zipcode >= 70000 && $zipcode <= 71599) {
+ $st = 'LA';
+ $state = 'Louisiana';
+ } else if ($zipcode >= 3900 && $zipcode <= 4999) {
+ $st = 'ME';
+ $state = 'Maine';
+ } else if ($zipcode >= 20600 && $zipcode <= 21999) {
+ $st = 'MD';
+ $state = 'Maryland';
+ } else if (($zipcode >= 1000 && $zipcode <= 2799) || ($zipcode == 5501) || ($zipcode == 5544 )) {
+ $st = 'MA';
+ $state = 'Massachusetts';
+ } else if ($zipcode >= 48000 && $zipcode <= 49999) {
+ $st = 'MI';
+ $state = 'Michigan';
+ } else if ($zipcode >= 55000 && $zipcode <= 56899) {
+ $st = 'MN';
+ $state = 'Minnesota';
+ } else if ($zipcode >= 38600 && $zipcode <= 39999) {
+ $st = 'MS';
+ $state = 'Mississippi';
+ } else if ($zipcode >= 63000 && $zipcode <= 65999) {
+ $st = 'MO';
+ $state = 'Missouri';
+ } else if ($zipcode >= 59000 && $zipcode <= 59999) {
+ $st = 'MT';
+ $state = 'Montana';
+ } else if ($zipcode >= 27000 && $zipcode <= 28999) {
+ $st = 'NC';
+ $state = 'North Carolina';
+ } else if ($zipcode >= 58000 && $zipcode <= 58999) {
+ $st = 'ND';
+ $state = 'North Dakota';
+ } else if ($zipcode >= 68000 && $zipcode <= 69999) {
+ $st = 'NE';
+ $state = 'Nebraska';
+ } else if ($zipcode >= 88900 && $zipcode <= 89999) {
+ $st = 'NV';
+ $state = 'Nevada';
+ } else if ($zipcode >= 3000 && $zipcode <= 3899) {
+ $st = 'NH';
+ $state = 'New Hampshire';
+ } else if ($zipcode >= 7000 && $zipcode <= 8999) {
+ $st = 'NJ';
+ $state = 'New Jersey';
+ } else if ($zipcode >= 87000 && $zipcode <= 88499) {
+ $st = 'NM';
+ $state = 'New Mexico';
+ } else if (($zipcode >= 10000 && $zipcode <= 14999) || ($zipcode == 6390) || ($zipcode == 501) || ($zipcode == 544)) {
+ $st = 'NY';
+ $state = 'New York';
+ } else if ($zipcode >= 43000 && $zipcode <= 45999) {
+ $st = 'OH';
+ $state = 'Ohio';
+ } else if (($zipcode >= 73000 && $zipcode <= 73199) || ($zipcode >= 73400 && $zipcode <= 74999)) {
+ $st = 'OK';
+ $state = 'Oklahoma';
+ } else if ($zipcode >= 97000 && $zipcode <= 97999) {
+ $st = 'OR';
+ $state = 'Oregon';
+ } else if ($zipcode >= 15000 && $zipcode <= 19699) {
+ $st = 'PA';
+ $state = 'Pennsylvania';
+ } else if ($zipcode >= 300 && $zipcode <= 999) {
+ $st = 'PR';
+ $state = 'Puerto Rico';
+ } else if ($zipcode >= 2800 && $zipcode <= 2999) {
+ $st = 'RI';
+ $state = 'Rhode Island';
+ } else if ($zipcode >= 29000 && $zipcode <= 29999) {
+ $st = 'SC';
+ $state = 'South Carolina';
+ } else if ($zipcode >= 57000 && $zipcode <= 57999) {
+ $st = 'SD';
+ $state = 'South Dakota';
+ } else if ($zipcode >= 37000 && $zipcode <= 38599) {
+ $st = 'TN';
+ $state = 'Tennessee';
+ } else if (($zipcode >= 75000 && $zipcode <= 79999) || ($zipcode >= 73301 && $zipcode <= 73399) || ($zipcode >= 88500 && $zipcode <= 88599)) {
+ $st = 'TX';
+ $state = 'Texas';
+ } else if ($zipcode >= 84000 && $zipcode <= 84999) {
+ $st = 'UT';
+ $state = 'Utah';
+ } else if ($zipcode >= 5000 && $zipcode <= 5999) {
+ $st = 'VT';
+ $state = 'Vermont';
+ } else if (($zipcode >= 20100 && $zipcode <= 20199) || ($zipcode >= 22000 && $zipcode <= 24699) || ($zipcode == 20598)) {
+ $st = 'VA';
+ $state = 'Virgina';
+ } else if (($zipcode >= 20000 && $zipcode <= 20099) || ($zipcode >= 20200 && $zipcode <= 20599) || ($zipcode >= 56900 && $zipcode <= 56999)) {
+ $st = 'DC';
+ $state = 'Washington DC';
+ } else if ($zipcode >= 98000 && $zipcode <= 99499) {
+ $st = 'WA';
+ $state = 'Washington';
+ } else if ($zipcode >= 24700 && $zipcode <= 26999) {
+ $st = 'WV';
+ $state = 'West Virginia';
+ } else if ($zipcode >= 53000 && $zipcode <= 54999) {
+ $st = 'WI';
+ $state = 'Wisconsin';
+ } else if ($zipcode >= 82000 && $zipcode <= 83199) {
+ $st = 'WY';
+ $state = 'Wyoming';
+ } else {
+ $st = 'none';
+ $state = 'none';
+ return 'No state found matching' . $zipcode;
+ }
+
+ return ['abbr' => $st, 'state' => $state];
+ }
+
+}
\ No newline at end of file
diff --git a/src/Framework/Assets.php b/src/Framework/Assets.php
new file mode 100644
index 0000000..b8fb6fb
--- /dev/null
+++ b/src/Framework/Assets.php
@@ -0,0 +1,267 @@
+$a_media) {
+ $ret .= self::wrapCss($file, $scope, $a_media);
+ }
+ return $ret;
+ }
+
+ public static function loadallJs(array $files, string $scope='project'): string {
+ $ret = '';
+ foreach($files as $file=>$a) {
+ $ret .= self::wrapJs($file, $scope, $a);
+ }
+ return $ret;
+ }
+
+ public static function image(string $file, string $scope = '', array $a = array()): string {
+ $more = '';
+ if (count($a)) {
+ foreach ($a as $k => $v) {
+ $more .= " {$k}=\"{$v}\"";
+ }
+ }
+ $file = self::wrapAsset($file, $scope);
+ if ($file === false) {
+ return '';
+ }
+ return "\r\n";
+ }
+
+ public static function alert($msg) {
+ return self::inlineJs('alert("'.$msg.'");');
+ }
+
+ /**
+ * Wrapper for JS/CSS assets for the page.
+ * @param string $file or CDN
+ * @param string $scope (project/framework/cdn)
+ * @retval boolean|string false is not found, else Asset REF
+ */
+ public static function wrapAsset(string $file, string $scope = 'project') {
+ $scope = StringFacade::strtolower($scope);
+ if ($scope === 'cdn') {
+ $proto = bootstrap\safer_io::get_clean_server_var('SERVER_PROTOCOL');
+ if ($proto === null) {
+ $protocol = '://';
+ } else {
+ $protocol = strtolower(substr($proto, 0, strpos($proto, '/'))) . '://';
+ }
+ return (str_contains($file, '://') === true) ? $file : $protocol . $file;
+ }
+ if ($scope === 'project' || $scope === 'app') {
+ $path = PROJECT_ASSETS_DIR . "/";
+ $ism = self::isMinified($path, $file);
+ return ($ism !== false) ? PROJECT_ASSETS_BASE_REF . "/" . $ism : false;
+ }
+ if ($scope === 'assets') {
+ $path = ASSETS_DIR . "/";
+ $ism = self::isMinified($path, $file);
+ return ($ism !== false) ? ASSETS_BASE_REF . "/" . $ism : false;
+ }
+ return $file;
+ }
+ /**
+ * Fetch Version of file if exists
+ * @param string $file
+ * @param string $scope
+ * @return string|bool
+ */
+ private static function projectPaths(string $file, string $scope = 'project'): string | bool {
+ $scope = stringFacade::strtolower($scope);
+ if ($scope === 'cdn') {
+ return "";
+ } else if ($scope === 'project' || $scope === 'app') {
+ $path = PROJECT_ASSETS_DIR . "/";
+ } else if ($scope === 'assets') {
+ $path = ASSETS_DIR . "/";
+ } else {
+ return "";
+ }
+ $check = self::is_minified($path, $file);
+ return ($check !==false) ? self::get_ver($path . $check) : false;
+ }
+
+ /**
+ * Wrapper to return the CSS href=file.. stylesheet code for use in page.
+ * @param string $file - CSS file
+ * @param string $media - default of all media
+ * @retval string
+ */
+ public static function wrapCss(string $file, string $scope = 'project', array $a_media = array()): string {
+ $more = '';
+ if (count($a_media)) {
+ foreach ($a_media as $k => $v) {
+ $more .= " {$k}=\"{$v}\"";
+ }
+ } else {
+ $more .= " media=\"all\"";
+ }
+
+ $ver = self::projectPaths($file, $scope);
+ $wrap_file = self::wrapAsset($file, $scope);
+ if ($ver === false || $wrap_file === false) {
+ return "";
+ }
+ return "\r\n";
+ }
+
+ /**
+ * Wrapper to return the JavaScript src=file... code for use with page.
+ * @param type $file - external JS file.
+ * @retval string of script src=file
+ */
+ public static function wrapJs(string $file, string $scope = 'project', array $a = array()): string {
+ $more = '';
+ if (count($a)) {
+ foreach ($a as $k => $v) {
+ $more .= (isset($k) && $k !=0 ) ? " {$k}=\"{$v}\"" : " {$v}";
+ }
+ }
+
+ $ver = self::projectPaths($file, $scope);
+ $wrap_file = self::wrapAsset($file, $scope);
+ if ($ver === false || $wrap_file === false) {
+ return "";
+ }
+ return "\r\n";
+ //return "";
+ }
+
+ /**
+ * Purpose: To do inline JavaScript.
+ * @param type $code string of code to inline into page.
+ * @retval type
+ */
+ public static function inlineJs(string $code): string {
+ return "\r\n";
+ }
+
+ /**
+ * Purpose: To execute this JavaScript code once JQuery is Ready().
+ * @param string $code to do once JQuery is Ready
+ * @retval string wrapped in ready code...
+ */
+ public static function jqueryLoad(string $code): string {
+ return "\r\n$(function() { \r\n \t {$code} \r\n }); \r\n";
+ }
+
+ public static function isMinified(string $path, string $file) {
+ if (self::attemptsRootDir($path)) {
+ return false;
+ }
+ $safe_path = Security::filterUri($path);
+ $safe_file = Security::filterUri($file);
+
+ if (str_contains($safe_file, '.auto.js')) {
+ $production = (isLive());
+ $safe_file = str_replace('.auto.js', '', $safe_file);
+ if ( $production && file_exists($safe_path . $safe_file . '.min.js') ) {
+ return $safe_file . '.min.js';
+ }
+ return (file_exists($safe_path . $safe_file . '.js')) ? $safe_file . '.js' : false;
+ }
+
+ if (str_contains($safe_file, '.auto.css')) {
+ $production = (isLive());
+ $safe_file = str_replace('.auto.css', '', $safe_file);
+ if ( $production && file_exists($safe_path . $safe_file . '.min.css') ) {
+ return $safe_file . '.min.css';
+ }
+ return (file_exists($safe_path . $safe_file . '.css')) ? $safe_file . '.css' : false;
+ }
+ return ( file_exists($safe_path . $safe_file) ) ? $safe_file : false;
+ }
+
+ /**
+ * meta redirect when headers are already sent...
+ * @param string url - site to do redirect on
+ * @reval none
+ */
+ public static function gotoUrl(string $url): void {
+ echo '';
+ exit;
+ }
+
+ /**
+ * Rediect to url and attempt to send via header.
+ * @param string $url - site to do redirect for
+ * @retval none - exits once done
+ */
+ public static function redirectUrl(string $url): void {
+ $url = str_replace(array('&', "\n", "\r"), array('&', '', ''), $url);
+ if (!headers_sent()) {
+ header('Location: ' . $url);
+ } else {
+ self::goto_url($url);
+ }
+ exit;
+ }
+
+}
diff --git a/src/Framework/Attributes/Validators/MyValidator.php b/src/Framework/Attributes/Validators/MyValidator.php
new file mode 100644
index 0000000..674eefb
--- /dev/null
+++ b/src/Framework/Attributes/Validators/MyValidator.php
@@ -0,0 +1,229 @@
+ is_string($message));
+ // overwrite the default message
+ $validationErrors = array_merge(self::DEFAULT_VALIDATION_ERRORS, $ruleMessages);
+
+ $fn = 'is_' . $rule_name;
+ $field = $name;
+ $data[$name] = $value;
+
+ $callable = self::class . "::{$fn}";
+
+ $string_params = array_map('strval', $params);
+
+ if (is_callable($callable)) {
+ $pass = $callable($data, $field, ...$string_params);
+ if (!$pass) {
+ $lookfor = $messages[$field][$rule_name] ?? $validationErrors[$rule_name];
+ $new_params = array_values($params);
+ $this->errors[$field] = sprintf(
+ $lookfor,
+ $field,
+ ...$params
+ );
+ }
+ }
+ }
+
+ /**
+ *
+ * @param object $object
+ * @param array $messages defined in trait
+ * @param type $default null avoids an error on no-entry, false gives errors on no-entry
+ * @return void
+ */
+
+ public function validate(object $object, array $messages = [], DEFAULT_VALUE $default_value = DEFAULT_VALUE::do_not_error_on_null): void {
+
+$handlers = [
+ Positive::class => function (string $name, $value, $attr, array $messages) {
+ $this->handleErrors("positive", $name, $value, messages: $messages);
+ },
+
+ Required::class => function (string $name, $value, $attr, array $messages) {
+ $this->handleErrors("required", $name, $value, messages: $messages);
+ },
+
+ Email::class => function (string $name, $value, $attr, array $messages) {
+ $this->handleErrors("email", $name, $value, messages: $messages);
+ },
+
+ GreaterThan::class => function (string $name, $value, $attr, array $messages) {
+ $params[] = $attr->value;
+ $this->handleErrors("greaterThan", $name, $value, $params, $messages);
+ },
+
+ LessThan::class => function (string $name, $value, $attr, array $messages) {
+ $params[] = $attr->value;
+ $this->handleErrors("lessThan", $name, $value, $params, $messages);
+ },
+
+ Min::class => function (string $name, $value, $attr, array $messages) {
+ $params[] = $attr->value;
+ $this->handleErrors("min", $name, $value, $params, $messages);
+ },
+
+ Max::class => function (string $name, $value, $attr, array $messages) {
+ $params[] = $attr->value;
+ $this->handleErrors("max", $name, $value, $params, $messages);
+ },
+
+ NumberRange::class => function (string $name, $value, $attr, array $messages) {
+ $params[] = $attr->min;
+ $params[] = $attr->max;
+
+ $this->handleErrors("numberRange", $name, $value, $params, $messages);
+ },
+
+ Between::class => function (string $name, $value, $attr, array $messages) {
+ $params[] = $attr->min;
+ $params[] = $attr->max;
+
+ $this->handleErrors("between", $name, $value, $params, $messages);
+ },
+
+ Same::class => function (string $name, $value, $attr, array $messages) {
+ $params[] = $attr->value;
+ $this->handleErrors("same", $name, $value, $params, $messages);
+ },
+
+ Alphanumeric::class => function (string $name, $value, $attr, array $messages) {
+ $this->handleErrors("alphanumeric", $name, $value, messages: $messages);
+ },
+
+ Secure::class => function (string $name, $value, $attr, array $messages) {
+ $this->handleErrors("secure", $name, $value, messages: $messages);
+ },
+
+ ValidEmailDomain::class => function (string $name, $value, $attr, array $messages) {
+ $this->handleErrors("validEmailDomain", $name, $value, messages: $messages);
+ },
+
+ ValidDomain::class => function (string $name, $value, $attr, array $messages) {
+ $this->handleErrors("validDomain", $name, $value, messages: $messages);
+ },
+
+];
+
+ $default = match($default_value) {
+ DEFAULT_VALUE::do_not_error_on_null => null,
+ // Fail validation as user requested false on default
+ DEFAULT_VALUE::do_error_on_null => false,
+ default => null, // Pass validation as null or value unset
+ };
+
+ $ref = new \ReflectionObject($object);
+
+ foreach ($ref->getProperties() as $property) {
+ $name = $property->getName();
+ $property->setAccessible(true);
+ $value = $property->getValue($object) ?? $default;
+
+ foreach ($property->getAttributes() as $attribute) {
+ $class = $attribute->getName();
+
+ if (!isset($handlers[$class])) {
+ continue;
+ }
+
+ $handlers[$class](
+ $name,
+ $value,
+ $attribute->newInstance(),
+ $messages
+ );
+ }
+ }
+ }
+
+ public function getErrors(): array {
+ return $this->errors;
+ }
+}
\ No newline at end of file
diff --git a/src/Framework/BbCodeParser.php b/src/Framework/BbCodeParser.php
new file mode 100644
index 0000000..07d0cea
--- /dev/null
+++ b/src/Framework/BbCodeParser.php
@@ -0,0 +1,176 @@
+ [
+ 'pattern' => '/\[h1\](.*?)\[\/h1\]/s',
+ 'replace' => '
$1', + 'content' => '$1' + ], + 'link' => [ + 'pattern' => '/\[url\](.*?)\[\/url\]/s', + 'replace' => '$1', + 'content' => '$1' + ], + 'namedlink' => [ + 'pattern' => '/\[url\=(.*?)\](.*?)\[\/url\]/s', + 'replace' => '$2', + 'content' => '$2' + ], + 'image' => [ + 'pattern' => '/\[img\](.*?)\[\/img\]/s', + 'replace' => '
$1',
+ 'content' => '$1'
+ ],
+ 'youtube' => [
+ 'pattern' => '/\[youtube\](.*?)\[\/youtube\]/s',
+ 'replace' => '',
+ 'content' => '$1'
+ ],
+ 'sub' => [
+ 'pattern' => '/\[sub\](.*?)\[\/sub\]/s',
+ 'replace' => '$1',
+ 'content' => '$1'
+ ],
+ 'sup' => [
+ 'pattern' => '/\[sup\](.*?)\[\/sup\]/s',
+ 'replace' => '$1',
+ 'content' => '$1'
+ ],
+ 'small' => [
+ 'pattern' => '/\[small\](.*?)\[\/small\]/s',
+ 'replace' => '$1',
+ 'content' => '$1'
+ ],
+ 'table' => [
+ 'pattern' => '/\[table\](.*?)\[\/table\]/s',
+ 'replace' => '| {$field} | {$nl}", $echo); + } + $ret .= self::doEcho("\t
|---|
| {$cell} | {$nl}", $echo); + } + $ret .= self::doEcho("\t
(.*?)<\/code>/s',
+ 'replace' => '[code]$1[/code]',
+ 'content' => '$1'
+ ],
+ 'orderedlistnumerical' => [
+ 'pattern' => '/(.*?)<\/ol>/s',
+ 'replace' => '[list=1]$1[/list]',
+ 'content' => '$1'
+ ],
+ 'unorderedlist' => [
+ 'pattern' => '/(.*?)<\/ul>/s',
+ 'replace' => '[list]$1[/list]',
+ 'content' => '$1'
+ ],
+ 'listitem' => [
+ 'pattern' => '/- (.*?)<\/li>/s',
+ 'replace' => '[*]$1',
+ 'content' => '$1'
+ ],
+ 'link' => [
+ 'pattern' => '/(.*?)<\/a>/s',
+ 'replace' => '[url=$1]$2[/url]',
+ 'content' => '$1'
+ ],
+ 'quote' => [
+ 'pattern' => '/
(.*?)<\/blockquote>/s',
+ 'replace' => '[quote]$1[/quote]',
+ 'content' => '$1'
+ ],
+ 'image' => [
+ 'pattern' => '/
/s',
+ 'replace' => '[img]$1[/img]',
+ 'content' => '$1'
+ ],
+ 'youtube' => [
+ 'pattern' => '/