├── .gitattributes ├── .gitignore ├── .htaccess ├── 3wifi.php ├── 3wifi.sql ├── 3wifid.php ├── 404.html ├── LICENSE ├── README.md ├── add_quadkeys.php ├── api ├── .htaccess └── ajax.php ├── apidoc.html ├── config.php-distr ├── counter.txt ├── css └── style.css ├── db.php ├── devmac.html ├── devmac.php ├── dlink_seq.php ├── faq.html ├── favicon.ico ├── find.html ├── geoext.php ├── graph.html ├── home.html ├── img ├── add.png ├── find.png ├── icon-fav-off.png ├── icon-fav-on.png ├── icon-hidden.png ├── icon-ip.png ├── icon-location.png ├── icon-map.png ├── icon-nowifi.png ├── icon-warning.png ├── loading.gif ├── loadsm.gif ├── logo.png ├── map.png ├── no.png ├── ok.png ├── rickroll.gif ├── search.png ├── stat.png └── warning.png ├── import.free.php ├── index.html ├── index.php ├── ipext.php ├── js ├── FileSaver.min.js ├── jquery-2.1.4.min.js ├── jquery.flot.categories.min.js ├── jquery.flot.min.js └── jquery.flot.resize.js ├── l10n ├── .htaccess ├── en-US.php ├── en.php ├── ru-RU.php └── ru.php ├── map.html ├── project_news.json ├── quadkey.php ├── ranges.html ├── robots.txt ├── rules.html ├── service_news.json ├── stat.html ├── statext.php ├── themes ├── .htaccess └── antichat │ ├── img │ ├── ajax.gif │ ├── bg.gif │ ├── logo.gif │ ├── menu_off.gif │ ├── menu_on.gif │ ├── rac.png │ ├── raz.gif │ └── shbg.gif │ ├── style.css │ └── theme.php ├── upload.html ├── uploads └── .htaccess ├── user.class.php ├── user.html ├── user.php ├── utils.php ├── win_login.html ├── win_newpass.html ├── win_reg.html ├── win_wait.html ├── wpspin.html └── wpspin.php /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Конфиг 2 | /config.php 3 | 4 | # Загрузки, кроме .htaccess 5 | /uploads/* 6 | !/uploads/.htaccess 7 | 8 | # Счетчик 9 | /counter.txt 10 | 11 | # Лог отладки 12 | /Debug.log 13 | 14 | # Среда разработки 15 | /.idea/* 16 | 17 | # SypexDumper 18 | /sxd/* 19 | -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | Options -Indexes 2 | 3 | RewriteEngine on 4 | 5 | # Redirect legacy pages 6 | RewriteRule left.html index.php?redir=home [NC,L,QSA] 7 | RewriteRule main.html index.php?redir=home [NC,L,QSA] 8 | RewriteRule devicemac.html index.php?redir=devmac [NC,L,QSA] 9 | RewriteRule ^(['_A-Za-z]+).html index.php?redir=$1 [NC,L,QSA] 10 | RewriteRule ^(map[0-9]*+).php index.php?redir=map [NC,L,QSA] 11 | RewriteRule find_ranges.php index.php?redir=ranges [NC,L,QSA] 12 | 13 | # Rewrite for simple URIs 14 | RewriteRule home$ index.php?page=home [NC,L,QSA] 15 | RewriteRule rules$ index.php?page=rules [NC,L,QSA] 16 | RewriteRule faq$ index.php?page=faq [NC,L,QSA] 17 | RewriteRule apidoc$ index.php?page=apidoc [NC,L,QSA] 18 | RewriteRule map$ index.php?page=map [NC,L,QSA] 19 | RewriteRule find$ index.php?page=find [NC,L,QSA] 20 | RewriteRule ranges$ index.php?page=ranges [NC,L,QSA] 21 | RewriteRule devmac$ index.php?page=devmac [NC,L,QSA] 22 | RewriteRule wpspin$ index.php?page=wpspin [NC,L,QSA] 23 | RewriteRule upload$ index.php?page=upload [NC,L,QSA] 24 | RewriteRule graph$ index.php?page=graph [NC,L,QSA] 25 | RewriteRule stat$ index.php?page=stat [NC,L,QSA] 26 | RewriteRule user$ index.php?page=user [NC,L,QSA] 27 | 28 | # 404 page 29 | ErrorDocument 404 /index.php?page=404 30 | 31 | 32 | AddOutputFilterByType DEFLATE text/html text/xml application/xml application/xhtml+xml text/css text/javascript application/javascript application/x-javascript application/json application/json-p 33 | -------------------------------------------------------------------------------- /3wifi.sql: -------------------------------------------------------------------------------- 1 | -- ------------------------------ 2 | -- Структура базы данных 3WiFi -- 3 | -- ------------------------------ 4 | 5 | -- Дамп структуры базы данных 3wifi 6 | CREATE DATABASE IF NOT EXISTS `3wifi` /*!40100 DEFAULT CHARACTER SET utf8 */; 7 | USE `3wifi`; 8 | 9 | -- Дамп структуры таблицы 3wifi.base 10 | CREATE TABLE `base` ( 11 | `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, 12 | `time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 13 | `cmtid` INT(10) UNSIGNED NULL DEFAULT NULL, 14 | `IP` INT(10) NULL DEFAULT NULL, 15 | `Port` SMALLINT(5) UNSIGNED NULL DEFAULT NULL, 16 | `Authorization` TINYTEXT NULL, 17 | `name` TINYTEXT NOT NULL, 18 | `RadioOff` BIT(1) NOT NULL DEFAULT b'0', 19 | `Hidden` BIT(1) NOT NULL DEFAULT b'0', 20 | `NoBSSID` TINYINT(3) UNSIGNED NOT NULL, 21 | `BSSID` BIGINT(15) UNSIGNED NOT NULL, 22 | `ESSID` VARCHAR(32) NOT NULL, 23 | `Security` TINYINT(1) UNSIGNED NOT NULL, 24 | `WiFiKey` VARCHAR(64) NOT NULL, 25 | `WPSPIN` INT(8) UNSIGNED NOT NULL, 26 | `LANIP` INT(10) NULL DEFAULT NULL, 27 | `LANMask` INT(10) NULL DEFAULT NULL, 28 | `WANIP` INT(10) NULL DEFAULT NULL, 29 | `WANMask` INT(10) NULL DEFAULT NULL, 30 | `WANGateway` INT(10) NULL DEFAULT NULL, 31 | `DNS1` INT(10) NULL DEFAULT NULL, 32 | `DNS2` INT(10) NULL DEFAULT NULL, 33 | `DNS3` INT(10) NULL DEFAULT NULL, 34 | PRIMARY KEY (`id`), 35 | INDEX `BSSID` (`BSSID`), 36 | INDEX `ESSID` (`ESSID`), 37 | INDEX `Time` (`time`), 38 | UNIQUE INDEX `WIFI` (`NoBSSID`, `BSSID`, `ESSID`, `WiFiKey`, `WPSPIN`) 39 | ) COLLATE='utf8_general_ci' ENGINE=InnoDB; 40 | 41 | -- Дамп структуры таблицы 3wifi.geo 42 | CREATE TABLE `geo` ( 43 | `BSSID` BIGINT(15) UNSIGNED NOT NULL, 44 | `latitude` FLOAT(12,8) NULL DEFAULT NULL, 45 | `longitude` FLOAT(12,8) NULL DEFAULT NULL, 46 | `quadkey` BIGINT(20) UNSIGNED NULL DEFAULT NULL, 47 | PRIMARY KEY (`BSSID`), 48 | INDEX `quadkey` (`quadkey`), 49 | INDEX `latitude` (`latitude`) 50 | ) COLLATE='utf8_general_ci' ENGINE=InnoDB; 51 | 52 | -- Дамп структуры для таблицы 3wifi.invites 53 | CREATE TABLE IF NOT EXISTS `invites` ( 54 | `invite` CHAR(12) NOT NULL, 55 | `puid` INT(11) UNSIGNED NOT NULL, 56 | `time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 57 | `uid` INT(11) UNSIGNED NULL DEFAULT NULL, 58 | `level` TINYINT(4) NOT NULL DEFAULT '1', 59 | PRIMARY KEY (`invite`) 60 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 61 | 62 | -- Дамп структуры таблицы 3wifi.comments 63 | CREATE TABLE `comments` ( 64 | `cmtid` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, 65 | `cmtval` VARCHAR(127) NOT NULL, 66 | PRIMARY KEY (`cmtid`), 67 | UNIQUE INDEX `comment` (`cmtval`) 68 | ) COLLATE='utf8_general_ci' ENGINE=InnoDB; 69 | 70 | -- Дамп структуры таблицы 3wifi.tasks 71 | CREATE TABLE `tasks` ( 72 | `tid` CHAR(32) NOT NULL, 73 | `uid` INT(11) UNSIGNED NULL DEFAULT NULL, 74 | `ipaddr` INT(11) NOT NULL, 75 | `tstate` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0, 76 | `created` TIMESTAMP NOT NULL DEFAULT current_timestamp(), 77 | `modified` TIMESTAMP NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), 78 | `ext` CHAR(4) NOT NULL, 79 | `comment` TINYTEXT NOT NULL, 80 | `checkexist` BIT(1) NOT NULL, 81 | `nowait` BIT(1) NOT NULL, 82 | `lines` INT(10) UNSIGNED NOT NULL DEFAULT 0, 83 | `accepted` INT(10) UNSIGNED NOT NULL DEFAULT 0, 84 | `onmap` INT(10) UNSIGNED NOT NULL DEFAULT 0, 85 | `warns` TEXT NULL DEFAULT NULL, 86 | PRIMARY KEY (`tid`), 87 | INDEX `task_state` (`tstate`), 88 | INDEX `created_time` (`created`) 89 | ) 90 | COLLATE='utf8_general_ci' ENGINE=InnoDB; 91 | 92 | -- Дамп структуры таблицы 3wifi.ranges 93 | CREATE TABLE `ranges` ( 94 | `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, 95 | `startIP` INT(10) UNSIGNED NOT NULL, 96 | `endIP` INT(10) UNSIGNED NOT NULL, 97 | `netname` TINYTEXT NOT NULL, 98 | `descr` TINYTEXT NOT NULL, 99 | `country` CHAR(2) NOT NULL, 100 | PRIMARY KEY (`id`), 101 | UNIQUE INDEX `RANGE` (`startIP`, `endIP`) 102 | ) COLLATE='utf8_general_ci' ENGINE=InnoDB; 103 | 104 | -- Дамп структуры таблицы 3wifi.stats 105 | CREATE TABLE `stats` ( 106 | `StatId` INT(15) UNSIGNED NOT NULL, 107 | `Value` INT(10) UNSIGNED NOT NULL DEFAULT '0', 108 | `LastUpdate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 109 | PRIMARY KEY (`StatId`) 110 | ) COLLATE='utf8_general_ci' ENGINE=MEMORY; 111 | 112 | -- Дамп структуры таблицы 3wifi.mem_base 113 | CREATE TABLE `mem_base` ( 114 | `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, 115 | `time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 116 | `cmtid` INT(10) UNSIGNED NULL DEFAULT NULL, 117 | `IP` INT(10) NULL DEFAULT NULL, 118 | `Port` SMALLINT(5) UNSIGNED NULL DEFAULT NULL, 119 | `Authorization` VARCHAR(64) NULL DEFAULT NULL, 120 | `name` VARCHAR(64) NOT NULL, 121 | `RadioOff` BIT(1) NOT NULL DEFAULT b'0', 122 | `Hidden` BIT(1) NOT NULL DEFAULT b'0', 123 | `NoBSSID` TINYINT(3) UNSIGNED NOT NULL, 124 | `BSSID` BIGINT(15) UNSIGNED NOT NULL, 125 | `ESSID` VARCHAR(32) NOT NULL, 126 | `Security` TINYINT(1) UNSIGNED NOT NULL, 127 | `WiFiKey` VARCHAR(64) NOT NULL, 128 | `WPSPIN` INT(8) UNSIGNED NOT NULL, 129 | `LANIP` INT(10) NULL DEFAULT NULL, 130 | `LANMask` INT(10) NULL DEFAULT NULL, 131 | `WANIP` INT(10) NULL DEFAULT NULL, 132 | `WANMask` INT(10) NULL DEFAULT NULL, 133 | `WANGateway` INT(10) NULL DEFAULT NULL, 134 | `DNS1` INT(10) NULL DEFAULT NULL, 135 | `DNS2` INT(10) NULL DEFAULT NULL, 136 | `DNS3` INT(10) NULL DEFAULT NULL, 137 | PRIMARY KEY (`id`), 138 | INDEX `BSSID` (`BSSID`), 139 | INDEX `ESSID` (`ESSID`), 140 | INDEX `Time` (`time`), 141 | UNIQUE INDEX `WIFI` (`NoBSSID`, `BSSID`, `ESSID`, `WiFiKey`, `WPSPIN`) 142 | ) COLLATE='utf8_general_ci' ENGINE=MEMORY; 143 | 144 | -- Дамп структуры таблицы 3wifi.mem_geo 145 | CREATE TABLE `mem_geo` ( 146 | `BSSID` BIGINT(15) UNSIGNED NOT NULL, 147 | `latitude` FLOAT(12,8) NULL DEFAULT NULL, 148 | `longitude` FLOAT(12,8) NULL DEFAULT NULL, 149 | `quadkey` BIGINT(20) UNSIGNED NULL DEFAULT NULL, 150 | PRIMARY KEY (`BSSID`), 151 | INDEX `quadkey` (`quadkey`), 152 | INDEX `latitude` (`latitude`) 153 | ) COLLATE='utf8_general_ci' ENGINE=MEMORY; 154 | 155 | -- Дамп структуры для таблицы 3wifi.users 156 | CREATE TABLE `users` ( 157 | `uid` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, 158 | `regdate` TIMESTAMP NULL DEFAULT NULL, 159 | `lastupdate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 160 | `puid` INT(11) NOT NULL DEFAULT '0', 161 | `login` VARCHAR(30) NOT NULL, 162 | `nick` VARCHAR(30) NOT NULL, 163 | `pass_hash` CHAR(32) NOT NULL, 164 | `autologin` CHAR(32) NOT NULL, 165 | `salt` CHAR(32) NOT NULL, 166 | `level` TINYINT(4) NOT NULL DEFAULT '0', 167 | `ip_hash` CHAR(32) NOT NULL, 168 | `invites` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0', 169 | `rapikey` CHAR(32) NULL DEFAULT NULL, 170 | `wapikey` CHAR(32) NULL DEFAULT NULL, 171 | `querytime` TIMESTAMP NULL DEFAULT NULL, 172 | `ban_reason` VARCHAR(16) NULL DEFAULT NULL, 173 | PRIMARY KEY (`uid`), 174 | UNIQUE INDEX `login` (`login`), 175 | UNIQUE INDEX `nick` (`nick`) 176 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 177 | 178 | -- Дамп структуры для таблицы 3wifi.logauth 179 | CREATE TABLE `logauth` ( 180 | `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, 181 | `timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 182 | `IP` INT(15) NOT NULL, 183 | `uid` INT(11) UNSIGNED NULL DEFAULT NULL, 184 | `action` TINYINT(3) UNSIGNED NOT NULL, 185 | `data` CHAR(64) NOT NULL DEFAULT '', 186 | `status` BIT(1) NOT NULL DEFAULT b'0', 187 | PRIMARY KEY (`id`) 188 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 189 | 190 | -- Дамп структуры для таблицы 3wifi.logupload 191 | CREATE TABLE `logupload` ( 192 | `id` INT(10) UNSIGNED NOT NULL, 193 | `updated` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 194 | `ipaddr` INT(11) NOT NULL, 195 | PRIMARY KEY (`id`), 196 | UNIQUE INDEX `FK1_logupload_base` (`id`), 197 | INDEX `updated` (`updated`), 198 | INDEX `ipaddr` (`ipaddr`), 199 | CONSTRAINT `FK1_logupload_base` FOREIGN KEY (`id`) REFERENCES `base` (`id`) ON UPDATE CASCADE ON DELETE CASCADE 200 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 201 | 202 | -- Дамп структуры для таблицы 3wifi.uploads 203 | CREATE TABLE `uploads` ( 204 | `uid` INT(10) UNSIGNED NOT NULL, 205 | `id` INT(10) UNSIGNED NOT NULL, 206 | `creator` BIT(1) NOT NULL DEFAULT b'0', 207 | UNIQUE INDEX `upload` (`uid`, `id`), 208 | INDEX `FK_uploads_base` (`id`), 209 | INDEX `uid` (`uid`), 210 | CONSTRAINT `FK_uploads_users` FOREIGN KEY (`uid`) REFERENCES `users` (`uid`) ON UPDATE CASCADE ON DELETE CASCADE, 211 | CONSTRAINT `FK_uploads_base` FOREIGN KEY (`id`) REFERENCES `base` (`id`) ON UPDATE CASCADE ON DELETE CASCADE 212 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 213 | 214 | -- Дамп структуры для таблицы 3wifi.favorites 215 | CREATE TABLE `favorites` ( 216 | `uid` INT(10) UNSIGNED NOT NULL, 217 | `id` INT(10) UNSIGNED NOT NULL, 218 | UNIQUE INDEX `favorite` (`uid`, `id`), 219 | INDEX `FK_favorites_base` (`id`), 220 | INDEX `uid` (`uid`), 221 | CONSTRAINT `FK_favorites_users` FOREIGN KEY (`uid`) REFERENCES `users` (`uid`) ON UPDATE CASCADE ON DELETE CASCADE, 222 | CONSTRAINT `FK_favorites_base` FOREIGN KEY (`id`) REFERENCES `base` (`id`) ON UPDATE CASCADE ON DELETE CASCADE 223 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 224 | 225 | -- Дамп структуры для таблицы 3wifi.locations 226 | CREATE TABLE `locations` ( 227 | `uid` INT(10) UNSIGNED NOT NULL, 228 | `latitude` FLOAT(12,8) NOT NULL, 229 | `longitude` FLOAT(12,8) NOT NULL, 230 | `comment` VARCHAR(127) NOT NULL, 231 | UNIQUE INDEX `uniq` (`uid`, `latitude`, `longitude`), 232 | INDEX `uid` (`uid`), 233 | INDEX `coords` (`latitude`, `longitude`), 234 | CONSTRAINT `FK_locations_users` FOREIGN KEY (`uid`) REFERENCES `users` (`uid`) ON UPDATE CASCADE ON DELETE CASCADE 235 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 236 | 237 | -- Дамп данных таблицы 3wifi.users 238 | INSERT INTO `users` SET 239 | `regdate`=CURRENT_TIMESTAMP, 240 | `login`='admin', 241 | `nick`='Administrator', 242 | `salt`='2p8a!m%EFHr).djHO1uuIA^x82X$(988', 243 | `pass_hash`=MD5(CONCAT('admin',`salt`)), 244 | `autologin`='', 245 | `level`=3, 246 | `ip_hash`='', 247 | `invites`=65535; 248 | 249 | -- Дамп структуры для таблицы 3wifi.extinfo 250 | CREATE TABLE `extinfo` ( 251 | `id` INT(11) NOT NULL, 252 | `data` VARCHAR(255) NOT NULL, 253 | `sn1` VARCHAR(50) NULL DEFAULT NULL, 254 | `sn2` VARCHAR(50) NULL DEFAULT NULL, 255 | `cable_mac` BIGINT(15) NULL DEFAULT NULL, 256 | PRIMARY KEY (`id`), 257 | INDEX `data_index` (`data`) 258 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 259 | 260 | -- Дамп данных процедуры 3wifi.show_graph_stat 261 | CREATE PROCEDURE `show_graph_stat` ( 262 | IN `radius` INT 263 | ) 264 | LANGUAGE SQL 265 | NOT DETERMINISTIC 266 | CONTAINS SQL 267 | BEGIN 268 | IF radius = 0 THEN 269 | SET @tme = (SELECT `time` FROM base WHERE `time` <= NOW() ORDER BY `time` DESC LIMIT 1); 270 | ELSE 271 | SET @tme = (SELECT `time` FROM base JOIN radius_ids USING(id) WHERE `time` <= NOW() ORDER BY radius_ids.id DESC LIMIT 1); 272 | END IF; 273 | SET @a = 0; 274 | 275 | a_loop: 276 | WHILE @a < 30 DO 277 | IF FOUND_ROWS() = 0 THEN 278 | LEAVE a_loop; 279 | END IF; 280 | IF @a = 0 THEN 281 | IF radius = 0 THEN 282 | CREATE TEMPORARY TABLE IF NOT EXISTS tmp_graph AS ( 283 | SELECT DATE_FORMAT(time,'%Y.%m.%d') AS `date`, COUNT(id) AS `count` FROM base 284 | WHERE `time` BETWEEN 285 | CONCAT(SUBSTRING_INDEX(@tme, ' ', 1), ' 00:00:00') AND 286 | CONCAT(SUBSTRING_INDEX(@tme, ' ', 1), ' 23:59:59') 287 | ); 288 | ELSE 289 | CREATE TEMPORARY TABLE IF NOT EXISTS tmp_graph AS ( 290 | SELECT DATE_FORMAT(time,'%Y.%m.%d') AS `date`, COUNT(id) AS `count` FROM base 291 | JOIN radius_ids USING(id) 292 | WHERE `time` BETWEEN 293 | CONCAT(SUBSTRING_INDEX(@tme, ' ', 1), ' 00:00:00') AND 294 | CONCAT(SUBSTRING_INDEX(@tme, ' ', 1), ' 23:59:59') 295 | ); 296 | END IF; 297 | ELSE 298 | IF radius = 0 THEN 299 | INSERT INTO tmp_graph 300 | SELECT DATE_FORMAT(time,'%Y.%m.%d') AS `date`, COUNT(id) AS `count` FROM base 301 | WHERE `time` BETWEEN 302 | CONCAT(SUBSTRING_INDEX(@tme, ' ', 1), ' 00:00:00') AND 303 | CONCAT(SUBSTRING_INDEX(@tme, ' ', 1), ' 23:59:59'); 304 | ELSE 305 | INSERT INTO tmp_graph 306 | SELECT DATE_FORMAT(time,'%Y.%m.%d') AS `date`, COUNT(id) AS `count` FROM base 307 | JOIN radius_ids USING(id) 308 | WHERE `time` BETWEEN 309 | CONCAT(SUBSTRING_INDEX(@tme, ' ', 1), ' 00:00:00') AND 310 | CONCAT(SUBSTRING_INDEX(@tme, ' ', 1), ' 23:59:59'); 311 | END IF; 312 | END IF; 313 | SET @a = @a + 1; 314 | IF radius = 0 THEN 315 | SET @tme = (SELECT `time` FROM base WHERE `time` < CONCAT(SUBSTRING_INDEX(@tme, ' ', 1), ' 00:00:00') ORDER BY `time` DESC LIMIT 1); 316 | ELSE 317 | SET @tme = (SELECT `time` FROM base JOIN radius_ids USING(id) WHERE `time` < CONCAT(SUBSTRING_INDEX(@tme, ' ', 1), ' 00:00:00') ORDER BY radius_ids.id DESC LIMIT 1); 318 | END IF; 319 | END WHILE a_loop; 320 | 321 | SELECT * FROM tmp_graph; 322 | DROP TABLE IF EXISTS tmp_graph; 323 | END 324 | -------------------------------------------------------------------------------- /404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
%l10n_msg_404%
7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 3WiFi Database 2 | 3 | (c) 2015-2022 Anton Kokarev et al. 4 | 5 | This project was created to collect data from Router Scan log reports, search for access points, obtain its geolocation coordinates, and display it on world map. 6 | 7 | ## Prerequirements: 8 | 1. Disable display of errors, warnings, and notices in `php.ini` 9 | 1. Make sure your web server is set up to apply .htaccess policies per directory 10 | 1. Make sure you have installed `bcmath`, `curl`, `mysqli`, and `simplexml` php extensions 11 | 12 | ## Installation steps: 13 | 1. Copy all required files to your `/www` directory 14 | 1. Create database (execute `3wifi.sql` to create tables) 15 | 1. Copy config.php-distr to config.php 16 | 1. Edit config.php (DB_SERV, DB_NAME, DB_USER, DB_PASS etc) 17 | 1. (optional) Turn on memory tables (in the `config.php` define `TRY_USE_MEMORY_TABLES` as `true`) 18 | 1. (optional) Use `import.free.php` once to import old format database 19 | 1. Start all background daemons: 20 | ```sh 21 | # Upload routine loads data into database 22 | php -f 3wifid.php uploads 23 | # Finalize routine prepares tasks for finalization 24 | php -f 3wifid.php finalize 25 | # Geolocate routine locates new added BSSIDs on map 26 | php -f 3wifid.php geolocate 27 | # Stats routine caches statistics (use only when stats caching enabled) 28 | php -f 3wifid.php stats 29 | # Memory table manager (use only with memory tables enabled) 30 | php -f 3wifid.php memory 31 | ``` 32 | 33 | ## Database maintenance: 34 | ```sh 35 | # Recheck not found BSSIDs in the database 36 | php -f 3wifid.php recheck 37 | ``` 38 | Before running the daemons, make sure that `php-cli` interpreter is accessible from your directory. 39 | -------------------------------------------------------------------------------- /add_quadkeys.php: -------------------------------------------------------------------------------- 1 | query($sql)) 22 | { 23 | echo "Failed to alter table $geo_table: "; 24 | echo "(" . $db->errno . ") " . $db->error; 25 | } 26 | 27 | $coord_res = QuerySql( 28 | "SELECT * FROM $geo_table 29 | WHERE `latitude` != 0 AND `longitude` != 0 30 | AND `latitude` IS NOT NULL AND `longitude` IS NOT NULL 31 | AND `quadkey` IS NULL"); 32 | if (!$coord_res) 33 | { 34 | echo "Failed to select from $geo_table: "; 35 | echo "(" . $db->errno . ") " . $db->error; 36 | exit(); 37 | } 38 | if (!($stmt = $db->prepare("UPDATE $geo_table SET `quadkey`=? WHERE `BSSID`=?"))) 39 | { 40 | echo "Failed to prepare query: (" . $db->errno . ") " . $db->error; 41 | exit(); 42 | } 43 | $quadkey = ''; 44 | $bssid = ''; 45 | if (!$stmt->bind_param("ss", $quadkey, $bssid)) 46 | { 47 | echo "Failed to bind params: (" . $stmt->errno . ") " . $stmt->error; 48 | exit(); 49 | } 50 | while ($coord_row = $coord_res->fetch_row()) { 51 | $bssid = $coord_row[0]; 52 | $quadkey = base_convert( 53 | latlon_to_quadkey($coord_row[1], $coord_row[2], MAX_ZOOM_LEVEL), 54 | 2, 55 | 10); 56 | $stmt->execute(); 57 | } 58 | $stmt->close(); 59 | } 60 | -------------------------------------------------------------------------------- /api/.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine on 2 | 3 | # Rewrite for APIs 4 | RewriteRule ^(\w+)$ ../3wifi.php?a=$1 [NC,L,QSA] 5 | -------------------------------------------------------------------------------- /api/ajax.php: -------------------------------------------------------------------------------- 1 | Auth($password, $login, true)) 20 | break; 21 | $data = $UserManager->getApiKeys(); 22 | if (is_null($data['rapikey'])) 23 | { 24 | $data['rapikey'] = $UserManager->createApiKey(1); 25 | } 26 | $json['lastupdate'] = 0; 27 | $json['r'] = $data['rapikey']; 28 | $json['w'] = $data['wapikey']; 29 | $json['Successes'] = true; 30 | } 31 | break; 32 | 33 | case 'Find': 34 | $json['Successes'] = false; 35 | $ver = $_GET['Version']; 36 | $key = $_GET['Key']; 37 | $bssid = $_GET['BSSID']; 38 | if (!in_array($ver, array('0.5', '0.51'), true)) 39 | { 40 | $json['Error'] = array('Code' => 0, 'Desc' => 'Unsupported version'); 41 | break; 42 | } 43 | if (!is_string($key) || empty($key) || !is_string($bssid) || empty($bssid) || !ismac($bssid)) 44 | { 45 | $json['Error'] = array('Code' => 0, 'Desc' => 'Wrong input'); 46 | break; 47 | } 48 | if (!$UserManager->AuthByApiKey($key, true)) 49 | { 50 | $json['Error'] = array('Code' => -100, 'Desc' => 'Wrong API key'); 51 | break; 52 | } 53 | if ($UserManager->ApiAccess != 'read') 54 | { 55 | $json['Error'] = array('Code' => 0, 'Desc' => 'API key have no "read" rights'); 56 | break; 57 | } 58 | if (!db_connect()) 59 | { 60 | $json['Error'] = array('Code' => 0, 'Desc' => 'Database unavailable'); 61 | break; 62 | } 63 | $bssid = mac2dec($bssid); 64 | $sql = "SELECT 65 | WiFiKey, WPSPIN 66 | FROM 67 | BASE_TABLE 68 | WHERE 69 | BSSID = $bssid 70 | ORDER BY 71 | time DESC 72 | LIMIT 10"; 73 | $res = QuerySql($sql); 74 | $json['Keys'] = array(); 75 | $json['WPS'] = array(); 76 | while ($row = $res->fetch_row()) 77 | { 78 | $json['Keys'][] = $row[0]; 79 | $json['WPS'][] = pin2str($row[1]); 80 | } 81 | $json['Successes'] = true; 82 | break; 83 | 84 | case 'AppVersion': 85 | $json['Successes'] = true; 86 | $json['ActualyVersion'] = '0.51'; 87 | $json['WhatNews'] = 'This API is depreciated and will be removed.'; 88 | break; 89 | 90 | case 'GetUserInfo': 91 | $json['Successes'] = false; 92 | $ver = $_GET['Version']; 93 | $key = $_GET['Key']; 94 | if (!in_array($ver, array('0.5', '0.51'), true)) 95 | { 96 | $json['Error'] = array('Code' => 0, 'Desc' => 'Unsupported version'); 97 | break; 98 | } 99 | if (!is_string($key) || empty($key)) 100 | { 101 | $json['Error'] = array('Code' => 0, 'Desc' => 'Wrong input'); 102 | break; 103 | } 104 | if (!$UserManager->AuthByApiKey($key, true)) 105 | { 106 | $json['Error'] = array('Code' => -100, 'Desc' => 'Wrong API key'); 107 | break; 108 | } 109 | $json['Nickname'] = '3WiFi User'; 110 | $json['RegDate'] = ''; 111 | $json['Level'] = 1; 112 | $json['InvCount'] = 0; 113 | $json['Inviter'] = 'This API is depreciated and will be removed.'; 114 | $json['LastUpdate'] = ''; 115 | $json['Successes'] = true; 116 | break; 117 | } 118 | 119 | Header('Content-Type: application/json'); 120 | echo json_encode($json); 121 | -------------------------------------------------------------------------------- /apidoc.html: -------------------------------------------------------------------------------- 1 | 3WiFi: Описание API 2 | 3 | 4 | 5 | 6 | 7 |
8 |

Описание API

9 | Сервис предоставляет доступ к базе данных через API.
10 | Ниже описан процесс отправки запроса, а так же доступные методы.

11 | 12 |
13 | 14 |

Все API запросы отправляются по следующему URI: /api/%method%, где method - название API-метода.

15 |

Различные методы могут принимать данные в разном формате. Большая часть методов использует API-ключи для доступа к функциям.

16 |

Все методы возвращают результат выполнения result, который равен true в случае успеха, либо false в случае неудачи. В последнем случае также возвращается параметр error с описанием возникшей ошибки.

17 | 18 |

Реализованные методы API

19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 42 | 44 | 46 | 47 | 48 | 50 | 51 | 52 | 54 | 56 | 57 | 58 | 60 | 61 | 62 | 74 | 75 | 76 | 77 | 78 | 79 | 83 | 85 | 87 | 88 | 89 | 91 | 92 | 93 | 95 | 96 | 97 | 99 | 100 | 101 | 117 | 118 | 119 | 120 | 121 | 122 | 126 | 128 | 130 | 131 | 132 | 134 | 135 | 136 | 152 | 153 | 154 | 155 | 156 | 157 | 161 | 163 | 165 | 166 | 167 | 169 | 170 | 171 | 173 | 174 | 175 | 191 | 192 | 193 | 194 | 195 | 196 | 200 | 202 | 204 | 205 | 206 | 208 | 209 | 210 | 212 | 213 | 214 | 216 | 217 | 218 | 227 | 228 |
МетодОписаниеВходные данныеВыходные данные
Тип данныхПараметры
apikeysПолучает API-ключи пользователя (и опционально генерирует их) 40 | POST (форма)
41 | POST (JSON-объект)
43 | string login - логин пользователя 45 | object profile - данные профиля пользователя: nick - никнейм, regdate - дата регистрации, level - уровень доступа
49 | string password - пароль пользователя
53 | bool genread - генерировать ключ на чтение при его отсутствии (опционально) 55 | array data - массив API-ключей, содержащий записи с полями key - ключ и access - права доступа для этого ключа (либо read - на чтение, либо write - на запись)
59 | bool genwrite - генерировать ключ на запись при его отсутствии (опционально)
63 |

Примеры:

64 | POST /api/apikeys
65 | Content-Type: application/x-www-form-urlencoded; charset=UTF-8
66 |
67 | login=user123&password=pass123

68 | POST /api/apikeys
69 | Content-Type: application/json
70 |
71 | {"login": "user123", "password": "pass123"}

72 |

Ответ:

73 | {"result": true, "profile": {"nick": "Anonymous", "regdate": "2015-12-13 12:00:00", "level": 1}, "data": [{"key": "0011223344", "access": "read"}, {"key": "5566778899", "access": "write"}]}
apiqueryЗапрашивает точки доступа из базы (точное совпадение с BSSID и/или ESSID) 80 | GET (запрос)
81 | POST (форма)
82 | POST (JSON-объект)
84 | string key - API-ключ с правами на чтение 86 | array data - массив найденных данных, ключи массива содержат либо "BSSID", либо пару "BSSID|ESSID", в зависимости от того, что было запрошено; каждая запись в массиве содержит в себе ещё один массив соответствий со следующими параметрами: time - дата и время загрузки записи в базу, bssid - BSSID, essid - ESSID, sec - тип защиты, key - ключ сети, wps - WPS пин код, lat - широта, lon - долгота
90 | array bssid - массив BSSID точек доступа
94 | array essid - массив ESSID точек доступа (опционально), если указан - должен быть соразмерен с массивом BSSID и соответствовать записям в нём
98 | bool sens - учитывать регистр символов ESSID (опционально)
102 |

Примеры (запрос одной точки):

103 | GET /api/apiquery?key=001122334455&bssid=01:23:45:67:89:AB
104 | POST /api/apiquery
105 | Content-Type: application/json
106 |
107 | {"key": "001122334455", "bssid": "01:23:45:67:89:AB"}

108 |

Ответ:

109 | {"result": true, "data": {"01:23:45:67:89:AB": [{"time": "2017-04-09 21:00:00", "bssid": "01:23:45:67:89:AB", "essid": "Wi-Fi AP", "sec": "WPA2", "key": "wifipass", "wps": "12345670", "lat": 55.76, "lon": 37.64}]}} 110 |

Примеры (запрос нескольких точек):

111 | POST /api/apiquery
112 | Content-Type: application/json
113 |
114 | {"key": "001122334455", "bssid": ["11:22:33:44:55:66", "77:88:99:AA:BB:CC"]}

115 |

Ответ:

116 | {"result": true, "data": {"11:22:33:44:55:66": [{"time": "2017-04-09 21:00:00", "bssid": "11:22:33:44:55:66", "essid": "Wi-Fi AP 1", "sec": "WPA2", "key": "wifipass", "wps": "12345670", "lat": 55.76, "lon": 37.64}], "77:88:99:AA:BB:CC": [{"time": "2017-04-09 21:00:00", "bssid": "77:88:99:AA:BB:CC", "essid": "Wi-Fi AP 2", "sec": "WPA2", "key": "wifipass", "wps": "12345670", "lat": 55.76, "lon": 37.64}]}}
apiwpsГенерирует WPS PIN коды на основе BSSID и данных из базы 123 | GET (запрос)
124 | POST (форма)
125 | POST (JSON-объект)
127 | string key - API-ключ с правами на чтение 129 | array data - массив найденных данных, ключи массива содержат "BSSID"; каждая запись в массиве содержит в себе ещё один массив scores со следующими параметрами: name - название алгоритма генерации пин кода, value - значение пин кода, score - вероятность (значение от 0 до 1)
133 | array bssid - массив BSSID точек доступа
137 |

Примеры (единичный запрос):

138 | GET /api/apiwps?key=001122334455&bssid=01:23:45:67:89:AB
139 | POST /api/apiwps
140 | Content-Type: application/json
141 |
142 | {"key": "001122334455", "bssid": "01:23:45:67:89:AB"}

143 |

Ответ:

144 | {"result": true, "data": {"01:23:45:67:89:AB": {"scores": [{"name": "Static PIN", "value": "12345670", "score": 0.75}]}}} 145 |

Примеры (мульти-запрос):

146 | POST /api/apiwps
147 | Content-Type: application/json
148 |
149 | {"key": "001122334455", "bssid": ["11:22:33:44:55:66", "77:88:99:AA:BB:CC"]}

150 |

Ответ:

151 | {"result": true, "data": {"11:22:33:44:55:66": {"scores": [{"name": "Static PIN", "value": "12345670", "score": 0.75}]}, "77:88:99:AA:BB:CC": {"scores": [{"name": "Static PIN", "value": "12345670", "score": 0.75}]}}}
apidevОпределяет модели устройств на основе BSSID и похожих устройств в базе 158 | GET (запрос)
159 | POST (форма)
160 | POST (JSON-объект)
162 | string key - API-ключ с правами на чтение 164 | array data - массив найденных данных, ключи массива содержат "BSSID"; каждая запись представляет из себя ещё один массив со следующими параметрами: name - название устройства, score - вероятность (значение от 0 до 1), count - кол-во таких же устройств в базе
168 | array bssid - массив BSSID точек доступа
172 | bool nocli - исключать Wi-Fi клиенты из определения (по умолчанию включено)
176 |

Примеры (единичный запрос):

177 | GET /api/apidev?key=001122334455&bssid=01:23:45:67:89:AB
178 | POST /api/apidev
179 | Content-Type: application/json
180 |
181 | {"key": "001122334455", "bssid": "01:23:45:67:89:AB"}

182 |

Ответ:

183 | {"result": true, "data": {"01:23:45:67:89:AB": [{"name": "Router Model 1", "score": 0.9, "count": 2000}, {"name": "Router Model 2", "score": 0.75, "count": 500}, {"name": "Router Model 3", "score": 0.4, "count": 100}]}} 184 |

Примеры (мульти-запрос):

185 | POST /api/apidev
186 | Content-Type: application/json
187 |
188 | {"key": "001122334455", "bssid": ["11:22:33:44:55:66", "77:88:99:AA:BB:CC"]}

189 |

Ответ:

190 | {"result": true, "data": {"11:22:33:44:55:66": [{"name": "Router Model 1", "score": 0.9, "count": 2000}, {"name": "Router Model 2", "score": 0.75, "count": 500}, {"name": "Router Model 3", "score": 0.4, "count": 100}], "77:88:99:AA:BB:CC": [{"name": "Router Model 4", "score": 0.75, "count": 2000}, {"name": "Router Model 5", "score": 0.6, "count": 500}, {"name": "Router Model 6", "score": 0.2, "count": 100}]}}
apirangesПолучает список диапазонов по широте, долготе и радиусу 197 | GET (запрос)
198 | POST (форма)
199 | POST (JSON-объект)
201 | string key - API-ключ с правами на чтение 203 | array data - массив найденных данных; каждая запись в массиве содержит параметры: range - IP диапазон, netname - название сети, descr - описание диапазона, country - двухсимвольный код страны
207 | float lat - широта (от -90 до 90)
211 | float lon - долгота (от -180 до 180)
215 | float rad - радиус (от 0.001 до 25)
219 |

Примеры (единичный запрос):

220 | GET /api/apiranges?key=001122334455&lat=%var_lat%&lon=%var_lon%&rad=%var_rad%
221 | POST /api/apiranges
222 | Content-Type: application/json
223 |
224 | {"key": "001122334455", "lat": %var_lat%, "lon": %var_lon%, "rad": %var_rad%}

225 |

Ответ:

226 | {"result": true, "data": [{"range": "192.168.0.0/16", "netname": "", "descr": "Local IP range", "country": ""}]}
229 | 230 |
231 |
232 | -------------------------------------------------------------------------------- /config.php-distr: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | ul { 2 | text-align: left; 3 | } 4 | .modal { 5 | display: none; 6 | position: fixed; 7 | top: 0px; 8 | left: 0px; 9 | width: 100%; 10 | height: 100%; 11 | opacity: 0; 12 | z-index: 4; 13 | } 14 | .modal_bkg { 15 | position: fixed; 16 | top: 0px; 17 | left: 0px; 18 | width: 100%; 19 | height: 100%; 20 | background: black; 21 | opacity: 0.7; 22 | } 23 | .modal_cnt { 24 | min-width: 400px; 25 | min-height: 250px; 26 | margin: 0 auto; 27 | overflow: visible; 28 | position: absolute; 29 | left: 50%; 30 | top: 50%; 31 | margin-left: -200px; 32 | margin-top: -125px; 33 | background: #353535; 34 | opacity: 0.975; 35 | border-radius: 10px; 36 | color: white; 37 | font-family: sans-serif; 38 | -webkit-box-shadow: 0px 0px 15px 6px rgba(255,255,255,0.6); 39 | -moz-box-shadow: 0px 0px 15px 6px rgba(255,255,255,0.6); 40 | box-shadow: 0px 0px 15px 6px rgba(255,255,255,0.6); 41 | } 42 | .modal_cnt h2 { 43 | background: #555; 44 | margin-top: 18px; 45 | margin-bottom: 12px; 46 | padding-top: 4px; 47 | padding-bottom: 4px; 48 | } 49 | .modal_cnt a { 50 | color: yellow; 51 | font-weight: bold; 52 | } 53 | .modal_cnt table { 54 | color: inherit; 55 | } 56 | .modal_main { 57 | height: 100%; 58 | } 59 | .modal_div { 60 | padding-top: 0px; 61 | height: 250px; 62 | } 63 | form td#checkinv, 64 | form td#checklogin, 65 | form td#checknick, 66 | form td#checkpass { 67 | width: 18px; 68 | } 69 | .mainmenu { 70 | background-color: black; 71 | color: white; 72 | position: relative; 73 | height: 52px; 74 | top: 22px; 75 | } 76 | .mainmenu a { 77 | color: inherit; 78 | text-decoration: none; 79 | } 80 | .menulogo { 81 | position: absolute; 82 | top: -28px; 83 | left: 8px; 84 | z-index: 3; 85 | cursor: pointer; 86 | -moz-transition: all 0.8s 0.1s ease-in; 87 | -o-transition: all 0.8s 0.1s ease-in; 88 | -webkit-transition: all 0.3s 0.1s ease-in; 89 | } 90 | .menulogo:hover { 91 | position: absolute; 92 | top: -28px; 93 | left: 8px; 94 | z-index: 3; 95 | cursor: pointer; 96 | -webkit-animation: 1.2s ease-in-out 0s normal none running trambling-animation; 97 | -moz-animation: 1.2s ease-in-out 0s normal none running trambling-animation; 98 | -o-animation: 1.2s ease-in-out 0s normal none running trambling-animation; 99 | animation: 1.2s ease-in-out 0s normal none running trambling-animation; 100 | } 101 | .logoplace { 102 | width: 92px; 103 | pointer-events: none; 104 | } 105 | @keyframes trambling-animation { 106 | 0%, 50%, 100% { 107 | transform: rotate(0deg); 108 | -webkit-transform: rotate(0deg); 109 | -moz-transform: rotate(0deg); 110 | -o-transform: rotate(0deg); 111 | -ms-transform: rotate(0deg); 112 | } 113 | 10%, 30% { 114 | transform: rotate(-10deg); 115 | -webkit-transform: rotate(-10deg); 116 | -moz-transform: rotate(-10deg); 117 | -o-transform: rotate(-10deg); 118 | -ms-transform: rotate(-10deg); 119 | } 120 | 20%, 40% { 121 | transform: rotate(10deg); 122 | -webkit-transform: rotate(10deg); 123 | -moz-transform: rotate(10deg); 124 | -o-transform: rotate(10deg); 125 | -ms-transform: rotate(10deg); 126 | } 127 | } 128 | form { 129 | margin: 0; 130 | } 131 | .menubtn { 132 | float: left; 133 | height: 52px; 134 | display: inline; 135 | padding: 0px 10px; 136 | font-family: sans-serif; 137 | font-size: 12pt; 138 | font-weight: bold; 139 | cursor: pointer; 140 | } 141 | .menubtn:hover { 142 | background: rgb(0,0,0); /* Old browsers */ 143 | background: -moz-linear-gradient(top, rgba(0,0,0,1) 88%, rgba(110,119,116,1) 93%, rgba(255,255,255,1) 100%); /* FF3.6-15 */ 144 | background: -webkit-linear-gradient(top, rgba(0,0,0,1) 88%,rgba(110,119,116,1) 93%,rgba(255,255,255,1) 100%); /* Chrome10-25,Safari5.1-6 */ 145 | background: linear-gradient(to bottom, rgba(0,0,0,1) 88%,rgba(110,119,116,1) 93%,rgba(255,255,255,1) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ 146 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#000000', endColorstr='#ffffff',GradientType=0); /* IE6-9 */ 147 | } 148 | .mbsel, .mbsel:hover { 149 | background: rgb(0,112,0); /* Old browsers */ 150 | background: -moz-linear-gradient(top, rgba(0,112,0,1) 88%, rgba(160,255,160,1) 100%); /* FF3.6-15 */ 151 | background: -webkit-linear-gradient(top, rgba(0,112,0,1) 88%,rgba(160,255,160,1) 100%); /* Chrome10-25,Safari5.1-6 */ 152 | background: linear-gradient(to bottom, rgba(0,112,0,1) 88%,rgba(160,255,160,1) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ 153 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#007000', endColorstr='#a0ffa0',GradientType=0); /* IE6-9 */ 154 | } 155 | .multi { 156 | position: relative; 157 | float: left; 158 | height: 52px; 159 | } 160 | .submenu { 161 | display: none; 162 | position: absolute; 163 | top: 52px; 164 | left: 0px; 165 | padding-top: 1px; 166 | background: white; 167 | border-left: 1px solid black; 168 | border-right: 1px solid black; 169 | z-index: 2; 170 | } 171 | .submbtn { 172 | background: black; 173 | padding-left: 12px; 174 | padding-right: 8px; 175 | font-family: sans-serif; 176 | font-size: 10.2pt; 177 | font-weight: bold; 178 | cursor: pointer; 179 | width: 140px; 180 | min-height: 23px; 181 | border-bottom: 1px solid white; 182 | } 183 | .submbtn p { 184 | margin: 0px; 185 | padding-top: 3px; 186 | } 187 | .submbtn:hover { 188 | background: rgb(0,0,0); /* Old browsers */ 189 | background: -moz-linear-gradient(right, rgba(0,0,0,1) 94%, rgba(110,119,116,1) 96%, rgba(255,255,255,1) 100%); /* FF3.6-15 */ 190 | background: -webkit-linear-gradient(right, rgba(0,0,0,1) 94%,rgba(110,119,116,1) 96%,rgba(255,255,255,1) 100%); /* Chrome10-25,Safari5.1-6 */ 191 | background: linear-gradient(to left, rgba(0,0,0,1) 94%,rgba(110,119,116,1) 96%,rgba(255,255,255,1) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ 192 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#000000', endColorstr='#ffffff',GradientType=0); /* IE6-9 */ 193 | } 194 | .smsel, .smsel:hover { 195 | background: rgb(0,112,0); /* Old browsers */ 196 | background: -moz-linear-gradient(right, rgba(0,112,0,1) 94%, rgba(160,255,160,1) 100%); /* FF3.6-15 */ 197 | background: -webkit-linear-gradient(right, rgba(0,112,0,1) 94%,rgba(160,255,160,1) 100%); /* Chrome10-25,Safari5.1-6 */ 198 | background: linear-gradient(to left, rgba(0,112,0,1) 94%,rgba(160,255,160,1) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ 199 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#007000', endColorstr='#a0ffa0',GradientType=0); /* IE6-9 */ 200 | } 201 | .header { 202 | height: 74px; 203 | } 204 | .content { 205 | display: block; 206 | min-height: 71%; 207 | padding-left: 16px; 208 | padding-right: 16px; 209 | padding-top: 12px; 210 | padding-bottom: 12px; 211 | } 212 | .content.map { 213 | padding: 0px; 214 | } 215 | .content.find { 216 | padding-left: 8px; 217 | padding-right: 8px; 218 | } 219 | .content.ranges, 220 | .content.devmac, 221 | .content.stat, 222 | .content.graph, 223 | .content.user { 224 | padding-top: 0px; 225 | } 226 | .footer { 227 | background-color: black; 228 | color: white; 229 | text-align: center; 230 | font-family: sans-serif; 231 | font-size: 10pt; 232 | font-weight: bold; 233 | margin-bottom: 12px; 234 | } 235 | .todo { 236 | list-style-type: decimal; 237 | line-height: 120%; 238 | } 239 | .todo li tt { 240 | font-weight: bold; 241 | color: yellow; 242 | background: black; 243 | border: 2px solid black; 244 | border-radius: 7px; 245 | } 246 | 247 | TABLE.st1 { 248 | background: #fffff0; /* Цвет фона нечетных строк */ 249 | border: 1px solid #a52a2a; /* Рамка вокруг таблицы */ 250 | border-collapse: collapse; /* Убираем двойные линии между ячейками */ 251 | } 252 | TABLE.st1 TD, 253 | TABLE.st1 TH { 254 | padding: 3px; /* Поля вокруг содержимого ячейки */ 255 | } 256 | TABLE.st1 TH { 257 | white-space: nowrap; 258 | } 259 | TABLE.st1 TD { 260 | text-align: center; /* Выравнивание по центру */ 261 | border: 1px solid #a52a2a; /* Бордюр вокруг ячейки */ 262 | } 263 | TABLE.st1 TH { 264 | background: #a52a2a; /* Цвет фона */ 265 | color: white; /* Цвет текста */ 266 | } 267 | TABLE.st1 TR:nth-child(2n) { 268 | background: #fff8dc; /* Цвет фона четных строк */ 269 | } 270 | TABLE.st1 TD img, 271 | TABLE.st1 TH img { 272 | vertical-align: inherit; 273 | } 274 | TABLE.swp_st { 275 | background: #fffff0; /* Цвет фона нечетных строк */ 276 | border: 1px solid #a52a2a; /* Рамка вокруг таблицы */ 277 | border-collapse: collapse; /* Убираем двойные линии между ячейками */ 278 | } 279 | TABLE.swp_st TD, 280 | TABLE.swp_st TH { 281 | padding: 3px; /* Поля вокруг содержимого ячейки */ 282 | } 283 | TABLE.swp_st TD { 284 | text-align: center; /* Выравнивание по центру */ 285 | border: 1px solid #a52a2a; /* Бордюр вокруг ячейки */ 286 | } 287 | TABLE.swp_st TH { 288 | background: #a52a2a; /* Цвет фона */ 289 | color: white; /* Цвет текста */ 290 | } 291 | TABLE.st2 { 292 | } 293 | TABLE.st2 TD#stat_es { 294 | cursor: pointer; 295 | padding-left: 24px; 296 | border-left: solid 1px #939393; 297 | border-right: solid 1px #939393; 298 | border-top: solid 1px #939393; 299 | min-width: 128px; 300 | width: 128px; 301 | height: 36px; 302 | font-family: sans-serif; 303 | font-weight: bold; 304 | } 305 | TABLE.st2 TD#stat_es.first { 306 | border-top-left-radius: 8px; 307 | } 308 | TABLE.st2 TD#stat_es.last { 309 | border-bottom: solid 1px #939393; 310 | border-bottom-left-radius: 8px; 311 | } 312 | TABLE.st2 TD#stat_em { 313 | cursor: pointer; 314 | padding-left: 24px; 315 | border-right: solid 1px #939393; 316 | border-top: solid 1px #939393; 317 | min-width: 128px; 318 | width: 128px; 319 | height: 36px; 320 | font-family: sans-serif; 321 | font-weight: bold; 322 | } 323 | TABLE.st2 TD.stat_sel { 324 | background-color: black; 325 | color: white; 326 | } 327 | TABLE.st2 TD#stat_ft { 328 | border-right: solid 1px #939393; 329 | } 330 | TABLE.st2 TD#stat_cn { 331 | width: 100%; 332 | padding: 8px; 333 | vertical-align: top; 334 | border-top: solid 1px #939393; 335 | border-right: solid 1px #939393; 336 | border-bottom: solid 1px #939393; 337 | } 338 | .la { 339 | text-align: left; /* Выравнивание по левому краю */ 340 | } 341 | .swp { cursor: pointer } 342 | .wrapper { position: relative } 343 | .hint { 344 | position: absolute; left: 0px; top: 0px; z-index: 1; 345 | border-style: solid; 346 | border-width: thin; 347 | border-color: darkgray; 348 | background-color: white; 349 | } 350 | .hval { cursor: pointer } 351 | .hval:hover { background-color: #ffff90 } 352 | .graphbkg { 353 | display: inline-block; 354 | box-sizing: border-box; 355 | margin-left: 8px; 356 | margin-right: 8px; 357 | margin-top: 8px; 358 | margin-bottom: 16px; 359 | padding: 20px 15px 15px 15px; 360 | border: 1px solid #ddd; 361 | background: #fff; 362 | background: linear-gradient(#f6f6f6 0, #fff 50px); 363 | background: -o-linear-gradient(#f6f6f6 0, #fff 50px); 364 | background: -ms-linear-gradient(#f6f6f6 0, #fff 50px); 365 | background: -moz-linear-gradient(#f6f6f6 0, #fff 50px); 366 | background: -webkit-linear-gradient(#f6f6f6 0, #fff 50px); 367 | box-shadow: 0 3px 10px rgba(0,0,0,0.15); 368 | -o-box-shadow: 0 3px 10px rgba(0,0,0,0.1); 369 | -ms-box-shadow: 0 3px 10px rgba(0,0,0,0.1); 370 | -moz-box-shadow: 0 3px 10px rgba(0,0,0,0.1); 371 | -webkit-box-shadow: 0 3px 10px rgba(0,0,0,0.1); 372 | } 373 | .dgraph { 374 | width: 100%; 375 | height: 95%; 376 | font-size: 14px; 377 | line-height: 1.2em; 378 | } 379 | .header_cap { 380 | font-family: monospace; 381 | font-size: 18pt; 382 | } 383 | 384 | /* User Tabs */ 385 | 386 | .userTabContainer { 387 | min-width:260px; 388 | clear:both; 389 | } 390 | .userTabs{ 391 | vertical-align:middle; 392 | height:23px; 393 | position:relative; 394 | z-index:1; 395 | } 396 | .userTabs a, 397 | .userTabs a:link { 398 | text-decoration:none; 399 | color:#00709f; 400 | } 401 | .userTabs a:visited, 402 | .userTabs a:active { 403 | text-decoration:none; 404 | color:#03697a; 405 | } 406 | .userTabs a:hover { 407 | text-decoration:none; 408 | color:#3390b1; 409 | } 410 | .userTab { /* Неактивна */ 411 | font-family: 'Segoe UI Semibold','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif; 412 | font-size:13px; 413 | line-height:17px; 414 | font-style:normal!important; 415 | height:22px; 416 | float:left; 417 | width:auto; 418 | padding:0 15px 0 15px; 419 | vertical-align:baseline; 420 | color:#2a2a2a; 421 | background-color:transparent; 422 | } 423 | .userTab a, 424 | .userTab a:link, 425 | .userTab a:visited, 426 | .userTab a:active { 427 | cursor: pointer; 428 | font-weight:bold; 429 | text-decoration:none; 430 | position:relative; 431 | top:2px; 432 | } 433 | .userTabActive { /* Активна */ 434 | font-family: 'Segoe UI Semibold','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif; 435 | font-size:13px; 436 | line-height:17px; 437 | font-style:normal!important; 438 | height:22px; 439 | float:left; 440 | width:auto; 441 | padding:0 15px 0 15px; 442 | vertical-align:baseline; 443 | color:#707070; 444 | border-top:solid 1px #939393; 445 | border-right:solid 1px #939393; 446 | border-left:solid 1px #939393; 447 | border-bottom:solid 1px #fff; 448 | background-color:transparent; 449 | border-top-left-radius:4px; 450 | border-top-right-radius:4px; 451 | } 452 | .userTabActive a, 453 | .userTabActive a:link, 454 | .userTabActive a:visited, 455 | .userTabActive a:active { 456 | font-weight:bold; 457 | text-decoration:none; 458 | position:relative; 459 | top:2px; 460 | } 461 | .userCodeContainer { 462 | border-left:solid 1px #939393; 463 | border-bottom:solid 1px #939393; 464 | border-right:solid 1px #939393; 465 | border-top:solid 1px #939393; 466 | clear:both; 467 | margin-bottom:12px; 468 | position:relative; 469 | top:-1px; 470 | } 471 | .userCode { 472 | font-family: 'Segoe UI Semibold','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif; 473 | font-size:14px; 474 | width:auto; 475 | margin:0; 476 | padding-right:21px; 477 | padding-left:21px; 478 | padding-top:10px; 479 | padding-bottom:10px; 480 | } 481 | .userCode div { 482 | padding:0; 483 | margin:0; 484 | } 485 | .userCode pre { 486 | padding:5px; 487 | margin:0; 488 | font-family:Consolas,Courier,monospace!important; 489 | font-style:normal; 490 | font-weight:normal; 491 | overflow:auto; 492 | word-wrap:normal; 493 | } 494 | .userCode table { 495 | font-size: inherit; 496 | } 497 | .userCode a { 498 | color:#00709f; 499 | font-weight:bold; 500 | text-decoration:none; 501 | } 502 | .userCode * table.userMgmt * input[type=text] { 503 | width: 100%; 504 | } 505 | .fQuestion { 506 | background: lightgrey; 507 | padding: 12 8 12 8; 508 | width: 100%; 509 | border-left: 2px dotted #808080; 510 | } 511 | .fAnswer { 512 | } 513 | .perc { 514 | height: 16px; 515 | border-width: 1px; 516 | border-style: inset; 517 | background-color: #C0C0C0; 518 | display: inline-flex; 519 | position: relative; 520 | padding: 1px; 521 | top: 1px; 522 | } 523 | .perc-data { 524 | width: 100%; 525 | height: 100%; 526 | background-color: #5566CC; 527 | display: inherit; 528 | position: relative; 529 | } 530 | p.failure { 531 | background: url(../img/warning.png) no-repeat left; 532 | background-size: 32px 32px; 533 | padding-left: 40px; 534 | margin: 16 14 6 14; 535 | } 536 | p.failure b { 537 | width: 100%; 538 | display: block; 539 | border-bottom: 1px solid black; 540 | margin-bottom: 4px; 541 | } 542 | -------------------------------------------------------------------------------- /devmac.html: -------------------------------------------------------------------------------- 1 | %l10n_title_devmac% 2 | 3 | 4 | 59 | 60 | 61 | 62 |

%l10n_msg_devmac%

63 |
64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 |
%l10n_str_bssid% (%l10n_bssid_format%)
72 |
73 |
74 | 75 | 76 | 77 |
78 | -------------------------------------------------------------------------------- /devmac.php: -------------------------------------------------------------------------------- 1 | fetch_row(); 64 | $res->close(); 65 | if ((int)$row[0] >= 20000) 66 | break; 67 | } 68 | } 69 | if (!$result['result']) 70 | break; 71 | $x |= $x << 1; 72 | } 73 | if ($result['result']) 74 | { 75 | $res = QuerySql("CREATE TEMPORARY TABLE tmp_device_names LIKE tmp_dev_names"); 76 | $result['result'] = $res !== false; 77 | } 78 | $mac = base_convert($mac, 10, 16); 79 | if ($result['result']) 80 | { 81 | $res = QuerySql( 82 | "INSERT tmp_device_names 83 | SELECT name, BSSID 84 | FROM tmp_dev_names 85 | ORDER BY ABS(BSSID - 0x$mac) 86 | "); 87 | $result['result'] = $res !== false; 88 | } 89 | if ($result['result']) 90 | { 91 | $res = QuerySql( 92 | "SELECT name, COUNT(name) cnt, ABS(BSSID - 0x$mac) diff 93 | FROM tmp_device_names 94 | GROUP BY name HAVING(cnt > 1) 95 | ORDER BY ABS(BSSID - 0x$mac) 96 | LIMIT 10 97 | "); 98 | $result['result'] = $res !== false; 99 | } 100 | if ($result['result']) 101 | { 102 | $devs = array(); 103 | while ($row = $res->fetch_assoc()) 104 | { 105 | $devs[] = $row; 106 | } 107 | $res->close(); 108 | } 109 | if (!$result['result']) 110 | { 111 | $result['error'] = 'database'; 112 | } 113 | else 114 | { 115 | $result['scores'] = array(); 116 | foreach($devs as $dev) 117 | { 118 | $entry = array(); 119 | $entry['name'] = $dev['name']; 120 | $entry['score'] = 1 - pow((int)$dev['diff'] / 0xFFFFFF, 1 / 8); 121 | $entry['count'] = (int)$dev['cnt']; 122 | $result['scores'][] = $entry; 123 | } 124 | } 125 | QuerySql("DROP TABLE IF EXISTS tmp_dev_names, tmp_device_names"); 126 | return $result; 127 | } 128 | -------------------------------------------------------------------------------- /faq.html: -------------------------------------------------------------------------------- 1 | 3WiFi: F.A.Q 2 | 3 | 4 | 5 | 6 | 7 |
8 |

F.A.Q

9 | 10 |

Откуда в базе берутся точки?

11 | 12 |

13 | Другие участники проекта загружают результаты сканирования программы Router Scan. Подробнее о программе можно узнать на официальном сайте (ссылка на главной). 14 |

15 | 16 |

Моя точка есть в базе, как это произошло и как удалить её из базы?

17 | 18 |

19 |

Ваш роутер подвержен одной из известных уязвимостей. Обновите прошивку роутера и смените пароль Wi-Fi. Также рекомендуется поменять пароль доступа к настройкам роутера.

20 |

Удалить точку из базы нельзя. Сразу же после попадания в базу пароль считается скомпрометированным, поэтому придётся поменять его везде, где он использовался.

21 |

22 | 23 |

Как добавить точки с паролями в базу из других программ/баз?

24 | 25 |

26 | В базу заносится множество полей, например IP-адрес, DNS серверы, тип шифрования, и другие параметры. Запустите последнюю версию Router Scan и сделайте экспорт в файл TXT или CSV, приведите Ваши данные в соответствующий формат. Затем откройте изменённый файл в Router Scan, проверьте корректность полей, и загрузите данные через загрузчик 3WiFi. Также Вы можете использовать Excel, но делайте это крайне осторожно, т.к. он любит удалять некоторые данные, например в полях PIN часто удаляет лидирующие нули, а длинные цифры преобразует к экспоненциальному виду 3,8+E8. 27 |

28 | 29 |

Я вижу карту и точки, но у них не отображаются пароли!

30 | 31 |

32 | Необходимо авторизоваться на сайте - кнопка Вход в правом верхнем углу. 33 |

34 | 35 |

Карта точек доступа не работает, но сам сайт работает, что не так?

36 | 37 |

38 | Возможно ваш провайдер интернета блокирует Яндекс.Карты, попробуйте зайти под прокси или VPN. 39 |

40 | 41 |

Как зарегистрироваться? Как получить код приглашения?

42 | 43 |

44 |

Код приглашения можно приобрести, написав в форму обратной связи, или в Telegram чат Router Scan (см. главную страницу). После регистрации по коду приглашения ваш аккаунт получает уровень доступа "Пользователь", смотрите список уровней доступа ниже.

45 |

Вы также можете обойтись без кода приглашения, для этого необходимо вступить в сообщество Router Scan — тогда вы сможете воспользоваться гостевой учётной записью, если она не заблокирована.

46 |

47 | 48 |

Как долго я смогу пользоваться своим личным аккаунтом?

49 | 50 |

51 | Аккаунты на 3WiFi не имеют определённого срока действия, сможете пользоваться им сколько угодно, до тех пор, пока не нарушаете правила использования сайта. 52 |

53 | 54 |

Как определяются координаты точек на карте?

55 | 56 |

57 | Все координаты точек на карте определяются по BSSID с помощью провайдеров геолокации. Подробнее здесь: https://forum.antichat.ru/posts/3911845 58 |

59 | 60 |

Как указать/изменить координаты точки на карте?

61 | 62 |

63 | Сайт не предоставляет возможности изменить координаты. Однако Вы можете попросить осуществить повторный запрос к провайдерам геолокации для обновления координат - для этого свяжитесь с администрацией. 64 |

65 | 66 |

Как скачать базу себе?

67 | 68 |

69 | Никак! Попытки слить базу приведут к нарушению правил использования сайта, бану Вашего аккаунта, и бану всех приглашенных Вами и далее по цепочке. Никакие заслуги не снимут бан. 70 |

71 | 72 |

Как помочь проекту?

73 | 74 |

75 |

1. Программирование
76 | Исходники проекта есть на гитхабе, мы будем благодарны любой Вашей помощи: исправление существующих проблем, улучшение быстродействия кода, добавление нового функционала, перевод на другие языки, дизайн, отлавливание багов и т.д.

77 |

2. Добавление новых точек
78 | База растет только благодаря Вам! Сайт сам никого просканировать не может. Спасибо активным заливалам, без Вас этот проект бы не смог стать миллионником!

79 |

3. Денежная помощь
80 | У сайта нет кошельков, но Вы можете помочь разработчику программы Router Scan - см. соответствующий раздел на сайте stascorp.com.

81 |

82 | 83 |

Кто админы, как связаться?

84 | 85 |

86 | На главной странице есть ссылка на форму обратной связи, а также на Telegram чат Router Scan. 87 |

88 | 89 |

Какие уровни доступа бывают у участников проекта?

90 | 91 |

92 | Неавторизованный:
93 | Просмотр карты без паролей.
94 | Добавление точек в базу.
95 | Просмотр статистики и состояния сайта.
96 |
97 | 98 | Гостевой аккаунт:
99 | Просмотр карты с паролями.
100 | Поиск в стандартном режиме.
101 | Использование инструментов.
102 | Не может менять никнейм и пароль.
103 | Имеет один постоянный API ключ для поиска точек доступа.
104 | Имеет ограничение на поиск и получение точек из базы через API: не более одного запроса в 10 секунд.
105 | Сессия входа закрывается автоматически после 1 часа бездействия.
106 |
107 | 108 | Пользователь:
109 | Наследует права от гостя, а также:
110 | Загруженные точки привязываются к аккаунту.
111 | Может сменить никнейм и пароль.
112 | Может получить свой API ключ, а также ключ для пополнения базы из Router Scan.
113 | Не имеет ограничений по времени и количеству запросов.
114 | Возможность привязки поиска и статистики к выбранной локации / региону на карте.
115 | Управление разделом "Избранное".
116 | Управление приглашёнными пользователями.
117 | Личная статистика.
118 | Общее количество приглашений: 3 (если приглашён разработчиком или админом).
119 | Сессия входа закрывается автоматически после 24 часов бездействия.
120 |
121 | 122 | Разработчик:
123 | Наследует права от обычного пользователя, а также:
124 | Поиск в продвинутом режиме.
125 | Общее количество приглашений: 10 (если приглашён админом).
126 |
127 | 128 | Администратор:
129 | Наследует права от разработчика, а также:
130 | Может выдать бесконечное число приглашений.
131 | Имеет доступ к административным функциям.
132 |

133 | 134 |

Как стать разработчиком 3WiFi и получить соответствующий уровень доступа?

135 | 136 |

137 | Данный уровень доступа назначается только тем участникам сообщества, которые длительное время участвовали в разработке сервиса 3WiFi, и своими достижениями заслужили доверие и уважение в сообществе. 138 |

139 | 140 |

Как стать администратором 3WiFi?

141 | 142 |

143 | Развернуть из исходников локальную копию сервиса 3WiFi у себя на ПК или сервере, ссылка на репозиторий GitHub есть на главной странице. Стандартные данные входа для администратора - admin / admin. 144 |

145 |
146 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/favicon.ico -------------------------------------------------------------------------------- /geoext.php: -------------------------------------------------------------------------------- 1 | = 56.864 && $lat <= 56.865) && ($lon >= 60.610 && $lon <= 60.612)) 38 | { 39 | geoDbg("[-] $prov / $bssid : Ekaterinburg fake spot rejected\r\n"); 40 | return false; 41 | } 42 | return true; 43 | } 44 | function GetGeolocationServices() 45 | { 46 | return array( 47 | 'Yandex', 48 | //'YandexLocator', 49 | 'Microsoft', 50 | //'AlterGeo', 51 | //'Mylnikov', 52 | 'MylnikovOpen', 53 | //'Multigeo', 54 | ); 55 | } 56 | function GeoLocateAP($bssid, $svcs = null) 57 | { 58 | geoDbg("start locate $bssid"); 59 | $coords = ''; 60 | if (!is_array($svcs)) 61 | $svcs = GetGeolocationServices(); 62 | foreach ($svcs as $svc) 63 | { 64 | $func = 'GetFrom' . $svc; 65 | $coords = $func($bssid); 66 | if ($coords != '') 67 | break; 68 | } 69 | return $coords; 70 | } 71 | function GetFromYandex($bssid) 72 | { 73 | geoDbg("yandex: $bssid"); 74 | $tries = 5; 75 | $bssid = str_replace(":","",$bssid); 76 | $bssid = str_replace("-","",$bssid); 77 | while (!($data = cURL_Get("http://mobile.maps.yandex.net/cellid_location/?clid=1866854&lac=-1&cellid=-1&operatorid=null&countrycode=null&signalstrength=-1&wifinetworks=$bssid:0&app")) && ($tries > 0)) 78 | { 79 | $tries--; 80 | sleep(3); 81 | } 82 | 83 | $result = ''; 84 | if (!$data) return $result; 85 | geoDebug('yandex', $bssid, $data); 86 | $latitude = getStringBetween($data, ' latitude="', '"'); 87 | $longitude = getStringBetween($data, ' longitude="', '"'); 88 | if ($latitude != '' && $longitude != '') 89 | { 90 | if (handleGeoErrors('yandex', $bssid, (float)$latitude, (float)$longitude)) 91 | { 92 | $result = $latitude.';'.$longitude.';yandex'; 93 | } 94 | } 95 | return $result; 96 | } 97 | function GetFromYandexLocator($bssid) 98 | { 99 | geoDbg("yandex_locator: $bssid"); 100 | $url = 'http://api.lbs.yandex.net/geolocation'; 101 | $apiKey = YLOCATOR_APIKEY; 102 | if (empty($apiKey)) 103 | { 104 | return ''; 105 | } 106 | $xmlRequest = ' 107 | 108 | 109 | 1.0 110 | '.$apiKey.' 111 | 112 | 113 | 114 | '.$bssid.' 115 | 116 | 117 | '; 118 | $curl = curl_init($url); 119 | curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: text/xml")); 120 | curl_setopt($curl, CURLOPT_POST, true); 121 | curl_setopt($curl, CURLOPT_POSTFIELDS, "xml=" . urlencode($xmlRequest)); 122 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 123 | $data = curl_exec($curl); 124 | 125 | if (curl_errno($curl)) 126 | { 127 | return ''; 128 | } 129 | curl_close($curl); 130 | 131 | $result = ''; 132 | geoDebug('yandex_locator', $bssid, $data); 133 | $xml = simplexml_load_string($data); 134 | 135 | if ($xml->position->type == 'wifi') 136 | { 137 | $latitude = $xml->position->latitude; 138 | $longitude = $xml->position->longitude; 139 | if (handleGeoErrors('yandex_locator', $bssid, $latitude, $longitude)) 140 | { 141 | $result = $latitude.';'.$longitude.';yandex_locator'; 142 | } 143 | } 144 | return $result; 145 | } 146 | function GetFromAlterGeo($bssid) 147 | { 148 | geoDbg("altergeo: $bssid"); 149 | $tries = 3; 150 | $bssid = strtolower(str_replace(":","-",$bssid)); 151 | while (!($data = cURL_Get("http://api.platform.altergeo.ru/loc/json?browser=firefox&sensor=false&wifi=mac:$bssid%7Css:0")) && ($tries > 0)) 152 | { 153 | $tries--; 154 | sleep(5); 155 | } 156 | 157 | $result = ''; 158 | if (!$data) return $result; 159 | geoDebug('altergeo', $bssid, $data); 160 | $json = json_decode($data); 161 | if (!$json) return $result; 162 | if ($json->status == 'OK') 163 | { 164 | if ($json->accuracy < 1000 && handleGeoErrors('altergeo', $bssid, $json->location->lat, $json->location->lng)) 165 | { 166 | $latitude = $json->location->lat; 167 | $longitude = $json->location->lng; 168 | $result = $latitude.';'.$longitude.';altergeo'; 169 | } 170 | } 171 | return $result; 172 | } 173 | function GetFromMicrosoft($bssid) 174 | { 175 | geoDbg("microsoft: $bssid"); 176 | $headers = array( 177 | 'Accept: */*', 178 | 'Accept-Language: en-us', 179 | 'Content-Type: text/xml', 180 | 'Accept-Encoding: gzip, deflate', 181 | 'User-Agent: PHP/'.phpversion().' 3WiFi/2.0', 182 | 'Cache-Control: no-cache', 183 | ); 184 | $tries = 2; 185 | $bssid = strtolower(str_replace("-",":",$bssid)); 186 | 187 | $data = null; 188 | while (!$data && ($tries > 0)) 189 | { 190 | $time = date('Y-m-d\TH:i:s.uP'); 191 | $xmlRequest = ''.$time.'e1e71f6b-2149-45f3-a298-a20682ab501721BF9AD6-CFD3-46B3-B041-EE90BD34FDBC'; 192 | $ch = curl_init(); 193 | curl_setopt($ch, CURLOPT_URL, 'https://inference.location.live.net/inferenceservice/v21/Pox/GetLocationUsingFingerprint'); 194 | curl_setopt($ch, CURLOPT_POST, 1); 195 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); 196 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 197 | curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlRequest); 198 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 199 | curl_setopt($ch, CURLOPT_VERBOSE, 0); 200 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 201 | $data = ( function_exists('gzdecode') ? gzdecode(curl_exec($ch)) : my_gzdecode(curl_exec($ch)) ); 202 | curl_close($ch); 203 | 204 | $tries--; 205 | sleep(2); 206 | } 207 | 208 | $result = ''; 209 | if (!$data) return $result; 210 | geoDebug('microsoft', $bssid, $data); 211 | $xml = simplexml_load_string($data); 212 | if (!$xml) return $result; 213 | if ($xml->GetLocationUsingFingerprintResult->ResponseStatus == 'Success' && 214 | $xml->GetLocationUsingFingerprintResult->LocationResult->ResolverStatus->attributes()->Status == 'Success' && 215 | $xml->GetLocationUsingFingerprintResult->LocationResult->ResolverStatus->attributes()->Source == 'Internal' && 216 | $xml->GetLocationUsingFingerprintResult->LocationResult->RadialUncertainty < 500 217 | ) 218 | { 219 | $geo = $xml->GetLocationUsingFingerprintResult->LocationResult->ResolvedPosition->attributes(); 220 | $result = $geo->Latitude.';'.$geo->Longitude.';microsoft'; 221 | if (!handleGeoErrors('microsoft', $bssid, $geo->Latitude, $geo->Longitude)) 222 | { 223 | $result = ''; 224 | } 225 | } 226 | return $result; 227 | } 228 | function GetFromMylnikov($bssid) 229 | { 230 | geoDbg("mylnikov: $bssid"); 231 | $tries = 5; 232 | while (!($data = cURL_Get("https://api.mylnikov.org/wifi/main.py/get?bssid=$bssid", ''/* 127.0.0.1:3128 */)) && ($tries > 0)) 233 | { 234 | $tries--; 235 | sleep(5); 236 | } 237 | 238 | geoDebug('mylnikov', $bssid, $data); 239 | $result = ''; 240 | if (!$data) return $result; 241 | $json = json_decode($data); 242 | if (!$json) return $result; 243 | if ($json->result == 200 && handleGeoErrors('mylnikov', $bssid, $json->data->lat, $json->data->lon)) 244 | { 245 | $latitude = $json->data->lat; 246 | $longitude = $json->data->lon; 247 | $result = $latitude.';'.$longitude.';mylnikov'; 248 | } 249 | return $result; 250 | } 251 | function GetFromMylnikovOpen($bssid) 252 | { 253 | geoDbg("mylnikov_open: $bssid"); 254 | $tries = 3; 255 | while (!($data = cURL_Get("http://api.mylnikov.org/geolocation/wifi?v=1.1&data=open&bssid=$bssid")) && ($tries > 0)) 256 | { 257 | $tries--; 258 | sleep(2); 259 | } 260 | 261 | $result = ''; 262 | if (!$data) return $result; 263 | $json = json_decode($data); 264 | if (!$json) return $result; 265 | geoDebug('mylnikov_open', $bssid, $data); 266 | if ($json->result == 200 && handleGeoErrors('mylnikov_open', $bssid, $json->data->lat, $json->data->lon)) 267 | { 268 | $latitude = $json->data->lat; 269 | $longitude = $json->data->lon; 270 | $result = $latitude.';'.$longitude.';mylnikov_open'; 271 | } 272 | return $result; 273 | } 274 | function GetFromMultigeo($bssid) 275 | { 276 | geoDbg("multigeo: $bssid"); 277 | $tries = 3; 278 | while (!($data = cURL_Get("http://geomac.local/locate.php?mac=$bssid")) && ($tries > 0)) 279 | { 280 | $tries--; 281 | sleep(2); 282 | } 283 | 284 | $result = ''; 285 | if (strpos($data, 'Results for ') === false) return $result; 286 | geoDebug('multigeo', $bssid, $data); 287 | $svc = 'apple'; 288 | $line = getStringBetween($data, 'Apple | ', "\n"); 289 | if (empty($line)) 290 | { 291 | $svc = 'google'; 292 | $line = getStringBetween($data, 'Google | ', "\n"); 293 | } 294 | if (empty($line)) 295 | return $result; 296 | $line = explode(', ', $line); 297 | $latitude = $line[0]; 298 | $longitude = $line[1]; 299 | if (handleGeoErrors('multigeo', $bssid, (float)$latitude, (float)$longitude)) 300 | { 301 | $result = $latitude.';'.$longitude.';'.$svc; 302 | } 303 | return $result; 304 | } 305 | function cURL_Get($url, $proxy = '', $proxytype = -1, $proxyauth = '') 306 | { 307 | geoDbg("Fetching: $url"); 308 | $ch = curl_init(); 309 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 310 | curl_setopt($ch, CURLOPT_ENCODING, 'utf-8'); 311 | curl_setopt($ch, CURLOPT_TIMEOUT, 3); 312 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); 313 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 314 | curl_setopt($ch, CURLOPT_FAILONERROR, 1); 315 | curl_setopt($ch, CURLOPT_USERAGENT, 'PHP/'.phpversion().' 3WiFi/2.0'); 316 | if ($proxy != '') 317 | { 318 | curl_setopt($ch, CURLOPT_PROXYTYPE, $proxytype); 319 | curl_setopt($ch, CURLOPT_PROXY, $proxy); 320 | curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyauth); 321 | } 322 | curl_setopt($ch, CURLOPT_URL, $url); 323 | $data = curl_exec($ch); 324 | if (strpos($url, 'mobile.maps.yandex.net') !== false 325 | && curl_getinfo($ch, CURLINFO_HTTP_CODE) == 404) 326 | { 327 | // workaround for Yandex 328 | $data = 'Not found'; 329 | } 330 | if ($data) 331 | geoDbg("Success: $url"); 332 | else 333 | geoDbg("Error: $url\r\n" . curl_getinfo($ch, CURLINFO_HTTP_CODE).' / '.curl_errno($ch).' ('.curl_error($ch).')'); 334 | curl_close($ch); 335 | return $data; 336 | } 337 | -------------------------------------------------------------------------------- /graph.html: -------------------------------------------------------------------------------- 1 | %l10n_title_graph% 2 | 3 | 4 | 5 | 6 | 7 | 156 | 180 | 181 | 182 | 183 |

%l10n_msg_graph%

184 | 185 | 186 | 192 | 198 | 199 |
187 |
188 |
189 |
190 |
191 |
193 |
194 |
195 |
 
196 |
197 |
200 |
201 | -------------------------------------------------------------------------------- /home.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 69 | 70 |
12 | 13 |
14 |

%l10n_home_project%

15 |

%l10n_home_desc%

16 | 17 |

18 | 19 | 20 | 21 | 22 | Watch 23 | 24 |

25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
36 |
37 | 38 |
39 |
40 |

%l10n_home_changelog%

41 | %news% 42 |
43 |
44 | 45 |
46 | 47 |
48 |

%l10n_home_todolist%

49 |
    50 |
  • #ФИЧА #Поиск По дате / за несколько суток (только для участников)
  • 51 |
  • #ФИЧА #Загрузка Показывать BSSIDы точек, найденных на карте
  • 52 |
53 |
54 | 55 |
56 |

Памятка пользователя

57 |

• Заполнить по вкусу

58 |
59 | 60 |
61 |

%l10n_tbl_links%

62 | 66 |
67 | 68 |
71 | -------------------------------------------------------------------------------- /img/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/add.png -------------------------------------------------------------------------------- /img/find.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/find.png -------------------------------------------------------------------------------- /img/icon-fav-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/icon-fav-off.png -------------------------------------------------------------------------------- /img/icon-fav-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/icon-fav-on.png -------------------------------------------------------------------------------- /img/icon-hidden.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/icon-hidden.png -------------------------------------------------------------------------------- /img/icon-ip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/icon-ip.png -------------------------------------------------------------------------------- /img/icon-location.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/icon-location.png -------------------------------------------------------------------------------- /img/icon-map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/icon-map.png -------------------------------------------------------------------------------- /img/icon-nowifi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/icon-nowifi.png -------------------------------------------------------------------------------- /img/icon-warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/icon-warning.png -------------------------------------------------------------------------------- /img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/loading.gif -------------------------------------------------------------------------------- /img/loadsm.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/loadsm.gif -------------------------------------------------------------------------------- /img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/logo.png -------------------------------------------------------------------------------- /img/map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/map.png -------------------------------------------------------------------------------- /img/no.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/no.png -------------------------------------------------------------------------------- /img/ok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/ok.png -------------------------------------------------------------------------------- /img/rickroll.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/rickroll.gif -------------------------------------------------------------------------------- /img/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/search.png -------------------------------------------------------------------------------- /img/stat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/stat.png -------------------------------------------------------------------------------- /img/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarymaster/3WiFi/dff2cee47042bd0731a77b0cd9bef155bf7cbef4/img/warning.png -------------------------------------------------------------------------------- /import.free.php: -------------------------------------------------------------------------------- 1 | query($sql); 18 | if ($res->num_rows == 0) exit(); 19 | 20 | $sql_wifi = 'INSERT INTO '.BASE_TABLE.' (`time`,`cmtid`,`IP`,`Port`,`Authorization`,`name`,`RadioOff`,`Hidden`,`NoBSSID`,`BSSID`,`ESSID`,`Security`,`WiFiKey`,`WPSPIN`,`LANIP`,`LANMask`,`WANIP`,`WANMask`,`WANGateway`,`DNS1`,`DNS2`,`DNS3`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE `cmtid`=?,`IP`=?,`Port`=?,`Authorization`=?,`name`=?,`RadioOff`=?,`Hidden`=?,`NoBSSID`=?,`BSSID`=?,`ESSID`=?,`Security`=?,`WiFiKey`=?,`WPSPIN`=?,`LANIP`=?,`LANMask`=?,`WANIP`=?,`WANMask`=?,`WANGateway`=?,`DNS1`=?,`DNS2`=?,`DNS3`=?;'; 21 | $wifi = $db->prepare($sql_wifi); 22 | 23 | $sql_geo = 'INSERT INTO '.GEO_TABLE.' (`BSSID`,`latitude`,`longitude`) VALUES (?,?,?) ON DUPLICATE KEY UPDATE `BSSID`=?,`latitude`=?,`longitude`=?;'; 24 | $geo = $db->prepare($sql_geo); 25 | 26 | while($row = $res->fetch_assoc()) 27 | { 28 | $row['comment'] = trim(preg_replace('/\s+/', ' ', $row['comment'])); 29 | if ($row['comment'] == 'none') $row['comment'] = ''; 30 | $cmtid = getCommentId($row['comment'], true); 31 | $row['IP'] = _ip2long($row['IP']); 32 | if ($row['IP'] == 0 || $row['IP'] == -1) $row['IP'] = null; 33 | $row['Port'] = (($row['Port'] == '') ? null : (int)$row['Port']); 34 | if ($row['Authorization'] == '') $row['Authorization'] = null; 35 | $row['RadioOff'] = (($row['RadioOff'] == '[X]') ? 1 : 0); 36 | $row['Hidden'] = (($row['Hidden'] == '[X]') ? 1 : 0); 37 | 38 | if (ismac($row['BSSID'])) 39 | { 40 | $NoBSSID = 0; 41 | $row['BSSID'] = mac2dec($row['BSSID']); 42 | } else { 43 | $NoBSSID = 1; 44 | if ($row['BSSID'] == '') 45 | $NoBSSID = 2; 46 | if ($row['BSSID'] == '') 47 | $NoBSSID = 3; 48 | if ($row['BSSID'] == '') 49 | $NoBSSID = 4; 50 | $row['BSSID'] = 0; 51 | } 52 | $row['Security'] = str2sec($row['Security']); 53 | $row['WPSPIN'] = preg_replace('~\D+~', '', $row['WPSPIN']); 54 | $row['WPSPIN'] = (($row['WPSPIN'] == '') ? 1 : (int)$row['WPSPIN']); 55 | $row['LANIP'] = _ip2long($row['LANIP']); 56 | if ($row['LANIP'] == 0 || $row['LANIP'] == -1) $row['LANIP'] = null; 57 | $row['LANMask'] = _ip2long($row['LANMask']); 58 | if ($row['LANMask'] == 0) $row['LANMask'] = null; 59 | $row['WANIP'] = _ip2long($row['WANIP']); 60 | if ($row['WANIP'] == 0 || $row['WANIP'] == -1) $row['WANIP'] = null; 61 | $row['WANMask'] = _ip2long($row['WANMask']); 62 | if ($row['WANMask'] == 0) $row['WANMask'] = null; 63 | $row['WANGateway'] = _ip2long($row['WANGateway']); 64 | if ($row['WANGateway'] == 0 || $row['WANGateway'] == -1) $row['WANGateway'] = null; 65 | 66 | $DNS = explode(' ', $row['DNS']); 67 | for ($i = 0; $i < count($DNS); $i++) 68 | { 69 | $DNS[$i] = _ip2long($DNS[$i]); 70 | if ($DNS[$i] == 0 || $DNS[$i] == -1) $DNS[$i] = null; 71 | } 72 | 73 | $wifi->bind_param('siiissiiissisiiiiiiiiiiiissiiissisiiiiiiiii', 74 | // INSERT ^ 2nd part 75 | $row['time'],$cmtid,$row['IP'],$row['Port'],$row['Authorization'],$row['name'],$row['RadioOff'],$row['Hidden'],$NoBSSID,$row['BSSID'],$row['ESSID'],$row['Security'],$row['WiFiKey'],$row['WPSPIN'],$row['LANIP'],$row['LANMask'],$row['WANIP'],$row['WANMask'],$row['WANGateway'],$DNS[0],$DNS[1],$DNS[2], 76 | // UPDATE 77 | $cmtid,$row['IP'],$row['Port'],$row['Authorization'],$row['name'],$row['RadioOff'],$row['Hidden'],$NoBSSID,$row['BSSID'],$row['ESSID'],$row['Security'],$row['WiFiKey'],$row['WPSPIN'],$row['LANIP'],$row['LANMask'],$row['WANIP'],$row['WANMask'],$row['WANGateway'],$DNS[0],$DNS[1],$DNS[2]); 78 | $wifi->execute(); 79 | 80 | if ($NoBSSID == 0 && $row['latitude'] != 'none') 81 | { 82 | if ($row['latitude'] == 'not found') 83 | { 84 | $row['latitude'] = 0; 85 | $row['longitude'] = 0; 86 | } 87 | $geo->bind_param('sddsdd', 88 | // INSERT 89 | $row['BSSID'],$row['latitude'],$row['longitude'], 90 | // UPDATE 91 | $row['BSSID'],$row['latitude'],$row['longitude']); 92 | $geo->execute(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | %title% 4 | 5 | 6 | 7 | 10 | 11 | 405 | %head% 406 | 407 | 408 |
409 | %theme_head% 410 | 449 |
450 | 451 | %broadcast% 452 |
%content%
453 | 454 | 455 | 456 | 467 | 468 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | Login; 75 | $ViewNick = $UserManager->Nick; 76 | $ViewLevel = $UserManager->Level; 77 | $ViewInvites = $UserManager->invites; 78 | $ViewRAPI = $UserManager->ReadApiKey; 79 | $ViewWAPI = $UserManager->WriteApiKey; 80 | $ViewReg = $UserManager->RegDate; 81 | $ViewInviter = $UserManager->InviterNickName; 82 | $ViewUser = ''; 83 | 84 | if (!is_null($UserManager->vuID)) 85 | { 86 | $ViewUser = $ViewNick; 87 | $info = $UserManager->getUserInfo($UserManager->vuID); 88 | $ViewLogin = $info['login']; 89 | $ViewNick = $info['nick']; 90 | $ViewLevel = (int)$info['level']; 91 | $ViewInvites = (int)$info['invites']; 92 | $ViewRAPI = $info['rapikey']; 93 | $ViewWAPI = $info['wapikey']; 94 | $ViewReg = $info['regdate']; 95 | $ViewInviter = $UserManager->getUserNameById($info['puid']); 96 | } 97 | 98 | if (empty($ViewRAPI)) $ViewRAPI = $l10n['no_access']; 99 | if (empty($ViewWAPI)) $ViewWAPI = $l10n['no_access']; 100 | 101 | $content = str_replace('%login_str%', ($UserManager->isLogged() ? $l10n['menu_logout'] : $l10n['menu_login']), $content); 102 | $content = str_replace('%ban_reasons%', json_encode($ban_reasons), $content); 103 | $content = str_replace('%profile%', $profile, $content); 104 | $content = str_replace('%isUser%', (int)$UserManager->isLogged(), $content); 105 | $content = str_replace('%login%', htmlspecialchars($ViewLogin), $content); 106 | $content = str_replace('%nick%', htmlspecialchars($ViewNick), $content); 107 | $content = str_replace('%user_access_level%', $ViewLevel, $content); 108 | $content = str_replace('%user_invites%', $ViewInvites, $content); 109 | $content = str_replace('%view_user%', htmlspecialchars($ViewUser), $content); 110 | $content = str_replace('%rapikey%', $ViewRAPI, $content); 111 | $content = str_replace('%wapikey%', $ViewWAPI, $content); 112 | $content = str_replace('%regdate%', $ViewReg, $content); 113 | $content = str_replace('%refuser%', $ViewInviter, $content); 114 | $content = str_replace('%var_lat%', $lat, $content); 115 | $content = str_replace('%var_lon%', $lon, $content); 116 | $content = str_replace('%var_rad%', $rad, $content); 117 | $content = str_replace('%var_ymaps_apikey%', YMAPS_APIKEY, $content); 118 | $content = str_replace('%var_wait%', GUEST_WAIT, $content); 119 | 120 | foreach ($l10n as $key => $value) 121 | { 122 | $content = str_replace("%l10n_$key%", $value, $content); 123 | } 124 | } 125 | function getNews() 126 | { 127 | $project_news = json_decode(file_get_contents('project_news.json'), true); 128 | $service_news = json_decode(file_get_contents('service_news.json'), true); 129 | $news = array_merge_recursive($service_news, $project_news); 130 | krsort($news); 131 | $out = "
    \r\n"; 132 | foreach ($news as $date => $list) 133 | { 134 | $a = array_merge(array("$date"), $list); 135 | $out .= '
  • ' . implode("
    \r\n", $a) . "
  • \r\n"; 136 | } 137 | $out .= '
'; 138 | return $out; 139 | } 140 | 141 | if (isset($_GET['redir']) && $_GET['redir'] != '') 142 | { 143 | $page = validPage($_GET['redir']); 144 | if ($page != '') 145 | { 146 | Header('HTTP/1.0 303 See Other'); 147 | Header('Location: ' . $page); 148 | } 149 | exit(); 150 | } 151 | 152 | require_once 'user.class.php'; 153 | require_once 'utils.php'; 154 | 155 | $UserManager = new User(); 156 | $UserManager->load(); 157 | 158 | if ($UserManager->Level == -2) 159 | { 160 | $UserManager->out(); 161 | $UserManager->setUser(); 162 | } 163 | 164 | $incscript = file_get_contents('counter.txt'); 165 | 166 | $page = validPage(isset($_GET['page']) ? $_GET['page'] : 'home'); 167 | $form = validForm(isset($_GET['fetch']) ? $_GET['fetch'] : ''); 168 | if ($page == '') $page = '404'; 169 | 170 | // getGeoByIP($_SERVER['REMOTE_ADDR'], YLOCATOR_APIKEY) 171 | $lat = DEFAULT_LAT; 172 | $lon = DEFAULT_LON; 173 | $rad = DEFAULT_RAD; 174 | 175 | function setFloat($in, &$out) 176 | { 177 | if (isset($in)) 178 | { 179 | $in = str_replace(',', '.', $in); 180 | $out = (float)$in; 181 | } 182 | } 183 | 184 | $uselocation = array(); 185 | parse_str($_COOKIE['uselocation'], $uselocation); 186 | 187 | setFloat($uselocation['lat'], $lat); 188 | setFloat($uselocation['lon'], $lon); 189 | setFloat($uselocation['rad'], $rad); 190 | 191 | setFloat($_GET['lat'], $lat); 192 | setFloat($_GET['lon'], $lon); 193 | setFloat($_GET['rad'], $rad); 194 | 195 | include_once loadLanguage(); 196 | 197 | $broadcast = ''; 198 | if(TRY_USE_MEMORY_TABLES) 199 | { 200 | $DataBaseStatus = GetStatsValue(STATS_DATABASE_STATUS); 201 | if($DataBaseStatus == DATABASE_PREPARE) 202 | { 203 | $broadcast .= '

'.$l10n['warning'].' '.$l10n['db_prepare'].'

'; 204 | } 205 | } 206 | 207 | $ban_reasons = array(); 208 | $profile = 'isUser: %isUser%, Nickname: "%nick%", Level: %user_access_level%, invites: %user_invites%, viewUser: "%view_user%"'; 209 | 210 | foreach (explode('|', BAN_REASONS) as $reason) 211 | { 212 | $ban_reasons[$reason] = $l10n["ban_$reason"]; 213 | } 214 | 215 | $theme_base = 'themes'; 216 | $themes = scandir("$theme_base/"); 217 | $filter = array(); 218 | foreach ($themes as $theme_name) 219 | { 220 | $theme_name = preg_replace("/[^a-zA-Z0-9\-_]+/", "", $theme_name); 221 | if ( file_exists("$theme_base/$theme_name/theme.php") ) 222 | $filter[] = $theme_name; 223 | } 224 | $themes = $filter; 225 | 226 | $theme = $_COOKIE['theme']; 227 | $theme_data = array(); 228 | if ( isset($theme) && in_array($theme, $themes, true) ) 229 | { 230 | require_once "$theme_base/$theme/theme.php"; 231 | } 232 | else 233 | { 234 | // use default theme 235 | $theme_data['css'] = 'css/style.css?' . filemtime('css/style.css'); 236 | $theme_data['head'] = ''; 237 | $theme_data['ajax'] = 'img/loadsm.gif'; 238 | } 239 | $themes_str = '['.(count($themes) > 0 ? "'".implode("','", $themes)."'" : '').']'; 240 | 241 | if ($form != '') 242 | { 243 | $content = file_get_contents($form.'.html'); 244 | preparePage($content); 245 | echo $content; 246 | die(); 247 | } 248 | 249 | if (!file_exists($page.'.html')) $page = '404'; 250 | $hfile = file_get_contents($page.'.html'); 251 | 252 | $title = getStringBetween($hfile, '', ''); 253 | if ($title == '') $title = $l10n['title']; 254 | $head = getStringBetween($hfile, '', ''); 255 | $content = getStringBetween($hfile, '', ''); 256 | 257 | $content = str_replace('%content%', $content, file_get_contents('index.html')); 258 | $content = str_replace('%title%', $title, $content); 259 | $content = str_replace('%head%', $head, $content); 260 | $content = str_replace('%page%', $page, $content); 261 | if (strpos($content, '%news%') !== false) 262 | { 263 | $content = str_replace('%news%', getNews(), $content); 264 | } 265 | 266 | preparePage($content); 267 | 268 | echo str_replace('', $incscript.'', $content); 269 | -------------------------------------------------------------------------------- /js/FileSaver.min.js: -------------------------------------------------------------------------------- 1 | /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ 2 | var saveAs=saveAs||function(e){"use strict";if(typeof navigator!=="undefined"&&/MSIE [1-9]\./.test(navigator.userAgent)){return}var t=e.document,n=function(){return e.URL||e.webkitURL||e},r=t.createElementNS("http://www.w3.org/1999/xhtml","a"),i="download"in r,o=function(e){var t=new MouseEvent("click");e.dispatchEvent(t)},a=/Version\/[\d\.]+.*Safari/.test(navigator.userAgent),f=e.webkitRequestFileSystem,u=e.requestFileSystem||f||e.mozRequestFileSystem,s=function(t){(e.setImmediate||e.setTimeout)(function(){throw t},0)},c="application/octet-stream",d=0,l=500,w=function(t){var r=function(){if(typeof t==="string"){n().revokeObjectURL(t)}else{t.remove()}};if(e.chrome){r()}else{setTimeout(r,l)}},p=function(e,t,n){t=[].concat(t);var r=t.length;while(r--){var i=e["on"+t[r]];if(typeof i==="function"){try{i.call(e,n||e)}catch(o){s(o)}}}},v=function(e){if(/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)){return new Blob(["\ufeff",e],{type:e.type})}return e},y=function(t,s,l){if(!l){t=v(t)}var y=this,m=t.type,S=false,h,R,O=function(){p(y,"writestart progress write writeend".split(" "))},g=function(){if(R&&a&&typeof FileReader!=="undefined"){var r=new FileReader;r.onloadend=function(){var e=r.result;R.location.href="data:attachment/file"+e.slice(e.search(/[,;]/));y.readyState=y.DONE;O()};r.readAsDataURL(t);y.readyState=y.INIT;return}if(S||!h){h=n().createObjectURL(t)}if(R){R.location.href=h}else{var i=e.open(h,"_blank");if(i==undefined&&a){e.location.href=h}}y.readyState=y.DONE;O();w(h)},b=function(e){return function(){if(y.readyState!==y.DONE){return e.apply(this,arguments)}}},E={create:true,exclusive:false},N;y.readyState=y.INIT;if(!s){s="download"}if(i){h=n().createObjectURL(t);r.href=h;r.download=s;setTimeout(function(){o(r);O();w(h);y.readyState=y.DONE});return}if(e.chrome&&m&&m!==c){N=t.slice||t.webkitSlice;t=N.call(t,0,t.size,c);S=true}if(f&&s!=="download"){s+=".download"}if(m===c||f){R=e}if(!u){g();return}d+=t.size;u(e.TEMPORARY,d,b(function(e){e.root.getDirectory("saved",E,b(function(e){var n=function(){e.getFile(s,E,b(function(e){e.createWriter(b(function(n){n.onwriteend=function(t){R.location.href=e.toURL();y.readyState=y.DONE;p(y,"writeend",t);w(e)};n.onerror=function(){var e=n.error;if(e.code!==e.ABORT_ERR){g()}};"writestart progress write abort".split(" ").forEach(function(e){n["on"+e]=y["on"+e]});n.write(t);y.abort=function(){n.abort();y.readyState=y.DONE};y.readyState=y.WRITING}),g)}),g)};e.getFile(s,{create:false},b(function(e){e.remove();n()}),b(function(e){if(e.code===e.NOT_FOUND_ERR){n()}else{g()}}))}),g)}),g)},m=y.prototype,S=function(e,t,n){return new y(e,t,n)};if(typeof navigator!=="undefined"&&navigator.msSaveOrOpenBlob){return function(e,t,n){if(!n){e=v(e)}return navigator.msSaveOrOpenBlob(e,t||"download")}}m.abort=function(){var e=this;e.readyState=e.DONE;p(e,"abort")};m.readyState=m.INIT=0;m.WRITING=1;m.DONE=2;m.error=m.onwritestart=m.onprogress=m.onwrite=m.onabort=m.onerror=m.onwriteend=null;return S}(typeof self!=="undefined"&&self||typeof window!=="undefined"&&window||this.content);if(typeof module!=="undefined"&&module.exports){module.exports.saveAs=saveAs}else if(typeof define!=="undefined"&&define!==null&&define.amd!=null){define([],function(){return saveAs})} -------------------------------------------------------------------------------- /js/jquery.flot.categories.min.js: -------------------------------------------------------------------------------- 1 | /* Javascript plotting library for jQuery, version 0.8.3. 2 | 3 | Copyright (c) 2007-2014 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | */ 7 | (function($){var options={xaxis:{categories:null},yaxis:{categories:null}};function processRawData(plot,series,data,datapoints){var xCategories=series.xaxis.options.mode=="categories",yCategories=series.yaxis.options.mode=="categories";if(!(xCategories||yCategories))return;var format=datapoints.format;if(!format){var s=series;format=[];format.push({x:true,number:true,required:true});format.push({y:true,number:true,required:true});if(s.bars.show||s.lines.show&&s.lines.fill){var autoscale=!!(s.bars.show&&s.bars.zero||s.lines.show&&s.lines.zero);format.push({y:true,number:true,required:false,defaultValue:0,autoscale:autoscale});if(s.bars.horizontal){delete format[format.length-1].y;format[format.length-1].x=true}}datapoints.format=format}for(var m=0;mindex)index=categories[v];return index+1}function categoriesTickGenerator(axis){var res=[];for(var label in axis.categories){var v=axis.categories[label];if(v>=axis.min&&v<=axis.max)res.push([v,label])}res.sort(function(a,b){return a[0]-b[0]});return res}function setupCategoriesForAxis(series,axis,datapoints){if(series[axis].options.mode!="categories")return;if(!series[axis].categories){var c={},o=series[axis].options.categories||{};if($.isArray(o)){for(var i=0;i