├── README.md
├── china.css
├── china.html
├── china.js
├── data
├── china_cities.csv
├── china_cities.json
├── china_provinces.json
├── country-codes.csv
└── readme-world.json
├── flags.css
├── fonts.css
├── fonts
└── Norse-Mapcons.woff
├── images
├── DarkNoiseBackground.png
├── flags
│ └── flags16.png
├── loading.gif
├── norse-white.png
└── unknown-poly.png
├── index.html
├── ipviking.css
├── ipviking.js
├── nodejs
└── main.js
└── presentations.js
/README.md:
--------------------------------------------------------------------------------
1 | livemapdemo
2 | ===========
3 |
4 | 地图实时攻击演示
5 |
6 |
7 |
8 | 目前包含:
9 | * 世界地图
10 | 基本就是copy了ipviking的展示,我觉得他们做的已经非常满足我的需求了。
11 |
12 | * 中国地图
13 | 目前只是简单的进行了修改,能够显示中国地图,但是显示的数据不能对应到城市或者省份,以后有时间再改。
14 |
15 |
16 | 服务端运行:
17 | nodejs目录下,npm install mysql,nodejs-websocket,geoip-lite,underscore
18 | 自行填充实时数据。
19 |
20 | 网页文件直接访问index.html查看世界地图,china.html查看中国地图
21 |
--------------------------------------------------------------------------------
/china.css:
--------------------------------------------------------------------------------
1 | @import url(http://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800);
2 | @import url(http://fonts.googleapis.com/css?family=Oswald:400,300,700);
3 |
4 | body {
5 | overflow: hidden;
6 | margin: 0;
7 | color: white;
8 | background: url(images/DarkNoiseBackground.png);
9 | font-family: "Oswald", "Open Sans", sans-serif;
10 | }
11 |
12 | ol {
13 | list-style-type: none;
14 | margin-left: -2.0em;
15 | }
16 |
17 | td {
18 | font-family: "Open Sans", "Oswald", sans-serif;
19 | font-weight: 400;
20 | }
21 |
22 |
23 | th {
24 | font-weight: normal;
25 | }
26 |
27 | h1, h2, h3, h4 {
28 | font-family: "Oswald", "Open Sans", sans-serif;
29 | }
30 |
31 | #drawer {
32 | position: absolute;
33 | top: 48px;
34 | right: 6px;
35 | z-index: 100;
36 | height: 385px;
37 | width: 595px;
38 | }
39 |
40 | .blue-bg {
41 | background: rgb(0, 78, 176);
42 | background: transparent\9;
43 | background-color: rgb(0, 78, 176, 0.95);
44 | border-radius: 4px;
45 | border: 1px solid rgba(0, 78, 176);
46 | border: 1px solid rgba(0, 78, 176, 0.95);
47 | -webkit-background-clip: padding-box; /* for Safari */
48 | background-clip: padding-box; /* for IE9+, Firefox 4+, Opera, Chrome */
49 | }
50 |
51 | #drawer-content {
52 | height: 100%;
53 | float: right;
54 | overflow: hidden;
55 | }
56 |
57 | #drawer-inner a,
58 | #drawer-content.info-btn {
59 | text-decoration: underline;
60 | color: #fff;
61 | }
62 |
63 | #drawer-inner a:hover,
64 | #drawer-content .info-btn:hover {
65 | color: rgb(20, 180, 255);
66 | }
67 |
68 | #drawer-inner {
69 | padding: 0 1em;
70 | font-size: 11px;
71 | font-family: "Open Sans", "Oswald", sans-serif;
72 | font-weight: 300;
73 | line-height: 13px;
74 | }
75 |
76 | #drawer-content h1 {
77 | margin-top: 5px;
78 | font-size: 24px;
79 | font-family: "Open Sans", "Oswald", sans-serif;
80 | font-weight: 300;
81 | line-height: 30px;
82 | }
83 |
84 | #drawer-left {
85 | float: left;
86 | width: 60%;
87 | }
88 |
89 | .table-ref {
90 | font-family: "Oswald", "Open Sans";
91 | font-weight: bold;
92 | text-transform: uppercase;
93 | font-size: 0.9em;
94 | }
95 |
96 | /*
97 | This has awful performance...
98 | #drawer-content .footer {
99 | width: 480px;
100 | position: absolute;
101 | bottom: 0;
102 | }
103 | */
104 |
105 | nav {
106 | /* background-color: rgba(0, 140, 240, 0.95);*/
107 | background: linear-gradient(rgba(0, 138, 255, 0.5),
108 | rgba(0, 150, 255, 0.5)),
109 | rgba(0, 0, 0, 0.8);
110 | float: left;
111 | width: 40px;
112 | border-bottom-left-radius: 6px;
113 | }
114 |
115 | nav ul {
116 | list-style-type: none;
117 | margin: 0 0 0 -2.4em;
118 | }
119 |
120 | nav ul li {
121 | margin: 0.2em;
122 | font-size: 1.4em;
123 | text-align: center;
124 | }
125 |
126 | nav ul li a {
127 | display: block;
128 | }
129 |
130 | nav ul li a:visited, a:link {
131 | color: white;
132 | text-decoration: none;
133 | }
134 |
135 | nav ul li a:hover {
136 | color: white;
137 | border-top-color: white;
138 | text-decoration: underline;
139 | }
140 |
141 | #content {
142 | width: 100%;
143 | opacity: 0;
144 | }
145 |
146 | #display-label-container {
147 | width: 100%;
148 | text-align: center;
149 | position: absolute;
150 | z-index: 6;
151 | text-shadow: -1px -1px 0 #000,
152 | 1px -1px 0 #000,
153 | -1px 1px 0 #000,
154 | 1px 1px 0 #000;
155 | }
156 |
157 | #top-line {
158 | width: 100%;
159 | background-color: rgb(1, 73, 128);
160 | height: 5px;
161 | }
162 |
163 | #logo {
164 | position: absolute;
165 | left: 6px;
166 | top: 12px;
167 | z-index: 100;
168 | }
169 |
170 | #loading {
171 | position: absolute;
172 | right: 4em;
173 | bottom: 1em;
174 | }
175 |
176 | #info {
177 | position: absolute;
178 | right: 20em;
179 | top: 1em;
180 | }
181 |
182 | .overlay {
183 | position: absolute;
184 | top: 0;
185 | left: 0;
186 | right: 0;
187 | z-index: 4;
188 | }
189 |
190 | .icon {
191 | width: 1em;
192 | }
193 |
194 | .buffer {
195 | visibility: hidden;
196 | }
197 |
198 | .shadow {
199 | -moz-box-shadow: 0 0 5px 5px rgb(40, 50, 80);
200 | -webkit-box-shadow: 0 0 5px 5px rgb(40, 50, 80);
201 | box-shadow: 0 0 5px 5px rgb(40, 50, 80);
202 | }
203 |
204 | .box {
205 | position: absolute;
206 | z-index: 20;
207 | 1px -1px 0 #000,
208 | -1px 1px 0 #000,
209 | 1px 1px 0 #000;
210 | }
211 |
212 | .gray-bg {
213 | background: rgb(51,51,51);
214 | background: transparent\9;
215 | background: rgba(51,51,51,0.5);
216 | border-radius: 4px;
217 | border: 1px solid rgba(51, 51, 51);
218 | border: 1px solid rgba(51, 51, 51, 0.5);
219 | -webkit-background-clip: padding-box; /* for Safari */
220 | background-clip: padding-box; /* for IE9+, Firefox 4+, Opera, Chrome */
221 | }
222 |
223 | .black-solid {
224 | background-color: rgba(10, 20, 30, 0.8);
225 | border: thin solid rgb(0, 180, 240);
226 | border-bottom-right-radius: 6px;
227 | border-bottom-left-radius: 6px;
228 | -webkit-box-shadow: 0 0 3px 1px rgb(0, 120, 240);
229 | -moz-box-shadow: 0 0 3px 1px rgb(0, 120, 240);
230 | box-shadow: 0 0 3px 1px rgb(0, 120, 240);
231 | }
232 |
233 | .table-container {
234 | z-index: -2;
235 | }
236 |
237 | /*
238 | .data table th {
239 | color: rgb(45, 255, 254);
240 | }
241 | */
242 |
243 | .data {
244 | width: 180px;
245 | }
246 |
247 | .data table tr {
248 | line-height: 18px;
249 | text-align: left;
250 | }
251 |
252 | .data table td,
253 | .data table th {
254 | font-size: 12px;
255 | }
256 |
257 | .data table th {
258 | font-size: 13px;
259 | font-family: "Open Sans Bold", "Oswald", sans-serif;
260 | font-weight: 700;
261 | text-transform: uppercase;
262 | }
263 |
264 | .data table th [class^="icon-"], .data table th [class*=" icon-"] {
265 | font-size: 16px;
266 | }
267 |
268 | .data table td span.numeric {
269 | font-size: 10px;
270 | font-family: "Open Sans Light", "Oswald", sans-serif;
271 | font-weight: 300;
272 | }
273 |
274 | .data .flag {
275 | margin-right: 20px;
276 | height: 1.0em;
277 | }
278 |
279 | .data .numeric {
280 | margin-right: 10px;
281 | }
282 |
283 | .data .icon-number {
284 | margin-right: 8px;
285 | }
286 |
287 | .data colgroup .bar-col { width: 0; }
288 | .data colgroup .total-count { width: 2.6em; }
289 | .data colgroup .data-label-small { width: 1.6em; }
290 | .data colgroup .data-label { width: 10em; }
291 | .data colgroup .port-label { width: 2.8em; }
292 |
293 |
294 | .data tr.row:hover {
295 | background-color: #0c2b4a;
296 | }
297 |
298 | .data table .bar {
299 | position: absolute;
300 | height: 20px;
301 | margin-top: -10px;
302 | background-color: #0c2b4a;
303 | z-index: -1;
304 | border-radius: 3px;
305 | max-width: 98%;
306 | }
307 |
308 | .data table tr td:nth-child(2),
309 | .data table tr th:nth-child(2) {
310 | text-align: right;
311 | padding-right: 0.4em;
312 | }
313 |
314 | .port-circle {
315 | font-size: 1.8em;
316 | text-align: center;
317 | line-height: 0.5em;
318 | }
319 |
320 | .table-header {
321 | text-align: center;
322 | color: rgb(40, 255, 255);
323 | color: rgb(255, 255, 255);
324 | text-transform: uppercase;
325 | border-top-right-radius: 6px;
326 | border-top-left-radius: 6px;
327 | margin-bottom: 4px;
328 | }
329 |
330 | .table-header h1 {
331 | margin: 0.4em 0.8em;
332 | font-family: "Open Sans", "Oswald", sans-serif;
333 | font-weight: 400;
334 | font-size: 16px;
335 | text-align: left;
336 | }
337 |
338 | .top-left {
339 | top: 72px;
340 | left: 6px;
341 | }
342 |
343 | .bottom {
344 | bottom: 6px;
345 | }
346 |
347 | .top-right {
348 | right: 6px;
349 | top: 48px;
350 | }
351 |
352 | .bottom-right {
353 | bottom: 50px;
354 | right: 6px;
355 | }
356 |
357 | .info-controls {
358 | position: absolute;
359 | top: 6px;
360 | right: 6px;
361 | z-index: 20;
362 | }
363 |
364 | .info-controls .icon-close {
365 | font-size: 14px;
366 | }
367 |
368 | .info-controls > div {
369 | float: right;
370 | width: 86px;
371 | height: 34px;
372 | }
373 |
374 | .info-controls > div:first-child {
375 | margin-left: 6px;
376 | }
377 |
378 | .controls {
379 | display: block;
380 | text-align: center;
381 | list-style: none;
382 | padding: 0;
383 | margin: 0;
384 | }
385 |
386 | .controls:hover {
387 | color: #00a6ff;
388 | cursor: pointer;
389 | }
390 |
391 | .controls > span {
392 | display: inline-block;
393 | line-height: 34px;
394 | }
395 |
396 | .information {
397 | display: block;
398 | text-align: center;
399 | list-style: none;
400 | padding: 0;
401 | margin: 0;
402 | }
403 |
404 | .information:hover {
405 | color: #00a6ff;
406 | cursor: pointer;
407 | }
408 |
409 | .information > span {
410 | line-height: 34px;
411 | display: inline-block;
412 | }
413 |
414 | .world {
415 | stroke: #555;
416 | stroke-linejoin: round;
417 | }
418 |
419 | .tick {
420 | stroke: white;
421 | }
422 |
423 | /* The data console */
424 | #console {
425 | left: 6px;
426 | bottom: 32px;
427 | pointer-events: none;
428 | padding: 6px 12px;
429 | }
430 |
431 | #console .table-header h1 {
432 | margin: 0;
433 | min-width: 156px;
434 | }
435 |
436 | #console .table-header {
437 | margin-bottom: 0;
438 | }
439 |
440 | #console table {
441 | font-size: 10px;
442 | font-family: "Open Sans Normal", "Oswald", sans-serif;
443 | font-weight: 400;
444 | line-height: 12px;
445 | border-collapse: collapse;
446 | }
447 |
448 | #console table td,
449 | #console table th {
450 | text-shadow: none;
451 | padding-right: 20px;
452 | }
453 |
454 | #console table td:last-child,
455 | #console table th:last-child {
456 | padding-right: 0px;
457 | }
458 |
459 | #console table tr.first-level {
460 | font-size: 12px;
461 | font-family: "Open Sans Bold", "Oswald", sans-serif;
462 | font-weight: 700;
463 | line-height: 16px;
464 | text-align: left;
465 | text-transform: uppercase;
466 | }
467 |
468 | #console table tr.second-level {
469 | font-size: 10px;
470 | font-family: "Open Sans Bold", "Oswald", sans-serif;
471 | font-weight: 700;
472 | line-height: 12px;
473 | text-align: left;
474 | padding-bottom: 0.2em;
475 | font-weight: light;
476 | text-transform: uppercase;
477 | }
478 |
479 | #console table tr.second-level th {
480 | font-weight: light !important;
481 | }
482 |
483 | #console colgroup col.left-border {
484 | padding-left: 0.5em;
485 | }
486 |
487 | #console table span.overflow {
488 | display: block;
489 | overflow: hidden;
490 | text-overflow: ellipsis;
491 | height: 1.4em;
492 | }
493 |
494 | #console colgroup col.timestamp-col { width: 11em; }
495 | #console colgroup col.location-col { width: 130px; }
496 | #console colgroup col.attacker-org-col { width: 160px; }
497 | #console colgroup col.attacker-ip-col { width: 98px; }
498 | #console colgroup col.service-col { width: 70px; }
499 | #console colgroup col.port-col { width: 30px; }
500 |
501 | a.toggle {
502 | color: rgb(55, 116, 172);
503 | pointer-events: all;
504 | }
505 |
506 | #rate-graph {
507 | z-index: 20;
508 | position: absolute;
509 | left: 6px;
510 | bottom: 6px;
511 | width: 100%;
512 | height: 20;
513 | }
514 |
515 | #drawer {
516 | display: none;
517 | }
518 |
519 | #drawer .social-media {
520 | list-style: none;
521 | padding: 0;
522 | margin: 0;
523 | }
524 |
525 | #drawer .social-media li {
526 | display: inline-block;
527 | margin-right: 35px;
528 | }
529 |
530 | #drawer .social-media li:last-child {
531 | margin-right: 0px;
532 | }
533 |
534 | #drawer .social-media a {
535 | text-decoration: none;
536 | font-size: 11px;
537 | font-family: "Open Sans Bold", "Oswald", sans-serif;
538 | font-weight: 700;
539 | }
540 |
541 | /* TODO -- sort these */
542 | .attacker {
543 | color: rgb(214, 39, 40);
544 | }
545 |
546 | .target {
547 | color: rgb(31, 119, 180);
548 | }
549 |
550 |
551 | /* LEGEND */
552 |
553 | #legend-container {
554 | float: left;
555 | width: 26%;
556 | margin-left: 10%;
557 | margin-top: 52px;
558 | padding-left: 10px;
559 | background: rgb(0,84,190); /* Old browsers */
560 | background: -moz-linear-gradient(left, rgba(0,84,190,1) 0px, rgba(0,84,190,1) 3px, rgba(0,78,176,1) 3px, rgba(0,78,176,1) 3px, rgba(0,78,176,1) 100%); /* FF3.6+ */
561 | background: -webkit-gradient(linear, left top, right top, color-stop(0px,rgba(0,84,190,1)), color-stop(3px,rgba(0,84,190,1)), color-stop(3px,rgba(0,78,176,1)), color-stop(3px,rgba(0,78,176,1)), color-stop(100%,rgba(0,78,176,1))); /* Chrome,Safari4+ */
562 | background: -webkit-linear-gradient(left, rgba(0,84,190,1) 0px,rgba(0,84,190,1) 3px,rgba(0,78,176,1) 3px,rgba(0,78,176,1) 3px,rgba(0,78,176,1) 100%); /* Chrome10+,Safari5.1+ */
563 | background: -o-linear-gradient(left, rgba(0,84,190,1) 0px,rgba(0,84,190,1) 3px,rgba(0,78,176,1) 3px,rgba(0,78,176,1) 3px,rgba(0,78,176,1) 100%); /* Opera 11.10+ */
564 | background: -ms-linear-gradient(left, rgba(0,84,190,1) 0px,rgba(0,84,190,1) 3px,rgba(0,78,176,1) 3px,rgba(0,78,176,1) 3px,rgba(0,78,176,1) 100%); /* IE10+ */
565 | background: linear-gradient(to right, rgba(0,84,190,1) 0px,rgba(0,84,190,1) 3px,rgba(0,78,176,1) 3px,rgba(0,78,176,1) 3px,rgba(0,78,176,1) 100%); /* W3C */
566 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#0054be', endColorstr='#004eb0',GradientType=1 ); /* IE6-9 */
567 | }
568 |
569 | #legend-container h4 {
570 | margin: 0;
571 | font-size: 9px;
572 | margin-bottom: 20px;
573 | font-family: "Open Sans Bold", "Oswald", sans-serif;
574 | font-weight: 400;
575 | line-height: 11px;
576 | text-align: left;
577 | }
578 |
579 | #legend > div {
580 | margin: auto 0.5%;
581 | text-align: left;
582 | }
583 |
584 | #legend ul {
585 | list-style-type: none;
586 | margin-left: -2em;
587 | }
588 |
589 | #legend .clusters ul > li {
590 | display: inline-block;
591 | margin: auto 0.8em;
592 | }
593 |
594 | #legend .country-colors ul > li {
595 | display: inline-block;
596 | margin: auto 0.2em;
597 | width: 1.2em;
598 | }
599 |
600 | #particle-legend > p {
601 | margin-left: 40px;
602 | }
603 |
604 | #origin-legend > p {
605 | margin-left: 15px;
606 | }
607 |
608 | #country-legend > p {
609 | margin-left: 5px;
610 | }
611 |
612 | #origin-legend p span {
613 | margin-right: 4px;
614 | }
615 |
616 | #origin-legend p .icon-one {
617 | font-size: 20px;
618 | padding-top: 12px;
619 | margin-right: ;
620 | }
621 |
622 | #origin-legend p .icon-ten {
623 | padding-top: 8px;
624 | font-size: 24px;
625 | }
626 |
627 | #origin-legend p .icon-twohundred {
628 | font-size: 32px;
629 | }
630 |
631 | h4 > span {
632 | margin-right: 5px;
633 | float: left;
634 | margin-top: 1px;
635 | }
636 |
637 | h4 > p {
638 | display: inline-block;
639 | width: 85%;
640 | margin: 0px;
641 | }
642 |
643 | #country-legend p [class^="icon-"], #country-legend p [class*=" icon-"] {
644 | font-size: 20px;
645 | }
646 |
647 | footer {
648 | width: 30%;
649 | float: right;
650 | font-size: 8px;
651 | font-family: "Open Sans", "Oswald", sans-serif;
652 | line-height: 10px;
653 | margin-top: 10px;
654 | }
655 |
656 | #events-data tr td:first-child {
657 | white-space: nowrap;
658 | }
659 |
660 | #message-panel {
661 | display: none;
662 | position: absolute;
663 | margin-left: auto;
664 | margin-right: auto;
665 | left: 0;
666 | right: 0;
667 | top: 300px;
668 | width: 600px;
669 | }
670 |
671 | #message-container {
672 | position: relative;
673 | min-height: 100px;
674 | padding: 10px;
675 | text-align: center;
676 | vertical-align: middle;
677 | }
678 |
679 | #message-container span {
680 | display: inline-block;
681 | vertical-align: middle ;
682 | }
683 |
684 | #close-button {
685 | position: absolute;
686 | width: 100px;
687 | left: 250px;
688 | bottom: 20px;
689 | height: 25px;
690 | color: white;
691 | border-radius: 3px;
692 | }
693 |
694 | #social-icons {
695 | position: absolute;
696 | height: 36px;
697 | width: 180px;
698 | bottom: 6px;
699 | right: 6px;
700 | font-size: 20px;
701 | line-height: 36px;
702 | text-align: center;
703 | z-index: 20;
704 | }
705 |
706 | #social-icons ul {
707 | list-style: none;
708 | padding: 0;
709 | margin: 0;
710 | }
711 |
712 | #social-icons li {
713 | display: inline-block;
714 | }
715 |
716 | #social-icons a {
717 | display: inline-block;
718 | cursor: pointer;
719 | }
720 |
721 | #social-icons a:visited {
722 | color: white;
723 | }
724 |
725 | #unknown-icon {
726 | position: absolute;
727 | width: 36px;
728 | height: 36px;
729 | opacity: 0.6;
730 | }
731 |
732 | #tooltip {
733 | border: 1px solid #777;
734 | }
735 |
736 | #tooltip label {
737 | font-style: italic;
738 | font-size: 70%;
739 | display: block;
740 | float: left;
741 | font-weight: bold;
742 | }
743 |
744 | .counties {
745 | fill: none;
746 | stroke: #aaa;
747 | stroke-width: 0.2px;
748 | stroke-linejoin: round;
749 | }
750 |
751 | .states {
752 | fill: none;
753 | stroke: #777;
754 | stroke-width: 1px;
755 | stroke-linejoin: round;
756 | }
757 |
758 | .active {
759 | fill: orange;
760 | }
761 |
762 | .q0 { fill: #ffffff; }
763 | .q1 { fill: #fee5d9; }
764 | .q2 { fill: #fcae91; }
765 | .q3 { fill: #fb6a4a; }
766 | .q4 { fill: #cb181d; }
767 |
--------------------------------------------------------------------------------
/china.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Norse - IPViking Live
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
Loading...
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | 国家
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | 国家
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | 类型
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | 攻击者
126 | 目标
127 | 行为
128 |
129 |
130 |
131 | 时间
132 | 位置
133 | IP
134 | 服务器IP
135 | 服务器位置
136 | 攻击类型
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
Norse Dark Intelligence
160 |
161 | Every second, Norse collects and analyzes live threat
162 | intelligence from darknets in hundreds of locations in
163 | over 40 countries. The attacks shown are based on a
164 | small subset of live flows against the Norse honeypot
165 | infrastructure, representing actual worldwide cyber
166 | attacks by bad actors. At a glance, one can see which
167 | countries are aggressors or targets at the moment, using
168 | which type of attacks (services-ports).
169 |
170 |
171 |
172 | Hovering over the Attack Origins ,
173 | Attack Targets , or
174 | Attack Types will
175 | highlight just the attacks emanating from that country
176 | or over that service-port respectively. Hovering over
177 | any bubble on the map, will highlight only the attacks
178 | from that location and type. Press s
179 | to toggle table sizes.
180 |
181 |
182 |
183 | Norse exposes its threat intelligence via
184 | high-performance, machine-readable APIs in a variety of
185 | forms. Norse also provides products and solutions that
186 | assist organizations in protecting and mitigating cyber
187 | attacks.
188 |
189 |
190 |
191 | For more information, please contact:
192 | inquiry@norse-corp.com
193 |
194 |
195 |
202 |
203 |
204 |
205 |
206 |
Each particle represents an attack
207 |
208 |
209 |
210 |
Attack origins are grouped into clusters
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
Countries are shaded in as they're attacked
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
243 |
244 |
245 |
246 |
247 |
250 |
251 |
252 | Close
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
--------------------------------------------------------------------------------
/data/china_cities.csv:
--------------------------------------------------------------------------------
1 | id,name,value
2 | 3415,六安市,0
3 | 3408,安庆市,0
4 | 3411,滁州市,0
5 | 3418,宣城市,0
6 | 3412,阜阳市,0
7 | 3413,宿州市,0
8 | 3410,黄山市,0
9 | 3414,巢湖市,0
10 | 3416,亳州市,0
11 | 3417,池州市,0
12 | 3401,合肥市,0
13 | 3403,蚌埠市,0
14 | 3402,芜湖市,0
15 | 3406,淮北市,0
16 | 3404,淮南市,0
17 | 3405,马鞍山市,0
18 | 3407,铜陵市,0
19 | 8200,澳门,0
20 | 110228,密云县,0
21 | 110116,怀柔区,0
22 | 110111,房山区,0
23 | 110229,延庆县,0
24 | 110109,门头沟区,0
25 | 110114,昌平区,0
26 | 110115,大兴区,1
27 | 110113,顺义区,0
28 | 110117,平谷区,0
29 | 110112,通州区,1
30 | 110105,朝阳区,1
31 | 110108,海淀区,4
32 | 110106,丰台区,1
33 | 110107,石景山区,1
34 | 110102,西城区,1
35 | 110101,东城区,1
36 | 110104,宣武区,0
37 | 110103,崇文区,0
38 | 500242,酉阳土家族苗族自治县,0
39 | 500236,奉节县,0
40 | 500238,巫溪县,0
41 | 500234,开县,0
42 | 500243,彭水苗族土家族自治县,0
43 | 500235,云阳县,0
44 | 500101,万州区,0
45 | 500229,城口县,0
46 | 500116,江津区,0
47 | 500240,石柱土家族自治县,0
48 | 500237,巫山县,0
49 | 500102,涪陵区,0
50 | 500230,丰都县,0
51 | 500232,武隆县,0
52 | 500119,南川区,0
53 | 500241,秀山土家族苗族自治县,0
54 | 500114,黔江区,0
55 | 500117,合川区,0
56 | 500222,綦江县,0
57 | 500233,忠县,0
58 | 500228,梁平县,0
59 | 500113,巴南区,0
60 | 500223,潼南县,0
61 | 500118,永川区,0
62 | 500231,垫江县,0
63 | 500112,渝北区,0
64 | 500115,长寿区,0
65 | 500225,大足县,0
66 | 500224,铜梁县,0
67 | 500226,荣昌县,0
68 | 500227,璧山县,0
69 | 500109,北碚区,0
70 | 500110,万盛区,0
71 | 500107,九龙坡区,0
72 | 500106,沙坪坝区,0
73 | 500108,南岸区,0
74 | 500105,江北区,0
75 | 500104,大渡口区,0
76 | 500111,双桥区,0
77 | 500103,渝中区,0
78 | 3507,南平市,0
79 | 3504,三明市,0
80 | 3508,龙岩市,0
81 | 3509,宁德市,0
82 | 3501,福州市,0
83 | 3506,漳州市,0
84 | 3505,泉州市,0
85 | 3503,莆田市,0
86 | 3502,厦门市,0
87 | 6209,酒泉市,0
88 | 6207,张掖市,0
89 | 6230,甘南藏族自治州,0
90 | 6206,武威市,0
91 | 6212,陇南市,0
92 | 6210,庆阳市,0
93 | 6204,白银市,0
94 | 6211,定西市,0
95 | 6205,天水市,0
96 | 6201,兰州市,0
97 | 6208,平凉市,0
98 | 6229,临夏回族自治州,0
99 | 6203,金昌市,0
100 | 6202,嘉峪关市,0
101 | 4418,清远市,0
102 | 4402,韶关市,0
103 | 4408,湛江市,0
104 | 4414,梅州市,0
105 | 4416,河源市,0
106 | 4412,肇庆市,0
107 | 4413,惠州市,0
108 | 4409,茂名市,0
109 | 4407,江门市,0
110 | 4417,阳江市,0
111 | 4453,云浮市,0
112 | 4401,广州市,0
113 | 4415,汕尾市,0
114 | 4452,揭阳市,0
115 | 4404,珠海市,0
116 | 4406,佛山市,2
117 | 4451,潮州市,0
118 | 4405,汕头市,0
119 | 4403,深圳市,0
120 | 4419,东莞市,0
121 | 4420,中山市,0
122 | 4510,百色市,0
123 | 4512,河池市,0
124 | 4503,桂林市,0
125 | 4501,南宁市,0
126 | 4502,柳州市,0
127 | 4514,崇左市,0
128 | 4513,来宾市,0
129 | 4509,玉林市,0
130 | 4504,梧州市,0
131 | 4511,贺州市,0
132 | 4507,钦州市,0
133 | 4508,贵港市,0
134 | 4506,防城港市,0
135 | 4505,北海市,1
136 | 5203,遵义市,0
137 | 5226,黔东南苗族侗族自治州,0
138 | 5224,毕节地区,0
139 | 5227,黔南布依族苗族自治州,0
140 | 5222,铜仁地区,0
141 | 5223,黔西南布依族苗族自治州,0
142 | 5202,六盘水市,0
143 | 5204,安顺市,0
144 | 5201,贵阳市,0
145 | 469003,儋州市,0
146 | 469005,文昌市,0
147 | 469033,乐东黎族自治县,0
148 | 4602,三亚市,2
149 | 469036,琼中黎族苗族自治县,0
150 | 469007,东方市,0
151 | 4601,海口市,2
152 | 469006,万宁市,1
153 | 469027,澄迈县,0
154 | 469030,白沙黎族自治县,0
155 | 469002,琼海市,1
156 | 469031,昌江黎族自治县,0
157 | 469028,临高县,0
158 | 469034,陵水黎族自治县,1
159 | 469026,屯昌县,0
160 | 469025,定安县,1
161 | 469035,保亭黎族苗族自治县,0
162 | 469001,五指山市,0
163 | 1308,承德市,0
164 | 1307,张家口市,0
165 | 1306,保定市,0
166 | 1302,唐山市,0
167 | 1309,沧州市,0
168 | 1301,石家庄市,0
169 | 1305,邢台市,0
170 | 1304,邯郸市,0
171 | 1303,秦皇岛市,2
172 | 1311,衡水市,0
173 | 1310,廊坊市,0
174 | 4113,南阳市,0
175 | 4115,信阳市,0
176 | 4103,洛阳市,0
177 | 4117,驻马店市,0
178 | 4116,周口市,0
179 | 4114,商丘市,0
180 | 4112,三门峡市,0
181 | 4107,新乡市,0
182 | 4104,平顶山市,0
183 | 4101,郑州市,0
184 | 4105,安阳市,0
185 | 4102,开封市,0
186 | 4108,焦作市,0
187 | 4110,许昌市,0
188 | 4109,濮阳市,0
189 | 4111,漯河市,0
190 | 4106,鹤壁市,0
191 | 2311,黑河市,0
192 | 2327,大兴安岭地区,0
193 | 2301,哈尔滨市,0
194 | 2302,齐齐哈尔市,0
195 | 2310,牡丹江市,0
196 | 2312,绥化市,0
197 | 2307,伊春市,0
198 | 2308,佳木斯市,0
199 | 2303,鸡西市,0
200 | 2305,双鸭山市,0
201 | 2306,大庆市,0
202 | 2304,鹤岗市,0
203 | 2309,七台河市,0
204 | 4228,恩施土家族苗族自治州,0
205 | 4203,十堰市,0
206 | 4205,宜昌市,0
207 | 4206,襄樊市,0
208 | 4211,黄冈市,0
209 | 4210,荆州市,0
210 | 4208,荆门市,0
211 | 4212,咸宁市,0
212 | 4213,随州市,0
213 | 4209,孝感市,0
214 | 4201,武汉市,0
215 | 4202,黄石市,0
216 | 429021,神农架林区,0
217 | 429006,天门市,0
218 | 429004,仙桃市,0
219 | 429005,潜江市,0
220 | 4207,鄂州市,0
221 | 4312,怀化市,0
222 | 4311,永州市,0
223 | 4305,邵阳市,0
224 | 4310,郴州市,0
225 | 4307,常德市,0
226 | 4331,湘西土家族苗族自治州,0
227 | 4304,衡阳市,0
228 | 4306,岳阳市,0
229 | 4309,益阳市,0
230 | 4301,长沙市,0
231 | 4302,株洲市,0
232 | 4308,张家界市,0
233 | 4313,娄底市,0
234 | 4303,湘潭市,0
235 | 2224,延边朝鲜族自治州,0
236 | 2202,吉林市,0
237 | 2208,白城市,0
238 | 2207,松原市,0
239 | 2201,长春市,0
240 | 2206,白山市,0
241 | 2205,通化市,0
242 | 2203,四平市,0
243 | 2204,辽源市,0
244 | 3209,盐城市,0
245 | 3203,徐州市,0
246 | 3206,南通市,0
247 | 3208,淮安市,0
248 | 3205,苏州市,1
249 | 3213,宿迁市,0
250 | 3207,连云港市,0
251 | 3210,扬州市,0
252 | 3201,南京市,1
253 | 3212,泰州市,0
254 | 3202,无锡市,2
255 | 3204,常州市,0
256 | 3211,镇江市,0
257 | 3607,赣州市,0
258 | 3608,吉安市,0
259 | 3611,上饶市,0
260 | 3604,九江市,0
261 | 3610,抚州市,0
262 | 3609,宜春市,0
263 | 3601,南昌市,0
264 | 3602,景德镇市,0
265 | 3603,萍乡市,0
266 | 3606,鹰潭市,0
267 | 3605,新余市,0
268 | 2102,大连市,0
269 | 2113,朝阳市,0
270 | 2106,丹东市,0
271 | 2112,铁岭市,0
272 | 2101,沈阳市,0
273 | 2104,抚顺市,0
274 | 2114,葫芦岛市,0
275 | 2109,阜新市,0
276 | 2107,锦州市,0
277 | 2103,鞍山市,0
278 | 2105,本溪市,0
279 | 2108,营口市,0
280 | 2110,辽阳市,0
281 | 2111,盘锦市,0
282 | 1507,呼伦贝尔市,0
283 | 1529,阿拉善盟,0
284 | 1525,锡林郭勒盟,0
285 | 1506,鄂尔多斯市,0
286 | 1504,赤峰市,0
287 | 1508,巴彦淖尔市,0
288 | 1505,通辽市,0
289 | 1509,乌兰察布市,0
290 | 1522,兴安盟,0
291 | 1502,包头市,0
292 | 1501,呼和浩特市,0
293 | 1503,乌海市,0
294 | 6403,吴忠市,0
295 | 6405,中卫市,0
296 | 6404,固原市,0
297 | 6401,银川市,0
298 | 6402,石嘴山市,0
299 | 6328,海西蒙古族藏族自治州,0
300 | 6327,玉树藏族自治州,0
301 | 6326,果洛藏族自治州,0
302 | 6325,海南藏族自治州,0
303 | 6322,海北藏族自治州,0
304 | 6323,黄南藏族自治州,0
305 | 6321,海东地区,0
306 | 6301,西宁市,0
307 | 3706,烟台市,0
308 | 3713,临沂市,0
309 | 3707,潍坊市,0
310 | 3702,青岛市,0
311 | 3717,菏泽市,0
312 | 3708,济宁市,1
313 | 3714,德州市,0
314 | 3716,滨州市,0
315 | 3715,聊城市,0
316 | 3705,东营市,0
317 | 3701,济南市,2
318 | 3709,泰安市,2
319 | 3710,威海市,0
320 | 3711,日照市,0
321 | 3703,淄博市,0
322 | 3704,枣庄市,0
323 | 3712,莱芜市,0
324 | 6108,榆林市,0
325 | 6106,延安市,0
326 | 6107,汉中市,0
327 | 6109,安康市,0
328 | 6110,商洛市,0
329 | 6103,宝鸡市,0
330 | 6105,渭南市,0
331 | 6104,咸阳市,0
332 | 6101,西安市,2
333 | 6102,铜川市,0
334 | 1409,忻州市,0
335 | 1411,吕梁市,0
336 | 1410,临汾市,0
337 | 1407,晋中市,2
338 | 1408,运城市,0
339 | 1402,大同市,0
340 | 1404,长治市,0
341 | 1406,朔州市,0
342 | 1405,晋城市,0
343 | 1401,太原市,2
344 | 1403,阳泉市,0
345 | 310230,崇明县,0
346 | 310119,南汇区,1
347 | 310120,奉贤区,0
348 | 310115,浦东新区,2
349 | 310116,金山区,0
350 | 310118,青浦区,1
351 | 310117,松江区,0
352 | 310114,嘉定区,0
353 | 310113,宝山区,0
354 | 310112,闵行区,1
355 | 310110,杨浦区,3
356 | 310107,普陀区,1
357 | 310104,徐汇区,2
358 | 310105,长宁区,0
359 | 310108,闸北区,1
360 | 310109,虹口区,1
361 | 310101,黄浦区,2
362 | 310103,卢湾区,2
363 | 310106,静安区,2
364 | 5133,甘孜藏族自治州,0
365 | 5132,阿坝藏族羌族自治州,0
366 | 5134,凉山彝族自治州,0
367 | 5107,绵阳市,0
368 | 5117,达州市,0
369 | 5108,广元市,0
370 | 5118,雅安市,0
371 | 5115,宜宾市,0
372 | 5111,乐山市,0
373 | 5113,南充市,0
374 | 5119,巴中市,0
375 | 5105,泸州市,0
376 | 5101,成都市,0
377 | 5120,资阳市,0
378 | 5104,攀枝花市,0
379 | 5114,眉山市,0
380 | 5116,广安市,0
381 | 5106,德阳市,0
382 | 5110,内江市,0
383 | 5109,遂宁市,0
384 | 5103,自贡市,0
385 | 7100,台湾,0
386 | 120225,蓟县,0
387 | 120114,武清区,0
388 | 120115,宝坻区,0
389 | 120223,静海县,0
390 | 120221,宁河县,0
391 | 120109,大港区,0
392 | 120107,塘沽区,0
393 | 120111,西青区,0
394 | 120113,北辰区,0
395 | 120110,东丽区,0
396 | 120108,汉沽区,0
397 | 120112,津南区,0
398 | 120103,河西区,0
399 | 120102,河东区,0
400 | 120104,南开区,0
401 | 120105,河北区,0
402 | 120106,红桥区,0
403 | 120101,和平区,0
404 | 5424,那曲地区,0
405 | 5425,阿里地区,0
406 | 5423,日喀则地区,0
407 | 5426,林芝地区,0
408 | 5421,昌都地区,0
409 | 5422,山南地区,0
410 | 5401,拉萨市,0
411 | 8100,香港,0
412 | 6528,巴音郭楞蒙古自治州,0
413 | 6532,和田地区,0
414 | 6522,哈密地区,0
415 | 6529,阿克苏地区,0
416 | 6543,阿勒泰地区,0
417 | 6531,喀什地区,0
418 | 6542,塔城地区,0
419 | 6523,昌吉回族自治州,0
420 | 6530,克孜勒苏柯尔克孜自治州,0
421 | 6521,吐鲁番地区,0
422 | 6540,伊犁哈萨克自治州,0
423 | 6527,博尔塔拉蒙古自治州,0
424 | 6501,乌鲁木齐市,0
425 | 6502,克拉玛依市,0
426 | 659002,阿拉尔市,0
427 | 659003,图木舒克市,0
428 | 659004,五家渠市,0
429 | 659001,石河子市,0
430 | 5308,普洱市,0
431 | 5325,红河哈尼族彝族自治州,0
432 | 5326,文山壮族苗族自治州,0
433 | 5303,曲靖市,0
434 | 5323,楚雄彝族自治州,1
435 | 5329,大理白族自治州,2
436 | 5309,临沧市,0
437 | 5334,迪庆藏族自治州,2
438 | 5306,昭通市,0
439 | 5301,昆明市,2
440 | 5307,丽江市,2
441 | 5328,西双版纳傣族自治州,0
442 | 5305,保山市,0
443 | 5304,玉溪市,0
444 | 5333,怒江傈僳族自治州,0
445 | 5331,德宏傣族景颇族自治州,0
446 | 3311,丽水市,2
447 | 3301,杭州市,4
448 | 3303,温州市,1
449 | 3302,宁波市,2
450 | 3309,舟山市,0
451 | 3310,台州市,0
452 | 3307,金华市,4
453 | 3308,衢州市,2
454 | 3306,绍兴市,1
455 | 3304,嘉兴市,1
456 | 3305,湖州市,0
457 |
--------------------------------------------------------------------------------
/data/china_provinces.json:
--------------------------------------------------------------------------------
1 | {"type":"FeatureCollection","features":[{"type":"Feature","id":"xin_jiang","properties":{"name":"新疆","cp":[84.9023,41.748],"childNum":18},"geometry":{"type":"Polygon","coordinates":[[[96.416,42.7588],[96.416,42.7148],[95.9766,42.4951],[96.0645,42.3193],[96.2402,42.2314],[95.9766,41.9238],[95.2734,41.6162],[95.1855,41.792],[94.5703,41.4844],[94.043,41.0889],[93.8672,40.6934],[93.0762,40.6494],[92.6367,39.6387],[92.373,39.3311],[92.373,39.1113],[92.373,39.0234],[90.1758,38.4961],[90.3516,38.2324],[90.6152,38.3203],[90.5273,37.8369],[91.0547,37.4414],[91.3184,37.0898],[90.7031,36.7822],[90.791,36.6064],[91.0547,36.5186],[91.0547,36.0791],[90.8789,36.0352],[90,36.2549],[89.9121,36.0791],[89.7363,36.0791],[89.209,36.2988],[88.7695,36.3428],[88.5938,36.4746],[87.3633,36.4307],[86.2207,36.167],[86.1328,35.8594],[85.6055,35.6836],[85.0781,35.7275],[84.1992,35.376],[83.1445,35.4199],[82.8809,35.6836],[82.4414,35.7275],[82.002,35.332],[81.6504,35.2441],[80.4199,35.4199],[80.2441,35.2881],[80.332,35.1563],[80.2441,35.2002],[79.8926,34.8047],[79.8047,34.4971],[79.1016,34.4531],[79.0137,34.3213],[78.2227,34.7168],[78.0469,35.2441],[78.0469,35.5078],[77.4316,35.4639],[76.8164,35.6396],[76.5527,35.8594],[76.2012,35.8154],[75.9375,36.0352],[76.0254,36.4746],[75.8496,36.6943],[75.498,36.7383],[75.4102,36.958],[75.0586,37.002],[74.8828,36.9141],[74.7949,37.0459],[74.5313,37.0898],[74.5313,37.2217],[74.8828,37.2217],[75.1465,37.4414],[74.8828,37.5732],[74.9707,37.749],[74.8828,38.4521],[74.3555,38.6719],[74.1797,38.6719],[74.0918,38.54],[73.8281,38.584],[73.7402,38.8477],[73.8281,38.9795],[73.4766,39.375],[73.916,39.5068],[73.916,39.6826],[73.8281,39.7705],[74.0039,40.0342],[74.8828,40.3418],[74.7949,40.5176],[75.2344,40.4297],[75.5859,40.6494],[75.7617,40.2979],[76.377,40.3857],[76.9043,41.001],[77.6074,41.001],[78.1348,41.2207],[78.1348,41.3965],[80.1563,42.0557],[80.2441,42.2754],[80.1563,42.627],[80.2441,42.8467],[80.5078,42.8906],[80.4199,43.0664],[80.7715,43.1982],[80.4199,44.165],[80.4199,44.6045],[79.9805,44.8242],[79.9805,44.9561],[81.7383,45.3955],[82.0898,45.2197],[82.5293,45.2197],[82.2656,45.6592],[83.0566,47.2412],[83.6719,47.0215],[84.7266,47.0215],[84.9023,46.8896],[85.5176,47.0654],[85.6934,47.2852],[85.5176,48.1201],[85.7813,48.4277],[86.5723,48.5596],[86.8359,48.8232],[86.748,48.9551],[86.8359,49.1309],[87.8027,49.1748],[87.8906,48.999],[87.7148,48.9111],[88.0664,48.7354],[87.9785,48.6035],[88.5059,48.3838],[88.6816,48.1641],[89.1211,47.9883],[89.5605,48.0322],[89.7363,47.8564],[90.0879,47.8564],[90.3516,47.6807],[90.5273,47.2412],[90.8789,46.9775],[91.0547,46.582],[90.8789,46.3184],[91.0547,46.0107],[90.7031,45.7471],[90.7031,45.5273],[90.8789,45.2197],[91.582,45.0879],[93.5156,44.9561],[94.7461,44.3408],[95.3613,44.2969],[95.3613,44.0332],[95.5371,43.9014],[95.8887,43.2422],[96.3281,42.9346],[96.416,42.7588]]]}},{"type":"Feature","id":"xi_zang","properties":{"name":"西藏","cp":[88.7695,31.6846],"childNum":7},"geometry":{"type":"Polygon","coordinates":[[[79.0137,34.3213],[79.1016,34.4531],[79.8047,34.4971],[79.8926,34.8047],[80.2441,35.2002],[80.332,35.1563],[80.2441,35.2881],[80.4199,35.4199],[81.6504,35.2441],[82.002,35.332],[82.4414,35.7275],[82.8809,35.6836],[83.1445,35.4199],[84.1992,35.376],[85.0781,35.7275],[85.6055,35.6836],[86.1328,35.8594],[86.2207,36.167],[87.3633,36.4307],[88.5938,36.4746],[88.7695,36.3428],[89.209,36.2988],[89.7363,36.0791],[89.3848,36.0352],[89.4727,35.9033],[89.7363,35.7715],[89.7363,35.4199],[89.4727,35.376],[89.4727,35.2441],[89.5605,34.8926],[89.8242,34.8486],[89.7363,34.6729],[89.8242,34.3652],[89.6484,34.0137],[90.0879,33.4863],[90.7031,33.1348],[91.4063,33.1348],[91.9336,32.8271],[92.1973,32.8271],[92.2852,32.7393],[92.9883,32.7393],[93.5156,32.4756],[93.7793,32.5635],[94.1309,32.4316],[94.6582,32.6074],[95.1855,32.4316],[95.0098,32.2998],[95.1855,32.3438],[95.2734,32.2119],[95.3613,32.168],[95.3613,31.9922],[95.4492,31.8164],[95.8008,31.6846],[95.9766,31.8164],[96.1523,31.5967],[96.2402,31.9482],[96.5039,31.7285],[96.8555,31.6846],[96.7676,31.9922],[97.2949,32.0801],[97.3828,32.5635],[97.7344,32.5195],[98.1738,32.3438],[98.4375,31.8604],[98.877,31.4209],[98.6133,31.2012],[98.9648,30.7617],[99.1406,29.2676],[98.9648,29.1357],[98.9648,28.8281],[98.7891,28.8721],[98.7891,29.0039],[98.7012,28.916],[98.6133,28.5205],[98.7891,28.3447],[98.7012,28.2129],[98.3496,28.125],[98.2617,28.3887],[98.1738,28.125],[97.5586,28.5205],[97.2949,28.0811],[97.3828,27.9053],[97.0313,27.7295],[96.5039,28.125],[95.7129,28.2568],[95.3613,28.125],[95.2734,27.9492],[94.2188,27.5537],[93.8672,27.0264],[93.6035,26.9385],[92.1094,26.8506],[92.0215,27.4658],[91.582,27.5537],[91.582,27.9053],[91.4063,28.0371],[91.0547,27.8613],[90.7031,28.0811],[89.8242,28.2129],[89.6484,28.1689],[89.1211,27.5977],[89.1211,27.334],[89.0332,27.2021],[88.7695,27.4219],[88.8574,27.9932],[88.6816,28.125],[88.1543,27.9053],[87.8906,27.9492],[87.7148,27.8174],[87.0996,27.8174],[86.748,28.125],[86.5723,28.125],[86.4844,27.9053],[86.1328,28.125],[86.0449,27.9053],[85.6934,28.3447],[85.6055,28.2568],[85.166,28.3447],[85.166,28.6523],[84.9023,28.5645],[84.4629,28.7402],[84.2871,28.8721],[84.1992,29.2236],[84.1113,29.2676],[83.584,29.1797],[83.2324,29.5752],[82.1777,30.0586],[82.0898,30.3223],[81.3867,30.3662],[81.2109,30.0146],[81.0352,30.2344],[80.0684,30.5859],[79.7168,30.9375],[79.0137,31.0693],[78.75,31.333],[78.8379,31.5967],[78.6621,31.8164],[78.75,31.9043],[78.4863,32.124],[78.3984,32.5195],[78.75,32.6953],[78.9258,32.3438],[79.2773,32.5635],[79.1016,33.1787],[78.6621,33.6621],[78.6621,34.1016],[78.9258,34.1455],[79.0137,34.3213]]]}},{"type":"Feature","id":"nei_meng_gu","properties":{"name":"内蒙古","cp":[117.5977,44.3408],"childNum":12},"geometry":{"type":"Polygon","coordinates":[[[97.207,42.8027],[99.4922,42.583],[100.8105,42.6709],[101.7773,42.4951],[102.041,42.2314],[102.7441,42.1436],[103.3594,41.8799],[103.8867,41.792],[104.502,41.8799],[104.502,41.6602],[105.0293,41.5723],[105.7324,41.9238],[107.4023,42.4512],[109.4238,42.4512],[110.3906,42.7588],[111.0059,43.3301],[111.9727,43.6816],[111.9727,43.8135],[111.4453,44.3848],[111.7969,45],[111.9727,45.0879],[113.6426,44.7363],[114.1699,44.9561],[114.5215,45.3955],[115.6641,45.4395],[116.1914,45.7031],[116.2793,45.9668],[116.543,46.2744],[117.334,46.3623],[117.4219,46.582],[117.7734,46.5381],[118.3008,46.7578],[118.7402,46.7139],[118.916,46.7578],[119.0918,46.6699],[119.707,46.626],[119.9707,46.7139],[119.707,47.1973],[118.4766,47.9883],[117.8613,48.0322],[117.334,47.6807],[116.8066,47.9004],[116.1914,47.8564],[115.9277,47.6807],[115.5762,47.9004],[115.4883,48.1641],[115.8398,48.252],[115.8398,48.5596],[116.7188,49.834],[117.7734,49.5264],[118.5645,49.9219],[119.2676,50.0977],[119.3555,50.3174],[119.1797,50.3613],[119.5313,50.7568],[119.5313,50.8887],[119.707,51.0645],[120.1465,51.6797],[120.6738,51.9434],[120.7617,52.1191],[120.7617,52.251],[120.5859,52.3389],[120.6738,52.5146],[120.4102,52.6465],[120.0586,52.6025],[120.0586,52.7344],[120.8496,53.2617],[121.4648,53.3496],[121.8164,53.042],[121.2012,52.5586],[121.6406,52.4268],[121.7285,52.2949],[121.9922,52.2949],[122.168,52.5146],[122.6953,52.251],[122.6074,52.0752],[122.959,51.3281],[123.3105,51.2402],[123.6621,51.3721],[124.3652,51.2842],[124.541,51.3721],[124.8926,51.3721],[125.0684,51.6357],[125.332,51.6357],[126.0352,51.0205],[125.7715,50.7568],[125.7715,50.5371],[125.332,50.1416],[125.1563,49.834],[125.2441,49.1748],[124.8047,49.1309],[124.4531,48.1201],[124.2773,48.5156],[122.4316,47.373],[123.0469,46.7139],[123.3984,46.8896],[123.3984,46.9775],[123.4863,46.9775],[123.5742,46.8457],[123.5742,46.8896],[123.5742,46.6699],[123.0469,46.582],[123.2227,46.2305],[122.7832,46.0107],[122.6953,45.7031],[122.4316,45.8789],[122.2559,45.791],[121.8164,46.0107],[121.7285,45.7471],[121.9043,45.7031],[122.2559,45.2637],[122.0801,44.8682],[122.3438,44.2529],[123.1348,44.4727],[123.4863,43.7256],[123.3105,43.5059],[123.6621,43.374],[123.5742,43.0225],[123.3105,42.9785],[123.1348,42.8027],[122.7832,42.7148],[122.3438,42.8467],[122.3438,42.6709],[121.9922,42.7148],[121.7285,42.4512],[121.4648,42.4951],[120.498,42.0996],[120.1465,41.7041],[119.8828,42.1875],[119.5313,42.3633],[119.3555,42.2754],[119.2676,41.7041],[119.4434,41.6162],[119.2676,41.3086],[118.3887,41.3086],[118.125,41.748],[118.3008,41.792],[118.3008,42.0996],[118.125,42.0557],[117.9492,42.2314],[118.0371,42.4072],[117.7734,42.627],[117.5098,42.583],[117.334,42.4512],[116.8945,42.4072],[116.8066,42.0117],[116.2793,42.0117],[116.0156,41.792],[115.9277,41.9238],[115.2246,41.5723],[114.9609,41.6162],[114.873,42.0996],[114.5215,42.1436],[114.1699,41.792],[114.2578,41.5723],[113.9063,41.4404],[113.9941,41.2207],[113.9063,41.1328],[114.082,40.7373],[114.082,40.5176],[113.8184,40.5176],[113.5547,40.3418],[113.2031,40.3857],[112.7637,40.166],[112.3242,40.2539],[111.9727,39.5947],[111.4453,39.6387],[111.3574,39.4189],[111.0938,39.375],[111.0938,39.5947],[110.6543,39.2871],[110.127,39.4629],[110.2148,39.2871],[109.8633,39.2432],[109.9512,39.1553],[108.9844,38.3203],[109.0723,38.0127],[108.8965,37.9688],[108.8086,38.0127],[108.7207,37.7051],[108.1934,37.6172],[107.666,37.8809],[107.3145,38.1006],[106.7871,38.1885],[106.5234,38.3203],[106.9629,38.9795],[106.7871,39.375],[106.3477,39.2871],[105.9082,38.7158],[105.8203,37.793],[104.3262,37.4414],[103.4473,37.8369],[103.3594,38.0127],[103.5352,38.1445],[103.4473,38.3643],[104.2383,38.9795],[104.0625,39.4189],[103.3594,39.3311],[103.0078,39.1113],[102.4805,39.2432],[101.8652,39.1113],[102.041,38.8916],[101.7773,38.6719],[101.3379,38.7598],[101.25,39.0234],[100.9863,38.9355],[100.8105,39.4189],[100.5469,39.4189],[100.0195,39.7705],[99.4922,39.8584],[100.1074,40.2539],[100.1953,40.6494],[99.9316,41.001],[99.2285,40.8691],[99.0527,40.6934],[98.9648,40.7813],[98.7891,40.6055],[98.5254,40.7373],[98.6133,40.6494],[98.3496,40.5615],[98.3496,40.9131],[97.4707,41.4844],[97.8223,41.6162],[97.8223,41.748],[97.207,42.8027]]]}},{"type":"Feature","id":"qing_hai","properties":{"name":"青海","cp":[96.2402,35.4199],"childNum":8},"geometry":{"type":"Polygon","coordinates":[[[89.7363,36.0791],[89.9121,36.0791],[90,36.2549],[90.8789,36.0352],[91.0547,36.0791],[91.0547,36.5186],[90.791,36.6064],[90.7031,36.7822],[91.3184,37.0898],[91.0547,37.4414],[90.5273,37.8369],[90.6152,38.3203],[90.3516,38.2324],[90.1758,38.4961],[92.373,39.0234],[92.373,39.1113],[93.1641,39.1992],[93.1641,38.9795],[93.6914,38.9355],[93.8672,38.7158],[94.3066,38.7598],[94.5703,38.3643],[95.0098,38.4082],[95.4492,38.2764],[95.7129,38.3643],[96.2402,38.1006],[96.416,38.2324],[96.6797,38.1885],[96.6797,38.4521],[97.1191,38.584],[97.0313,39.1992],[98.1738,38.8037],[98.3496,39.0234],[98.6133,38.9355],[98.7891,39.0674],[99.1406,38.9355],[99.8438,38.3643],[100.1953,38.2764],[100.0195,38.4521],[100.1074,38.4961],[100.459,38.2764],[100.7227,38.2324],[101.1621,37.8369],[101.5137,37.8809],[101.7773,37.6172],[101.9531,37.7051],[102.1289,37.4414],[102.5684,37.1777],[102.4805,36.958],[102.6563,36.8262],[102.5684,36.7383],[102.832,36.3428],[103.0078,36.2549],[102.9199,36.0791],[102.9199,35.9033],[102.6563,35.7715],[102.832,35.5957],[102.4805,35.5957],[102.3047,35.4199],[102.3926,35.2002],[101.9531,34.8486],[101.9531,34.6289],[102.2168,34.4092],[102.1289,34.2773],[101.6895,34.1016],[100.9863,34.3652],[100.8105,34.2773],[101.25,33.6621],[101.5137,33.7061],[101.6016,33.5303],[101.7773,33.5303],[101.6895,33.3105],[101.7773,33.2227],[101.6016,33.1348],[101.1621,33.2227],[101.25,32.6953],[100.7227,32.6514],[100.7227,32.5195],[100.3711,32.7393],[100.1074,32.6514],[100.1074,32.8711],[99.8438,33.0029],[99.7559,32.7393],[99.2285,32.915],[99.2285,33.0469],[98.877,33.1787],[98.4375,34.0576],[97.8223,34.1895],[97.6465,34.1016],[97.7344,33.9258],[97.3828,33.8818],[97.4707,33.5742],[97.7344,33.3984],[97.3828,32.8711],[97.4707,32.6953],[97.7344,32.5195],[97.3828,32.5635],[97.2949,32.0801],[96.7676,31.9922],[96.8555,31.6846],[96.5039,31.7285],[96.2402,31.9482],[96.1523,31.5967],[95.9766,31.8164],[95.8008,31.6846],[95.4492,31.8164],[95.3613,31.9922],[95.3613,32.168],[95.2734,32.2119],[95.1855,32.3438],[95.0098,32.2998],[95.1855,32.4316],[94.6582,32.6074],[94.1309,32.4316],[93.7793,32.5635],[93.5156,32.4756],[92.9883,32.7393],[92.2852,32.7393],[92.1973,32.8271],[91.9336,32.8271],[91.4063,33.1348],[90.7031,33.1348],[90.0879,33.4863],[89.6484,34.0137],[89.8242,34.3652],[89.7363,34.6729],[89.8242,34.8486],[89.5605,34.8926],[89.4727,35.2441],[89.4727,35.376],[89.7363,35.4199],[89.7363,35.7715],[89.4727,35.9033],[89.3848,36.0352],[89.7363,36.0791]]]}},{"type":"Feature","id":"si_chuan","properties":{"name":"四川","cp":[102.9199,30.1904],"childNum":21},"geometry":{"type":"Polygon","coordinates":[[[101.7773,33.5303],[101.8652,33.5742],[101.9531,33.4424],[101.8652,33.0908],[102.4805,33.4424],[102.2168,33.9258],[102.9199,34.3213],[103.0957,34.1895],[103.1836,33.7939],[104.1504,33.6182],[104.2383,33.3984],[104.4141,33.3105],[104.3262,33.2227],[104.4141,33.0469],[104.3262,32.8711],[104.4141,32.7393],[105.2051,32.6074],[105.3809,32.7393],[105.3809,32.8711],[105.4688,32.915],[105.5566,32.7393],[106.084,32.8711],[106.084,32.7393],[106.3477,32.6514],[107.0508,32.6953],[107.1387,32.4756],[107.2266,32.4316],[107.4023,32.5195],[108.0176,32.168],[108.2813,32.2559],[108.5449,32.2119],[108.3691,32.168],[108.2813,31.9043],[108.5449,31.6846],[108.1934,31.5088],[107.9297,30.8496],[107.4902,30.8496],[107.4023,30.7617],[107.4902,30.6299],[107.0508,30.0146],[106.7871,30.0146],[106.6113,30.3223],[106.2598,30.1904],[105.8203,30.4541],[105.6445,30.2783],[105.5566,30.1025],[105.7324,29.8828],[105.293,29.5313],[105.4688,29.3115],[105.7324,29.2676],[105.8203,28.96],[106.2598,28.8721],[106.3477,28.5205],[105.9961,28.7402],[105.6445,28.4326],[105.9082,28.125],[106.1719,28.125],[106.3477,27.8174],[105.6445,27.6416],[105.5566,27.7734],[105.293,27.7295],[105.2051,27.9932],[105.0293,28.0811],[104.8535,27.9053],[104.4141,27.9492],[104.3262,28.0371],[104.4141,28.125],[104.4141,28.2568],[104.2383,28.4326],[104.4141,28.6084],[103.8867,28.6523],[103.7988,28.3008],[103.4473,28.125],[103.4473,27.7734],[102.9199,27.29],[103.0078,26.3672],[102.6563,26.1914],[102.5684,26.3672],[102.1289,26.1035],[101.8652,26.0596],[101.6016,26.2354],[101.6895,26.3672],[101.4258,26.5869],[101.4258,26.8066],[101.4258,26.7188],[101.1621,27.0264],[101.1621,27.1582],[100.7227,27.8613],[100.3711,27.8174],[100.2832,27.7295],[100.0195,28.125],[100.1953,28.3447],[99.668,28.8281],[99.4043,28.5205],[99.4043,28.1689],[99.2285,28.3008],[99.1406,29.2676],[98.9648,30.7617],[98.6133,31.2012],[98.877,31.4209],[98.4375,31.8604],[98.1738,32.3438],[97.7344,32.5195],[97.4707,32.6953],[97.3828,32.8711],[97.7344,33.3984],[97.4707,33.5742],[97.3828,33.8818],[97.7344,33.9258],[97.6465,34.1016],[97.8223,34.1895],[98.4375,34.0576],[98.877,33.1787],[99.2285,33.0469],[99.2285,32.915],[99.7559,32.7393],[99.8438,33.0029],[100.1074,32.8711],[100.1074,32.6514],[100.3711,32.7393],[100.7227,32.5195],[100.7227,32.6514],[101.25,32.6953],[101.1621,33.2227],[101.6016,33.1348],[101.7773,33.2227],[101.6895,33.3105],[101.7773,33.5303]]]}},{"type":"Feature","id":"hei_long_jiang","properties":{"name":"黑龙江","cp":[128.1445,48.5156],"childNum":13},"geometry":{"type":"Polygon","coordinates":[[[121.4648,53.3496],[123.6621,53.5693],[124.8926,53.0859],[125.0684,53.2178],[125.5957,53.0859],[125.6836,52.9102],[126.123,52.7783],[126.0352,52.6025],[126.2109,52.5146],[126.3867,52.2949],[126.3867,52.207],[126.5625,52.1631],[126.4746,51.9434],[126.9141,51.3721],[126.8262,51.2842],[127.002,51.3281],[126.9141,51.1084],[127.2656,50.7568],[127.3535,50.2734],[127.6172,50.2295],[127.5293,49.8779],[127.793,49.6143],[128.7598,49.5703],[129.1113,49.3506],[129.4629,49.4385],[130.2539,48.8672],[130.6934,48.8672],[130.5176,48.6475],[130.8691,48.2959],[130.6934,48.1201],[131.0449,47.6807],[132.5391,47.7246],[132.627,47.9443],[133.0664,48.1201],[133.5059,48.1201],[134.209,48.3838],[135.0879,48.4277],[134.7363,48.252],[134.5605,47.9883],[134.7363,47.6807],[134.5605,47.4609],[134.3848,47.4609],[134.209,47.2852],[134.209,47.1533],[133.8574,46.5381],[133.9453,46.2744],[133.5059,45.835],[133.418,45.5713],[133.2422,45.5273],[133.0664,45.1318],[132.8906,45.0439],[131.9238,45.3516],[131.5723,45.0439],[131.0449,44.8682],[131.3086,44.0771],[131.2207,43.7256],[131.3086,43.4619],[130.8691,43.418],[130.5176,43.6377],[130.3418,43.9893],[129.9902,43.8574],[129.9023,44.0332],[129.8145,43.9014],[129.2871,43.8135],[129.1992,43.5938],[128.8477,43.5498],[128.4961,44.165],[128.4082,44.4727],[128.0566,44.3408],[128.0566,44.1211],[127.7051,44.1211],[127.5293,44.6045],[127.0898,44.6045],[127.002,44.7803],[127.0898,45],[126.9141,45.1318],[126.5625,45.2637],[126.0352,45.1758],[125.7715,45.3076],[125.6836,45.5273],[125.0684,45.3955],[124.8926,45.5273],[124.3652,45.4395],[124.0137,45.7471],[123.9258,46.2305],[123.2227,46.2305],[123.0469,46.582],[123.5742,46.6699],[123.5742,46.8896],[123.5742,46.8457],[123.4863,46.9775],[123.3984,46.9775],[123.3984,46.8896],[123.0469,46.7139],[122.4316,47.373],[124.2773,48.5156],[124.4531,48.1201],[124.8047,49.1309],[125.2441,49.1748],[125.1563,49.834],[125.332,50.1416],[125.7715,50.5371],[125.7715,50.7568],[126.0352,51.0205],[125.332,51.6357],[125.0684,51.6357],[124.8926,51.3721],[124.541,51.3721],[124.3652,51.2842],[123.6621,51.3721],[123.3105,51.2402],[122.959,51.3281],[122.6074,52.0752],[122.6953,52.251],[122.168,52.5146],[121.9922,52.2949],[121.7285,52.2949],[121.6406,52.4268],[121.2012,52.5586],[121.8164,53.042],[121.4648,53.3496]]]}},{"type":"Feature","id":"gan_su","properties":{"name":"甘肃","cp":[95.7129,40.166],"childNum":14},"geometry":{"type":"Polygon","coordinates":[[[96.416,42.7148],[97.207,42.8027],[97.8223,41.748],[97.8223,41.6162],[97.4707,41.4844],[98.3496,40.9131],[98.3496,40.5615],[98.6133,40.6494],[98.5254,40.7373],[98.7891,40.6055],[98.9648,40.7813],[99.0527,40.6934],[99.2285,40.8691],[99.9316,41.001],[100.1953,40.6494],[100.1074,40.2539],[99.4922,39.8584],[100.0195,39.7705],[100.5469,39.4189],[100.8105,39.4189],[100.9863,38.9355],[101.25,39.0234],[101.3379,38.7598],[101.7773,38.6719],[102.041,38.8916],[101.8652,39.1113],[102.4805,39.2432],[103.0078,39.1113],[103.3594,39.3311],[104.0625,39.4189],[104.2383,38.9795],[103.4473,38.3643],[103.5352,38.1445],[103.3594,38.0127],[103.4473,37.8369],[104.3262,37.4414],[104.5898,37.4414],[104.5898,37.2217],[104.8535,37.2217],[105.293,36.8262],[105.2051,36.6943],[105.4688,36.123],[105.293,35.9912],[105.3809,35.7715],[105.7324,35.7275],[105.8203,35.5518],[105.9961,35.4639],[105.9082,35.4199],[105.9961,35.4199],[106.084,35.376],[106.2598,35.4199],[106.3477,35.2441],[106.5234,35.332],[106.4355,35.6836],[106.6992,35.6836],[106.9629,35.8154],[106.875,36.123],[106.5234,36.2549],[106.5234,36.4746],[106.4355,36.5625],[106.6113,36.7822],[106.6113,37.0898],[107.3145,37.0898],[107.3145,36.9141],[108.7207,36.3428],[108.6328,35.9912],[108.5449,35.8594],[108.6328,35.5518],[108.5449,35.2881],[107.7539,35.2881],[107.7539,35.1123],[107.8418,35.0244],[107.666,34.9365],[107.2266,34.8926],[106.9629,35.0684],[106.6113,35.0684],[106.5234,34.7607],[106.3477,34.585],[106.6992,34.3213],[106.5234,34.2773],[106.6113,34.1455],[106.4355,33.9258],[106.5234,33.5303],[105.9961,33.6182],[105.7324,33.3984],[105.9961,33.1787],[105.9082,33.0029],[105.4688,32.915],[105.3809,32.8711],[105.3809,32.7393],[105.2051,32.6074],[104.4141,32.7393],[104.3262,32.8711],[104.4141,33.0469],[104.3262,33.2227],[104.4141,33.3105],[104.2383,33.3984],[104.1504,33.6182],[103.1836,33.7939],[103.0957,34.1895],[102.9199,34.3213],[102.2168,33.9258],[102.4805,33.4424],[101.8652,33.0908],[101.9531,33.4424],[101.8652,33.5742],[101.7773,33.5303],[101.6016,33.5303],[101.5137,33.7061],[101.25,33.6621],[100.8105,34.2773],[100.9863,34.3652],[101.6895,34.1016],[102.1289,34.2773],[102.2168,34.4092],[101.9531,34.6289],[101.9531,34.8486],[102.3926,35.2002],[102.3047,35.4199],[102.4805,35.5957],[102.832,35.5957],[102.6563,35.7715],[102.9199,35.9033],[102.9199,36.0791],[103.0078,36.2549],[102.832,36.3428],[102.5684,36.7383],[102.6563,36.8262],[102.4805,36.958],[102.5684,37.1777],[102.1289,37.4414],[101.9531,37.7051],[101.7773,37.6172],[101.5137,37.8809],[101.1621,37.8369],[100.7227,38.2324],[100.459,38.2764],[100.1074,38.4961],[100.0195,38.4521],[100.1953,38.2764],[99.8438,38.3643],[99.1406,38.9355],[98.7891,39.0674],[98.6133,38.9355],[98.3496,39.0234],[98.1738,38.8037],[97.0313,39.1992],[97.1191,38.584],[96.6797,38.4521],[96.6797,38.1885],[96.416,38.2324],[96.2402,38.1006],[95.7129,38.3643],[95.4492,38.2764],[95.0098,38.4082],[94.5703,38.3643],[94.3066,38.7598],[93.8672,38.7158],[93.6914,38.9355],[93.1641,38.9795],[93.1641,39.1992],[92.373,39.1113],[92.373,39.3311],[92.6367,39.6387],[93.0762,40.6494],[93.8672,40.6934],[94.043,41.0889],[94.5703,41.4844],[95.1855,41.792],[95.2734,41.6162],[95.9766,41.9238],[96.2402,42.2314],[96.0645,42.3193],[95.9766,42.4951],[96.416,42.7148]]]}},{"type":"Feature","id":"yun_nan","properties":{"name":"云南","cp":[101.8652,25.1807],"childNum":16},"geometry":{"type":"Polygon","coordinates":[[[98.1738,28.125],[98.2617,28.3887],[98.3496,28.125],[98.7012,28.2129],[98.7891,28.3447],[98.6133,28.5205],[98.7012,28.916],[98.7891,29.0039],[98.7891,28.8721],[98.9648,28.8281],[98.9648,29.1357],[99.1406,29.2676],[99.2285,28.3008],[99.4043,28.1689],[99.4043,28.5205],[99.668,28.8281],[100.1953,28.3447],[100.0195,28.125],[100.2832,27.7295],[100.3711,27.8174],[100.7227,27.8613],[101.1621,27.1582],[101.1621,27.0264],[101.4258,26.7188],[101.4258,26.8066],[101.4258,26.5869],[101.6895,26.3672],[101.6016,26.2354],[101.8652,26.0596],[102.1289,26.1035],[102.5684,26.3672],[102.6563,26.1914],[103.0078,26.3672],[102.9199,27.29],[103.4473,27.7734],[103.4473,28.125],[103.7988,28.3008],[103.8867,28.6523],[104.4141,28.6084],[104.2383,28.4326],[104.4141,28.2568],[104.4141,28.125],[104.3262,28.0371],[104.4141,27.9492],[104.8535,27.9053],[105.0293,28.0811],[105.2051,27.9932],[105.293,27.7295],[105.2051,27.3779],[104.5898,27.334],[104.4141,27.4658],[104.1504,27.2461],[103.8867,27.4219],[103.623,27.0264],[103.7109,26.9824],[103.7109,26.7627],[103.8867,26.543],[104.4141,26.6748],[104.6777,26.4111],[104.3262,25.708],[104.8535,25.2246],[104.5898,25.0488],[104.6777,24.9609],[104.502,24.7412],[104.6777,24.3457],[104.7656,24.4775],[105.0293,24.4336],[105.2051,24.082],[105.4688,24.0381],[105.5566,24.126],[105.9961,24.126],[106.1719,23.8184],[106.1719,23.5547],[105.6445,23.4229],[105.5566,23.2031],[105.293,23.3789],[104.8535,23.1592],[104.7656,22.8516],[104.3262,22.6758],[104.1504,22.8076],[103.9746,22.5439],[103.623,22.7637],[103.5352,22.5879],[103.3594,22.8076],[103.0957,22.4561],[102.4805,22.7637],[102.3047,22.4121],[101.8652,22.3682],[101.7773,22.5],[101.6016,22.1924],[101.8652,21.6211],[101.7773,21.1377],[101.6016,21.2256],[101.25,21.1816],[101.1621,21.7529],[100.6348,21.4453],[100.1074,21.4893],[99.9316,22.0605],[99.2285,22.1484],[99.4043,22.5879],[99.3164,22.7197],[99.4922,23.0713],[98.877,23.2031],[98.7012,23.9502],[98.877,24.126],[98.1738,24.082],[97.7344,23.8623],[97.5586,23.9063],[97.7344,24.126],[97.6465,24.4336],[97.5586,24.4336],[97.5586,24.7412],[97.7344,24.8291],[97.8223,25.2686],[98.1738,25.4004],[98.1738,25.6201],[98.3496,25.5762],[98.5254,25.8398],[98.7012,25.8838],[98.6133,26.0596],[98.7012,26.1475],[98.7891,26.5869],[98.7012,27.5098],[98.5254,27.6416],[98.3496,27.5098],[98.1738,28.125]]]}},{"type":"Feature","id":"guang_xi","properties":{"name":"广西","cp":[108.2813,23.6426],"childNum":14},"geometry":{"type":"Polygon","coordinates":[[[104.502,24.7412],[104.6777,24.6094],[105.2051,24.9609],[105.9961,24.6533],[106.1719,24.7852],[106.1719,24.9609],[106.875,25.1807],[107.0508,25.2686],[106.9629,25.4883],[107.2266,25.6201],[107.4902,25.2246],[107.7539,25.2246],[107.8418,25.1367],[108.1055,25.2246],[108.1934,25.4443],[108.3691,25.5322],[108.6328,25.3125],[108.6328,25.5762],[109.0723,25.5322],[108.9844,25.752],[109.3359,25.708],[109.5117,26.0156],[109.7754,25.8838],[109.9512,26.1914],[110.2148,25.9717],[110.5664,26.3232],[111.1816,26.3232],[111.2695,26.2354],[111.2695,25.8838],[111.4453,25.8398],[111.0059,25.0049],[111.0938,24.9609],[111.3574,25.1367],[111.5332,24.6533],[111.709,24.7852],[112.0605,24.7412],[111.8848,24.6533],[112.0605,24.3457],[111.8848,24.2139],[111.8848,23.9941],[111.7969,23.8184],[111.6211,23.8184],[111.6211,23.6865],[111.3574,23.4668],[111.4453,23.0273],[111.2695,22.8076],[110.7422,22.5439],[110.7422,22.2803],[110.6543,22.1484],[110.3027,22.1484],[110.3027,21.8848],[109.9512,21.8408],[109.8633,21.665],[109.7754,21.6211],[109.7754,21.4014],[109.5996,21.4453],[109.1602,21.3574],[109.248,20.874],[109.0723,20.9619],[109.0723,21.5332],[108.7207,21.5332],[108.6328,21.665],[108.2813,21.4893],[107.8418,21.6211],[107.4023,21.6211],[107.0508,21.7969],[107.0508,21.9287],[106.6992,22.0166],[106.6113,22.4121],[106.7871,22.7637],[106.6992,22.8955],[105.9082,22.9395],[105.5566,23.0713],[105.5566,23.2031],[105.6445,23.4229],[106.1719,23.5547],[106.1719,23.8184],[105.9961,24.126],[105.5566,24.126],[105.4688,24.0381],[105.2051,24.082],[105.0293,24.4336],[104.7656,24.4775],[104.6777,24.3457],[104.502,24.7412]]]}},{"type":"Feature","id":"hu_nan","properties":{"name":"湖南","cp":[111.5332,27.3779],"childNum":14},"geometry":{"type":"Polygon","coordinates":[[[109.248,28.4766],[109.248,29.1357],[109.5117,29.6191],[109.6875,29.6191],[109.7754,29.751],[110.4785,29.6631],[110.6543,29.751],[110.4785,30.0146],[110.8301,30.1465],[111.7969,29.9268],[112.2363,29.5313],[112.5,29.6191],[112.6758,29.5752],[112.9395,29.7949],[113.0273,29.751],[112.9395,29.4873],[113.0273,29.4434],[113.5547,29.8389],[113.5547,29.707],[113.7305,29.5752],[113.6426,29.3115],[113.7305,29.0918],[113.9063,29.0479],[114.1699,28.8281],[114.082,28.5645],[114.2578,28.3447],[113.7305,27.9492],[113.6426,27.5977],[113.6426,27.3779],[113.8184,27.29],[113.7305,27.1143],[113.9063,26.9385],[113.9063,26.6309],[114.082,26.5869],[113.9941,26.1914],[114.2578,26.1475],[113.9941,26.0596],[113.9063,25.4443],[113.6426,25.3125],[113.2031,25.5322],[112.8516,25.3564],[113.0273,25.2246],[113.0273,24.9609],[112.8516,24.917],[112.5879,25.1367],[112.2363,25.1807],[112.1484,24.873],[112.0605,24.7412],[111.709,24.7852],[111.5332,24.6533],[111.3574,25.1367],[111.0938,24.9609],[111.0059,25.0049],[111.4453,25.8398],[111.2695,25.8838],[111.2695,26.2354],[111.1816,26.3232],[110.5664,26.3232],[110.2148,25.9717],[109.9512,26.1914],[109.7754,25.8838],[109.5117,26.0156],[109.4238,26.2793],[109.248,26.3232],[109.4238,26.5869],[109.3359,26.7188],[109.5117,26.8066],[109.5117,27.0264],[109.3359,27.1582],[108.8965,27.0264],[108.8086,27.1143],[109.4238,27.5977],[109.3359,27.9053],[109.3359,28.2568],[109.248,28.4766]]]}},{"type":"Feature","id":"shan_xi_1","properties":{"name":"陕西","cp":[109.5996,35.6396],"childNum":10},"geometry":{"type":"Polygon","coordinates":[[[105.4688,32.915],[105.9082,33.0029],[105.9961,33.1787],[105.7324,33.3984],[105.9961,33.6182],[106.5234,33.5303],[106.4355,33.9258],[106.6113,34.1455],[106.5234,34.2773],[106.6992,34.3213],[106.3477,34.585],[106.5234,34.7607],[106.6113,35.0684],[106.9629,35.0684],[107.2266,34.8926],[107.666,34.9365],[107.8418,35.0244],[107.7539,35.1123],[107.7539,35.2881],[108.5449,35.2881],[108.6328,35.5518],[108.5449,35.8594],[108.6328,35.9912],[108.7207,36.3428],[107.3145,36.9141],[107.3145,37.0898],[107.3145,37.6172],[107.666,37.8809],[108.1934,37.6172],[108.7207,37.7051],[108.8086,38.0127],[108.8965,37.9688],[109.0723,38.0127],[108.9844,38.3203],[109.9512,39.1553],[109.8633,39.2432],[110.2148,39.2871],[110.127,39.4629],[110.6543,39.2871],[111.0938,39.5947],[111.0938,39.375],[111.1816,39.2432],[110.918,38.7158],[110.8301,38.4961],[110.4785,38.1885],[110.4785,37.9688],[110.8301,37.6611],[110.3906,37.002],[110.4785,36.123],[110.5664,35.6396],[110.2148,34.8926],[110.2148,34.6729],[110.3906,34.585],[110.4785,34.2334],[110.6543,34.1455],[110.6543,33.8379],[111.0059,33.5303],[111.0059,33.2666],[110.7422,33.1348],[110.5664,33.2666],[110.3027,33.1787],[109.5996,33.2666],[109.4238,33.1348],[109.7754,33.0469],[109.7754,32.915],[110.127,32.7393],[110.127,32.6074],[109.6875,32.6074],[109.5117,32.4316],[109.5996,31.7285],[109.248,31.7285],[109.0723,31.9482],[108.5449,32.2119],[108.2813,32.2559],[108.0176,32.168],[107.4023,32.5195],[107.2266,32.4316],[107.1387,32.4756],[107.0508,32.6953],[106.3477,32.6514],[106.084,32.7393],[106.084,32.8711],[105.5566,32.7393],[105.4688,32.915]]]}},{"type":"Feature","id":"guang_dong","properties":{"name":"广东","cp":[113.4668,22.8076],"childNum":21},"geometry":{"type":"Polygon","coordinates":[[[109.7754,21.4014],[109.7754,21.6211],[109.8633,21.665],[109.9512,21.8408],[110.3027,21.8848],[110.3027,22.1484],[110.6543,22.1484],[110.7422,22.2803],[110.7422,22.5439],[111.2695,22.8076],[111.4453,23.0273],[111.3574,23.4668],[111.6211,23.6865],[111.6211,23.8184],[111.7969,23.8184],[111.8848,23.9941],[111.8848,24.2139],[112.0605,24.3457],[111.8848,24.6533],[112.0605,24.7412],[112.1484,24.873],[112.2363,25.1807],[112.5879,25.1367],[112.8516,24.917],[113.0273,24.9609],[113.0273,25.2246],[112.8516,25.3564],[113.2031,25.5322],[113.6426,25.3125],[113.9063,25.4443],[113.9941,25.2686],[114.6094,25.4004],[114.7852,25.2686],[114.6973,25.1367],[114.4336,24.9609],[114.1699,24.6973],[114.4336,24.5215],[115.4004,24.7852],[115.8398,24.5654],[115.752,24.7852],[115.9277,24.917],[116.2793,24.7852],[116.3672,24.873],[116.543,24.6094],[116.7188,24.6533],[116.9824,24.1699],[116.9824,23.9063],[117.1582,23.5547],[117.334,23.2471],[116.8945,23.3789],[116.6309,23.1152],[116.543,22.8516],[115.9277,22.7197],[115.6641,22.7637],[115.5762,22.6318],[115.0488,22.6758],[114.6094,22.3682],[114.3457,22.5439],[113.9941,22.5],[113.8184,22.1924],[114.3457,22.1484],[114.4336,22.0166],[114.082,21.9287],[113.9941,21.7969],[113.5547,22.0166],[113.1152,21.8408],[112.9395,21.5771],[112.4121,21.4453],[112.2363,21.5332],[111.5332,21.4893],[111.2695,21.3574],[110.7422,21.3574],[110.6543,21.2256],[110.7422,20.918],[110.4785,20.874],[110.6543,20.2588],[110.5664,20.2588],[110.3906,20.127],[110.0391,20.127],[109.8633,20.127],[109.8633,20.3027],[109.5996,20.918],[109.7754,21.4014],[109.7754,21.4014]],[[113.5986,22.1649],[113.6096,22.1265],[113.5547,22.11],[113.5437,22.2034],[113.5767,22.2034],[113.5986,22.1649]]]}},{"type":"Feature","id":"ji_lin","properties":{"name":"吉林","cp":[126.4746,43.5938],"childNum":9},"geometry":{"type":"Polygon","coordinates":[[[123.2227,46.2305],[123.9258,46.2305],[124.0137,45.7471],[124.3652,45.4395],[124.8926,45.5273],[125.0684,45.3955],[125.6836,45.5273],[125.7715,45.3076],[126.0352,45.1758],[126.5625,45.2637],[126.9141,45.1318],[127.0898,45],[127.002,44.7803],[127.0898,44.6045],[127.5293,44.6045],[127.7051,44.1211],[128.0566,44.1211],[128.0566,44.3408],[128.4082,44.4727],[128.4961,44.165],[128.8477,43.5498],[129.1992,43.5938],[129.2871,43.8135],[129.8145,43.9014],[129.9023,44.0332],[129.9902,43.8574],[130.3418,43.9893],[130.5176,43.6377],[130.8691,43.418],[131.3086,43.4619],[131.3086,43.3301],[131.1328,42.9346],[130.4297,42.7148],[130.6055,42.6709],[130.6055,42.4512],[130.2539,42.7588],[130.2539,42.8906],[130.166,42.9785],[129.9023,43.0225],[129.7266,42.4951],[129.375,42.4512],[128.9355,42.0117],[128.0566,42.0117],[128.3203,41.5723],[128.1445,41.3525],[127.0898,41.5283],[127.1777,41.5723],[126.9141,41.792],[126.6504,41.6602],[126.4746,41.3965],[126.123,40.957],[125.6836,40.8691],[125.5957,40.9131],[125.7715,41.2207],[125.332,41.6602],[125.332,41.9678],[125.4199,42.0996],[125.332,42.1436],[124.8926,42.8027],[124.8926,43.0664],[124.7168,43.0664],[124.4531,42.8467],[124.2773,43.2422],[123.8379,43.4619],[123.6621,43.374],[123.3105,43.5059],[123.4863,43.7256],[123.1348,44.4727],[122.3438,44.2529],[122.0801,44.8682],[122.2559,45.2637],[121.9043,45.7031],[121.7285,45.7471],[121.8164,46.0107],[122.2559,45.791],[122.4316,45.8789],[122.6953,45.7031],[122.7832,46.0107],[123.2227,46.2305]]]}},{"type":"Feature","id":"he_bei","properties":{"name":"河北","cp":[115.4004,37.9688],"childNum":11},"geometry":{"type":"MultiPolygon","coordinates":[[[[114.5215,39.5068],[114.3457,39.8584],[113.9941,39.9902],[114.5215,40.3418],[114.3457,40.3857],[114.2578,40.6055],[114.082,40.7373],[113.9063,41.1328],[113.9941,41.2207],[113.9063,41.4404],[114.2578,41.5723],[114.1699,41.792],[114.5215,42.1436],[114.873,42.0996],[114.9609,41.6162],[115.2246,41.5723],[115.9277,41.9238],[116.0156,41.792],[116.2793,42.0117],[116.8066,42.0117],[116.8945,42.4072],[117.334,42.4512],[117.5098,42.583],[117.7734,42.627],[118.0371,42.4072],[117.9492,42.2314],[118.125,42.0557],[118.3008,42.0996],[118.3008,41.792],[118.125,41.748],[118.3887,41.3086],[119.2676,41.3086],[118.8281,40.8252],[119.2676,40.5176],[119.5313,40.5615],[119.707,40.1221],[119.8828,39.9463],[119.5313,39.6826],[119.4434,39.4189],[118.916,39.0674],[118.4766,38.9355],[118.125,39.0234],[118.0371,39.1992],[118.0371,39.2432],[117.8613,39.4189],[117.9492,39.5947],[117.6855,39.5947],[117.5098,39.7705],[117.5098,39.9902],[117.6855,39.9902],[117.6855,40.0781],[117.4219,40.21],[117.2461,40.5176],[117.4219,40.6494],[116.9824,40.6934],[116.6309,41.0449],[116.3672,40.9131],[116.4551,40.7813],[116.1914,40.7813],[116.1035,40.6055],[115.752,40.5615],[115.9277,40.2539],[115.4004,39.9463],[115.4883,39.6387],[115.752,39.5068],[116.1914,39.5947],[116.3672,39.4629],[116.543,39.5947],[116.8066,39.5947],[116.8945,39.1113],[116.7188,38.9355],[116.7188,38.8037],[117.2461,38.54],[117.5977,38.6279],[117.9492,38.3203],[117.4219,37.8369],[116.8066,37.8369],[116.4551,37.4854],[116.2793,37.5732],[116.2793,37.3535],[116.0156,37.3535],[115.752,36.9141],[115.3125,36.5186],[115.4883,36.167],[115.3125,36.0791],[115.1367,36.2109],[114.9609,36.0791],[114.873,36.123],[113.7305,36.3428],[113.4668,36.6504],[113.7305,36.8701],[113.7305,37.1338],[114.1699,37.6611],[113.9941,37.7051],[113.8184,38.1445],[113.5547,38.2764],[113.5547,38.54],[113.8184,38.8037],[113.8184,38.9355],[113.9063,39.0234],[114.3457,39.0674],[114.5215,39.5068]]],[[[117.2461,40.0781],[117.1582,39.8145],[117.1582,39.6387],[116.8945,39.6826],[116.8945,39.8145],[116.8066,39.9902],[117.2461,40.0781]]]]}},{"type":"Feature","id":"hu_bei","properties":{"name":"湖北","cp":[112.2363,31.1572],"childNum":17},"geometry":{"type":"Polygon","coordinates":[[[110.2148,31.1572],[110.127,31.377],[109.6875,31.5527],[109.7754,31.6846],[109.5996,31.7285],[109.5117,32.4316],[109.6875,32.6074],[110.127,32.6074],[110.127,32.7393],[109.7754,32.915],[109.7754,33.0469],[109.4238,33.1348],[109.5996,33.2666],[110.3027,33.1787],[110.5664,33.2666],[110.7422,33.1348],[111.0059,33.2666],[111.5332,32.6074],[112.3242,32.3438],[113.2031,32.4316],[113.4668,32.2998],[113.7305,32.4316],[113.8184,31.8604],[113.9941,31.7725],[114.1699,31.8604],[114.5215,31.7725],[114.6094,31.5527],[114.7852,31.4648],[115.1367,31.5967],[115.2246,31.4209],[115.4004,31.4209],[115.5762,31.2012],[116.0156,31.0254],[115.752,30.6738],[116.1035,30.1904],[116.1035,29.8389],[115.9277,29.707],[115.4883,29.7949],[114.873,29.3994],[114.2578,29.3555],[113.9063,29.0479],[113.7305,29.0918],[113.6426,29.3115],[113.7305,29.5752],[113.5547,29.707],[113.5547,29.8389],[113.0273,29.4434],[112.9395,29.4873],[113.0273,29.751],[112.9395,29.7949],[112.6758,29.5752],[112.5,29.6191],[112.2363,29.5313],[111.7969,29.9268],[110.8301,30.1465],[110.4785,30.0146],[110.6543,29.751],[110.4785,29.6631],[109.7754,29.751],[109.6875,29.6191],[109.5117,29.6191],[109.248,29.1357],[109.0723,29.3555],[108.9844,29.3115],[108.6328,29.8389],[108.457,29.7949],[108.5449,30.2344],[108.457,30.4102],[108.6328,30.5859],[108.8086,30.498],[109.0723,30.6299],[109.1602,30.542],[109.248,30.6299],[109.4238,30.542],[109.8633,30.8936],[110.0391,30.8057],[110.2148,31.1572]]]}},{"type":"Feature","id":"gui_zhou","properties":{"name":"贵州","cp":[106.6113,26.9385],"childNum":9},"geometry":{"type":"Polygon","coordinates":[[[104.1504,27.2461],[104.4141,27.4658],[104.5898,27.334],[105.2051,27.3779],[105.293,27.7295],[105.5566,27.7734],[105.6445,27.6416],[106.3477,27.8174],[106.1719,28.125],[105.9082,28.125],[105.6445,28.4326],[105.9961,28.7402],[106.3477,28.5205],[106.5234,28.5645],[106.4355,28.7842],[106.5234,28.7842],[106.6113,28.6523],[106.6113,28.5205],[106.6992,28.4766],[106.875,28.7842],[107.4023,28.8721],[107.4023,29.1797],[107.5781,29.2236],[107.8418,29.1357],[107.8418,29.0039],[108.2813,29.0918],[108.3691,28.6523],[108.5449,28.6523],[108.5449,28.3887],[108.7207,28.4766],[108.7207,28.2129],[109.0723,28.2129],[109.248,28.4766],[109.3359,28.2568],[109.3359,27.9053],[109.4238,27.5977],[108.8086,27.1143],[108.8965,27.0264],[109.3359,27.1582],[109.5117,27.0264],[109.5117,26.8066],[109.3359,26.7188],[109.4238,26.5869],[109.248,26.3232],[109.4238,26.2793],[109.5117,26.0156],[109.3359,25.708],[108.9844,25.752],[109.0723,25.5322],[108.6328,25.5762],[108.6328,25.3125],[108.3691,25.5322],[108.1934,25.4443],[108.1055,25.2246],[107.8418,25.1367],[107.7539,25.2246],[107.4902,25.2246],[107.2266,25.6201],[106.9629,25.4883],[107.0508,25.2686],[106.875,25.1807],[106.1719,24.9609],[106.1719,24.7852],[105.9961,24.6533],[105.2051,24.9609],[104.6777,24.6094],[104.502,24.7412],[104.6777,24.9609],[104.5898,25.0488],[104.8535,25.2246],[104.3262,25.708],[104.6777,26.4111],[104.4141,26.6748],[103.8867,26.543],[103.7109,26.7627],[103.7109,26.9824],[103.623,27.0264],[103.8867,27.4219],[104.1504,27.2461]]]}},{"type":"Feature","id":"shan_dong","properties":{"name":"山东","cp":[118.7402,36.4307],"childNum":17},"geometry":{"type":"Polygon","coordinates":[[[115.4883,36.167],[115.3125,36.5186],[115.752,36.9141],[116.0156,37.3535],[116.2793,37.3535],[116.2793,37.5732],[116.4551,37.4854],[116.8066,37.8369],[117.4219,37.8369],[117.9492,38.3203],[118.125,38.1445],[118.916,38.1445],[119.3555,37.6611],[119.0039,37.5293],[119.0039,37.3535],[119.3555,37.1338],[119.707,37.1338],[119.8828,37.3975],[120.498,37.8369],[120.5859,38.1445],[120.9375,38.4521],[121.0254,37.8369],[121.2012,37.6611],[121.9043,37.4854],[122.168,37.6172],[122.2559,37.4854],[122.6074,37.4854],[122.6953,37.3535],[122.6074,36.9141],[122.4316,36.7822],[121.8164,36.8701],[121.7285,36.6943],[121.1133,36.6064],[121.1133,36.4307],[121.377,36.2549],[120.7617,36.167],[120.9375,35.8594],[120.6738,36.0352],[119.707,35.4639],[119.9707,34.9805],[119.3555,35.0244],[119.2676,35.1123],[118.916,35.0244],[118.7402,34.7168],[118.4766,34.6729],[118.3887,34.4092],[118.2129,34.4092],[118.125,34.6289],[117.9492,34.6729],[117.5977,34.4531],[117.334,34.585],[117.2461,34.4531],[116.8066,34.9365],[116.4551,34.8926],[116.3672,34.6289],[116.1914,34.585],[115.5762,34.585],[115.4004,34.8486],[114.7852,35.0684],[115.0488,35.376],[115.2246,35.4199],[115.4883,35.7275],[116.1035,36.0791],[115.3125,35.8154],[115.4883,36.167]]]}},{"type":"Feature","id":"jiang_xi","properties":{"name":"江西","cp":[116.0156,27.29],"childNum":11},"geometry":{"type":"Polygon","coordinates":[[[114.2578,28.3447],[114.082,28.5645],[114.1699,28.8281],[113.9063,29.0479],[114.2578,29.3555],[114.873,29.3994],[115.4883,29.7949],[115.9277,29.707],[116.1035,29.8389],[116.2793,29.7949],[116.7188,30.0586],[116.8945,29.9268],[116.7188,29.751],[116.7188,29.6191],[117.1582,29.707],[117.0703,29.8389],[117.1582,29.9268],[117.5098,29.6191],[118.0371,29.5752],[118.2129,29.3994],[118.0371,29.1797],[118.0371,29.0479],[118.3887,28.7842],[118.4766,28.3447],[118.4766,28.3008],[118.3008,28.0811],[117.7734,27.8174],[117.5098,27.9932],[116.9824,27.6416],[117.1582,27.29],[117.0703,27.1143],[116.543,26.8066],[116.6309,26.4551],[116.3672,26.2354],[116.4551,26.1035],[116.1914,25.8838],[116.0156,25.2686],[115.8398,25.2246],[115.9277,24.917],[115.752,24.7852],[115.8398,24.5654],[115.4004,24.7852],[114.4336,24.5215],[114.1699,24.6973],[114.4336,24.9609],[114.6973,25.1367],[114.7852,25.2686],[114.6094,25.4004],[113.9941,25.2686],[113.9063,25.4443],[113.9941,26.0596],[114.2578,26.1475],[113.9941,26.1914],[114.082,26.5869],[113.9063,26.6309],[113.9063,26.9385],[113.7305,27.1143],[113.8184,27.29],[113.6426,27.3779],[113.6426,27.5977],[113.7305,27.9492],[114.2578,28.3447]]]}},{"type":"Feature","id":"he_nan","properties":{"name":"河南","cp":[113.4668,33.8818],"childNum":17},"geometry":{"type":"Polygon","coordinates":[[[110.3906,34.585],[110.8301,34.6289],[111.1816,34.8047],[111.5332,34.8486],[111.7969,35.0684],[112.0605,35.0684],[112.0605,35.2881],[112.7637,35.2002],[113.1152,35.332],[113.6426,35.6836],[113.7305,36.3428],[114.873,36.123],[114.9609,36.0791],[115.1367,36.2109],[115.3125,36.0791],[115.4883,36.167],[115.3125,35.8154],[116.1035,36.0791],[115.4883,35.7275],[115.2246,35.4199],[115.0488,35.376],[114.7852,35.0684],[115.4004,34.8486],[115.5762,34.585],[116.1914,34.585],[116.1914,34.4092],[116.543,34.2773],[116.6309,33.9258],[116.1914,33.7061],[116.0156,33.9697],[115.6641,34.0576],[115.5762,33.9258],[115.5762,33.6621],[115.4004,33.5303],[115.3125,33.1787],[114.873,33.1348],[114.873,33.0029],[115.1367,32.8711],[115.2246,32.6074],[115.5762,32.4316],[115.8398,32.5195],[115.9277,31.7725],[115.4883,31.6846],[115.4004,31.4209],[115.2246,31.4209],[115.1367,31.5967],[114.7852,31.4648],[114.6094,31.5527],[114.5215,31.7725],[114.1699,31.8604],[113.9941,31.7725],[113.8184,31.8604],[113.7305,32.4316],[113.4668,32.2998],[113.2031,32.4316],[112.3242,32.3438],[111.5332,32.6074],[111.0059,33.2666],[111.0059,33.5303],[110.6543,33.8379],[110.6543,34.1455],[110.4785,34.2334],[110.3906,34.585]]]}},{"type":"Feature","id":"liao_ning","properties":{"name":"辽宁","cp":[122.3438,41.0889],"childNum":14},"geometry":{"type":"Polygon","coordinates":[[[119.2676,41.3086],[119.4434,41.6162],[119.2676,41.7041],[119.3555,42.2754],[119.5313,42.3633],[119.8828,42.1875],[120.1465,41.7041],[120.498,42.0996],[121.4648,42.4951],[121.7285,42.4512],[121.9922,42.7148],[122.3438,42.6709],[122.3438,42.8467],[122.7832,42.7148],[123.1348,42.8027],[123.3105,42.9785],[123.5742,43.0225],[123.6621,43.374],[123.8379,43.4619],[124.2773,43.2422],[124.4531,42.8467],[124.7168,43.0664],[124.8926,43.0664],[124.8926,42.8027],[125.332,42.1436],[125.4199,42.0996],[125.332,41.9678],[125.332,41.6602],[125.7715,41.2207],[125.5957,40.9131],[125.6836,40.8691],[124.541,40.21],[124.1016,39.6826],[123.3984,39.6826],[123.1348,39.4189],[123.1348,39.0234],[122.0801,39.0234],[121.5527,38.7158],[121.1133,38.6719],[120.9375,38.9795],[121.377,39.1992],[121.2012,39.5508],[122.0801,40.3857],[121.9922,40.6934],[121.7285,40.8252],[121.2012,40.8252],[120.5859,40.21],[119.8828,39.9463],[119.707,40.1221],[119.5313,40.5615],[119.2676,40.5176],[118.8281,40.8252],[119.2676,41.3086]]]}},{"type":"Feature","id":"shan_xi_2","properties":{"name":"山西","cp":[112.4121,37.6611],"childNum":11},"geometry":{"type":"Polygon","coordinates":[[[110.918,38.7158],[111.1816,39.2432],[111.0938,39.375],[111.3574,39.4189],[111.4453,39.6387],[111.9727,39.5947],[112.3242,40.2539],[112.7637,40.166],[113.2031,40.3857],[113.5547,40.3418],[113.8184,40.5176],[114.082,40.5176],[114.082,40.7373],[114.2578,40.6055],[114.3457,40.3857],[114.5215,40.3418],[113.9941,39.9902],[114.3457,39.8584],[114.5215,39.5068],[114.3457,39.0674],[113.9063,39.0234],[113.8184,38.9355],[113.8184,38.8037],[113.5547,38.54],[113.5547,38.2764],[113.8184,38.1445],[113.9941,37.7051],[114.1699,37.6611],[113.7305,37.1338],[113.7305,36.8701],[113.4668,36.6504],[113.7305,36.3428],[113.6426,35.6836],[113.1152,35.332],[112.7637,35.2002],[112.0605,35.2881],[112.0605,35.0684],[111.7969,35.0684],[111.5332,34.8486],[111.1816,34.8047],[110.8301,34.6289],[110.3906,34.585],[110.2148,34.6729],[110.2148,34.8926],[110.5664,35.6396],[110.4785,36.123],[110.3906,37.002],[110.8301,37.6611],[110.4785,37.9688],[110.4785,38.1885],[110.8301,38.4961],[110.918,38.7158]]]}},{"type":"Feature","id":"an_hui","properties":{"name":"安徽","cp":[117.2461,32.0361],"childNum":17},"geometry":{"type":"Polygon","coordinates":[[[116.6309,33.9258],[116.543,34.2773],[116.1914,34.4092],[116.1914,34.585],[116.3672,34.6289],[116.8945,34.4092],[117.1582,34.0576],[117.5977,34.0137],[117.7734,33.7061],[118.125,33.75],[117.9492,33.2227],[118.0371,33.1348],[118.2129,33.2227],[118.3008,32.7832],[118.7402,32.7393],[118.916,32.959],[119.1797,32.8271],[119.1797,32.4756],[118.5645,32.5635],[118.6523,32.2119],[118.4766,32.168],[118.3887,31.9482],[118.916,31.5527],[118.7402,31.377],[118.8281,31.2451],[119.3555,31.2891],[119.4434,31.1572],[119.6191,31.1133],[119.6191,31.0693],[119.4434,30.6738],[119.2676,30.6299],[119.3555,30.4102],[118.916,30.3223],[118.916,29.9707],[118.7402,29.707],[118.2129,29.3994],[118.0371,29.5752],[117.5098,29.6191],[117.1582,29.9268],[117.0703,29.8389],[117.1582,29.707],[116.7188,29.6191],[116.7188,29.751],[116.8945,29.9268],[116.7188,30.0586],[116.2793,29.7949],[116.1035,29.8389],[116.1035,30.1904],[115.752,30.6738],[116.0156,31.0254],[115.5762,31.2012],[115.4004,31.4209],[115.4883,31.6846],[115.9277,31.7725],[115.8398,32.5195],[115.5762,32.4316],[115.2246,32.6074],[115.1367,32.8711],[114.873,33.0029],[114.873,33.1348],[115.3125,33.1787],[115.4004,33.5303],[115.5762,33.6621],[115.5762,33.9258],[115.6641,34.0576],[116.0156,33.9697],[116.1914,33.7061],[116.6309,33.9258]]]}},{"type":"Feature","id":"fu_jian","properties":{"name":"福建","cp":[118.3008,25.9277],"childNum":9},"geometry":{"type":"Polygon","coordinates":[[[118.4766,28.3008],[118.8281,28.2568],[118.7402,28.0371],[118.916,27.4658],[119.2676,27.4219],[119.6191,27.6855],[119.7949,27.29],[120.2344,27.4219],[120.4102,27.1582],[120.7617,27.0264],[120.6738,26.8945],[120.2344,26.8506],[120.2344,26.7188],[120.4102,26.6748],[120.498,26.3672],[120.2344,26.2793],[120.4102,26.1475],[120.0586,26.1914],[119.9707,25.9277],[119.7949,25.9277],[119.9707,25.4004],[119.7949,25.2686],[119.5313,25.1367],[119.4434,25.0049],[119.2676,25.0928],[118.916,24.8291],[118.6523,24.5215],[118.4766,24.5215],[118.4766,24.4336],[118.2129,24.3457],[118.2129,24.1699],[117.8613,23.9941],[117.7734,23.7744],[117.5098,23.5986],[117.1582,23.5547],[116.9824,23.9063],[116.9824,24.1699],[116.7188,24.6533],[116.543,24.6094],[116.3672,24.873],[116.2793,24.7852],[115.9277,24.917],[115.8398,25.2246],[116.0156,25.2686],[116.1914,25.8838],[116.4551,26.1035],[116.3672,26.2354],[116.6309,26.4551],[116.543,26.8066],[117.0703,27.1143],[117.1582,27.29],[116.9824,27.6416],[117.5098,27.9932],[117.7734,27.8174],[118.3008,28.0811],[118.4766,28.3008]]]}},{"type":"Feature","id":"zhe_jiang","properties":{"name":"浙江","cp":[120.498,29.0918],"childNum":11},"geometry":{"type":"Polygon","coordinates":[[[118.2129,29.3994],[118.7402,29.707],[118.916,29.9707],[118.916,30.3223],[119.3555,30.4102],[119.2676,30.6299],[119.4434,30.6738],[119.6191,31.0693],[119.6191,31.1133],[119.9707,31.1572],[120.498,30.8057],[120.9375,31.0254],[121.2891,30.6738],[121.9922,30.8057],[122.6953,30.8936],[122.8711,30.7178],[122.959,30.1465],[122.6074,30.1025],[122.6074,29.9268],[122.168,29.5313],[122.3438,28.8721],[121.9922,28.8721],[121.9922,28.4326],[121.7285,28.3447],[121.7285,28.2129],[121.4648,28.2129],[121.5527,28.0371],[121.2891,27.9492],[121.1133,27.4219],[120.6738,27.334],[120.6738,27.1582],[120.9375,27.0264],[120.7617,27.0264],[120.4102,27.1582],[120.2344,27.4219],[119.7949,27.29],[119.6191,27.6855],[119.2676,27.4219],[118.916,27.4658],[118.7402,28.0371],[118.8281,28.2568],[118.4766,28.3008],[118.4766,28.3447],[118.3887,28.7842],[118.0371,29.0479],[118.0371,29.1797],[118.2129,29.3994]]]}},{"type":"Feature","id":"jiang_su","properties":{"name":"江苏","cp":[120.0586,32.915],"childNum":13},"geometry":{"type":"Polygon","coordinates":[[[116.3672,34.6289],[116.4551,34.8926],[116.8066,34.9365],[117.2461,34.4531],[117.334,34.585],[117.5977,34.4531],[117.9492,34.6729],[118.125,34.6289],[118.2129,34.4092],[118.3887,34.4092],[118.4766,34.6729],[118.7402,34.7168],[118.916,35.0244],[119.2676,35.1123],[119.3555,35.0244],[119.3555,34.8486],[119.707,34.585],[120.3223,34.3652],[120.9375,33.0469],[121.0254,32.6514],[121.377,32.4756],[121.4648,32.168],[121.9043,31.9922],[121.9922,31.6846],[121.9922,31.5967],[121.2012,31.8604],[121.1133,31.7285],[121.377,31.5088],[121.2012,31.4648],[120.9375,31.0254],[120.498,30.8057],[119.9707,31.1572],[119.6191,31.1133],[119.4434,31.1572],[119.3555,31.2891],[118.8281,31.2451],[118.7402,31.377],[118.916,31.5527],[118.3887,31.9482],[118.4766,32.168],[118.6523,32.2119],[118.5645,32.5635],[119.1797,32.4756],[119.1797,32.8271],[118.916,32.959],[118.7402,32.7393],[118.3008,32.7832],[118.2129,33.2227],[118.0371,33.1348],[117.9492,33.2227],[118.125,33.75],[117.7734,33.7061],[117.5977,34.0137],[117.1582,34.0576],[116.8945,34.4092],[116.3672,34.6289]]]}},{"type":"Feature","id":"chong_qing","properties":{"name":"重庆","cp":[107.7539,30.1904],"childNum":40},"geometry":{"type":"Polygon","coordinates":[[[108.5449,31.6846],[108.2813,31.9043],[108.3691,32.168],[108.5449,32.2119],[109.0723,31.9482],[109.248,31.7285],[109.5996,31.7285],[109.7754,31.6846],[109.6875,31.5527],[110.127,31.377],[110.2148,31.1572],[110.0391,30.8057],[109.8633,30.8936],[109.4238,30.542],[109.248,30.6299],[109.1602,30.542],[109.0723,30.6299],[108.8086,30.498],[108.6328,30.5859],[108.457,30.4102],[108.5449,30.2344],[108.457,29.7949],[108.6328,29.8389],[108.9844,29.3115],[109.0723,29.3555],[109.248,29.1357],[109.248,28.4766],[109.0723,28.2129],[108.7207,28.2129],[108.7207,28.4766],[108.5449,28.3887],[108.5449,28.6523],[108.3691,28.6523],[108.2813,29.0918],[107.8418,29.0039],[107.8418,29.1357],[107.5781,29.2236],[107.4023,29.1797],[107.4023,28.8721],[106.875,28.7842],[106.6992,28.4766],[106.6113,28.5205],[106.6113,28.6523],[106.5234,28.7842],[106.4355,28.7842],[106.5234,28.5645],[106.3477,28.5205],[106.2598,28.8721],[105.8203,28.96],[105.7324,29.2676],[105.4688,29.3115],[105.293,29.5313],[105.7324,29.8828],[105.5566,30.1025],[105.6445,30.2783],[105.8203,30.4541],[106.2598,30.1904],[106.6113,30.3223],[106.7871,30.0146],[107.0508,30.0146],[107.4902,30.6299],[107.4023,30.7617],[107.4902,30.8496],[107.9297,30.8496],[108.1934,31.5088],[108.5449,31.6846]]]}},{"type":"Feature","id":"ning_xia","properties":{"name":"宁夏","cp":[105.9961,37.3096],"childNum":5},"geometry":{"type":"Polygon","coordinates":[[[104.3262,37.4414],[105.8203,37.793],[105.9082,38.7158],[106.3477,39.2871],[106.7871,39.375],[106.9629,38.9795],[106.5234,38.3203],[106.7871,38.1885],[107.3145,38.1006],[107.666,37.8809],[107.3145,37.6172],[107.3145,37.0898],[106.6113,37.0898],[106.6113,36.7822],[106.4355,36.5625],[106.5234,36.4746],[106.5234,36.2549],[106.875,36.123],[106.9629,35.8154],[106.6992,35.6836],[106.4355,35.6836],[106.5234,35.332],[106.3477,35.2441],[106.2598,35.4199],[106.084,35.376],[105.9961,35.4199],[106.084,35.4639],[105.9961,35.4639],[105.8203,35.5518],[105.7324,35.7275],[105.3809,35.7715],[105.293,35.9912],[105.4688,36.123],[105.2051,36.6943],[105.293,36.8262],[104.8535,37.2217],[104.5898,37.2217],[104.5898,37.4414],[104.3262,37.4414]]]}},{"type":"Feature","id":"hai_nan","properties":{"name":"海南","cp":[109.9512,19.2041],"childNum":18},"geometry":{"type":"Polygon","coordinates":[[[108.6328,19.3799],[109.0723,19.6436],[109.248,19.9512],[109.5996,20.0391],[110.0391,20.127],[110.3906,20.127],[110.5664,20.2588],[110.6543,20.2588],[111.0938,19.9512],[111.2695,19.9951],[110.6543,19.1602],[110.5664,18.6768],[110.2148,18.5889],[110.0391,18.3691],[109.8633,18.3691],[109.6875,18.1055],[108.9844,18.2813],[108.6328,18.457],[108.6328,19.3799]]]}},{"type":"Feature","id":"tai_wan","properties":{"name":"台湾","cp":[121.0254,23.5986],"childNum":1},"geometry":{"type":"Polygon","coordinates":[[[121.9043,25.0488],[121.9922,25.0049],[121.8164,24.7412],[121.9043,24.5654],[121.6406,24.0381],[121.377,23.1152],[121.0254,22.6758],[120.8496,22.0605],[120.7617,21.9287],[120.6738,22.3242],[120.2344,22.5879],[120.0586,23.0713],[120.1465,23.6865],[121.0254,25.0488],[121.5527,25.3125],[121.9043,25.0488]]]}},{"type":"Feature","id":"bei_jing","properties":{"name":"北京","cp":[116.4551,40.2539],"childNum":19},"geometry":{"type":"Polygon","coordinates":[[[117.4219,40.21],[117.334,40.1221],[117.2461,40.0781],[116.8066,39.9902],[116.8945,39.8145],[116.8945,39.6826],[116.8066,39.5947],[116.543,39.5947],[116.3672,39.4629],[116.1914,39.5947],[115.752,39.5068],[115.4883,39.6387],[115.4004,39.9463],[115.9277,40.2539],[115.752,40.5615],[116.1035,40.6055],[116.1914,40.7813],[116.4551,40.7813],[116.3672,40.9131],[116.6309,41.0449],[116.9824,40.6934],[117.4219,40.6494],[117.2461,40.5176],[117.4219,40.21]]]}},{"type":"Feature","id":"tian_jin","properties":{"name":"天津","cp":[117.4219,39.4189],"childNum":18},"geometry":{"type":"Polygon","coordinates":[[[116.8066,39.5947],[116.8945,39.6826],[117.1582,39.6387],[117.1582,39.8145],[117.2461,40.0781],[117.334,40.1221],[117.4219,40.21],[117.6855,40.0781],[117.6855,39.9902],[117.5098,39.9902],[117.5098,39.7705],[117.6855,39.5947],[117.9492,39.5947],[117.8613,39.4189],[118.0371,39.2432],[118.0371,39.1992],[117.8613,39.1113],[117.5977,38.6279],[117.2461,38.54],[116.7188,38.8037],[116.7188,38.9355],[116.8945,39.1113],[116.8066,39.5947]]]}},{"type":"Feature","id":"shang_hai","properties":{"name":"上海","cp":[121.4648,31.2891],"childNum":19},"geometry":{"type":"Polygon","coordinates":[[[120.9375,31.0254],[121.2012,31.4648],[121.377,31.5088],[121.1133,31.7285],[121.2012,31.8604],[121.9922,31.5967],[121.9043,31.1572],[121.9922,30.8057],[121.2891,30.6738],[120.9375,31.0254]]]}},{"type":"Feature","id":"xiang_gang","properties":{"name":"香港","cp":[114.2578,22.3242],"childNum":1},"geometry":{"type":"Polygon","coordinates":[[[114.6094,22.4121],[114.5215,22.1484],[114.3457,22.1484],[113.9063,22.1484],[113.8184,22.1924],[113.9063,22.4121],[114.1699,22.5439],[114.3457,22.5439],[114.4336,22.5439],[114.4336,22.4121],[114.6094,22.4121]]]}},{"type":"Feature","id":"ao_men","properties":{"name":"澳门","cp":[113.5547,22.1484],"childNum":1},"geometry":{"type":"Polygon","coordinates":[[[113.5986,22.1649],[113.6096,22.1265],[113.5547,22.11],[113.5437,22.2034],[113.5767,22.2034],[113.5986,22.1649]]]}}],"srcSize":{"left":243.4766,"top":36.4307,"width":61.6113,"height":35.4638}}
--------------------------------------------------------------------------------
/data/country-codes.csv:
--------------------------------------------------------------------------------
1 | euname,modified,linked_country,iso3,iso2,grc,isonum,country,imperitive
2 | ,,Georgia,,,ABK,,Abkhazia,De Facto; Currency
3 | AFGHANISTAN,,,AFG,AF,AFG,004,Afghanistan,
4 | ,Added 26th October 2010,Finland,ALA,AX,ALA,248,Åland Islands,Postal
5 | Albania,,,ALB,AL,ALB,008,Albania,
6 | ALGERIA,,,DZA,DZ,ALG,012,Algeria,
7 | ,,United States of America,ASM,AS,AMS,016,American Samoa,Geographical
8 | ANDORRA,,,AND,AD,AND,020,Andorra,
9 | ANGOLA,,,AGO,AO,ANG,024,Angola,
10 | ,,United Kingdom,AIA,AI,ANU,660,Anguilla,Geographical; Postal; Currency; Telephone
11 | ANTIGUA AND BARBUDA,,,ATG,AG,ANT,028,Antigua & Barbuda,
12 | Argentina,,,ARG,AR,ARG,032,Argentina,
13 | Armenia,,,ARM,AM,ARM,051,Armenia,
14 | ARUBA,,Netherlands,ABW,AW,ARU,533,Aruba,Geographical; Postal; Currency; Telephone
15 | Australia,,,AUS,AU,AST,036,Australia,
16 | Austria,,,AUT,AT,AUS,040,Austria,
17 | AZERBAIJAN,,,AZE,AZ,AZE,031,Azerbaijan,
18 | BAHAMAS,,,BHS,BS,BAH,044,Bahamas,
19 | BAHRAIN,,,BHR,BH,BAR,048,Bahrain,
20 | BANGLADESH,,,BGD,BD,BAN,050,Bangladesh,
21 | Barbados,,,BRB,BB,BAB,052,Barbados,
22 | BELARUS,,,BLR,BY,BEO,112,Belarus,
23 | Belgium,,,BEL,BE,BEL,056,Belgium,
24 | BELIZE,,,BLZ,BZ,BEI,084,Belize,
25 | Benin,,,BEN,BJ,BEN,204,Benin,
26 | ,,United Kingdom,BMU,BM,BER,060,Bermuda,Geographical; Postal; Currency; Telephone
27 | BHUTAN,,,BTN,BT,BHU,064,Bhutan,
28 | BOLIVIA,,,BOL,BO,BOL,068,Bolivia,
29 | ,ISO codes added 28th Dec. 2010,Netherlands,BES,BQ,BON,535,Bonaire,Geographical; Postal; Currency; Telephone
30 | Bosnia-Herzegovina,,,BIH,BA,BOS,070,Bosnia-Herzegovina,
31 | BOTSWANA,,,BWA,BW,BOT,072,Botswana,
32 | Brazil,,,BRA,BR,BRA,076,Brazil,
33 | ,,"United Kingdom, United States of America",IOT,IO,BIO,086,British Indian Ocean Territory,Geographical; Postal; Telephone
34 | British Virgin Islands,,United Kingdom,VGB,VG,BVI,092,British Virgin Islands,Geographical; Postal; Currency; Telephone
35 | BRUNEI,,,BRN,BN,BRU,096,Brunei Darussalam,
36 | Bulgaria,,,BGR,BG,BUL,100,Bulgaria,
37 | BURKINA FASO,,,BFA,BF,BUK,854,Burkina Faso,
38 | BURUNDI,,,BDI,BI,BUU,108,Burundi,
39 | Cambodia,,,KHM,KH,CAM,116,Cambodia,
40 | Cameroon,,,CMR,CM,CAE,120,Cameroon,
41 | Canada,,,CAN,CA,CAN,124,Canada,
42 | CAPE VERDE,,,CPV,CV,CAP,132,Cape Verde Islands,
43 | ,,United Kingdom,CYM,KY,CAY,136,Cayman Islands,Geographical; Postal; Currency; Telephone
44 | "CENTRAL AFRICAN, REPUBLIC",,,CAF,CF,CEN,140,Central African Republic,
45 | Chad,,,TCD,TD,CHA,148,Chad,
46 | CHILE,,,CHL,CL,CHI,152,Chile,
47 | CHINA,,,CHN,CN,CHN,156,China,
48 | ,,Australia,CXR,CX,CHR,162,Christmas Island,Geographical
49 | ,,Australia,CCK,CC,COC,166,Cocos (Keeling) Islands,Geographical
50 | Colombia,,,COL,CO,CLO,170,Colombia,
51 | COMOROS,,,COM,KM,COM,174,Comoros,
52 | CONGO,,,COG,CG,CNG,178,Congo (Brazzaville),
53 | "CONGO, DEMOCRATIC REPUBLIC OF",,,ZAR,CD,ZAI,180,Congo (Kinshasa),
54 | COOK ISLANDS,,New Zealand,COK,CK,COO,184,Cook Islands,Geographical; Postal; Telephone
55 | Costa Rica,,,CRI,CR,COS,188,Costa Rica,
56 | Croatia,,,HRV,HR,CRO,191,Croatia,
57 | CUBA,,,CUB,CU,CUB,192,Cuba,
58 | ,ISO codes added 28th Dec. 2010,Netherlands,CUW,CW,CUR,531,Curaçao,Geographical; Postal; Currency; Telephone
59 | Cyprus,,,CYP,CY,CYP,196,Cyprus,
60 | Czech Republic,,,CZE,CZ,CZE,203,Czech Republic,
61 | Denmark,,,DNK,DK,DEN,208,Denmark,
62 | DJIBOUTI,,,DJI,DJ,DJI,262,Djibouti,
63 | DOMINIQUE,,,DMA,DM,DOI,212,Dominica,
64 | Dominican Republic,,,DOM,DO,DOM,214,Dominican Republic,
65 | EAST TIMOR,,,TLS,TL,ETI,626,East Timor,
66 | Ecuador,,,ECU,EC,ECU,218,Ecuador,
67 | EGYPT,,,EGY,EG,EGY,818,Egypt,
68 | El Salvador,,,SLV,SV,ELS,222,El Salvador,
69 | EQUATORIAL GUINEA,,,GNQ,GQ,EQA,226,Equatorial Guinea,
70 | ERITREA,,,ERI,ER,ERI,232,Eritrea,
71 | Estonia,,,EST,EE,EST,233,Estonia,
72 | ETHIOPIA,,,ETH,ET,ETH,231,Ethiopia,
73 | FAROE ISLANDS,,,FRO,FO,FAE,234,Faeroe Islands,
74 | ,,United Kingdom,FLK,FK,FAL,238,Falkland Islands,Geographical; Postal; Currency; Telephone
75 | FIJI,,,FJI,FJ,FIJ,242,Fiji,
76 | Finland,,,FIN,FI,FIN,246,Finland,
77 | France,,,FRA,FR,FRA,250,France,
78 | FRENCH GUYANA,,France,GUF,GF,FGU,254,French Guiana,Geographical; Telephone
79 | FRENCH POLYNESIA,Corrected 13th November 2010,France,PYF,PF,FPO,258,French Polynesia,Geographical; Currency; Telephone
80 | ,,France,ATF,TF,FST,260,French Southern Territories,Geographical; Postal; Telephone
81 | GABON,,,GAB,GA,GAB,266,Gabon,
82 | GAMBIA,,,GMB,GM,GAM,270,Gambia,
83 | GEORGIA,,,GEO,GE,GEO,268,Georgia,
84 | Germany,,,DEU,DE,GER,276,Germany,
85 | Ghana,,,GHA,GH,GHA,288,Ghana,
86 | GIBRALTAR,,United Kingdom,GIB,GI,GIB,292,Gibralter,Geographical; Postal; Currency; Telephone
87 | Greece,,,GRC,GR,GRE,300,Greece,
88 | GREENLAND,,Denmark,GRL,GL,GRN,304,Greenland,Geographical; Postal; Telephone
89 | GRENADA,,,GRD,GD,GRA,308,Grenada,
90 | GUADELOUPE,,France,GLP,GP,GUD,312,Guadeloupe,Geographical; Postal; Telephone
91 | ,,United States of America,GUM,GU,GUM,316,Guam,Geographical
92 | Guatemala,,,GTM,GT,GUA,320,Guatemala,
93 | ,,United Kingdom,GGY,GG,GUE,831,Guernsey,Postal
94 | Guinea,,,GIN,GN,GUI,324,Guinea,
95 | GUINEA BISSAU,,,GNB,GW,GUB,624,Guinea-Bissau,
96 | GUYANA,,,GUY,GY,GUY,328,Guyana,
97 | HAITI,,,HTI,HT,HAI,332,Haiti,
98 | HOLY SEE (VATICAN CITY STATE),,,VAT,VA,VAT,336,Holy See,
99 | Honduras,,,HND,HN,HON,340,Honduras,
100 | Hong Kong,,China,HKG,HK,HOK,344,Hong Kong,Postal; Currency; Telephone
101 | Hungary,,,HUN,HU,HUN,348,Hungary,
102 | Iceland,,,ISL,IS,ICE,352,Iceland,
103 | India,,,IND,IN,IND,356,India,
104 | INDONESIA,,,IDN,ID,INO,360,Indonesia,
105 | "IRAN, ISLAMIC REPUBLIC OF",,,IRN,IR,IRA,364,Iran,
106 | IRAQ,,,IRQ,IQ,IRQ,368,Iraq,
107 | Ireland,,,IRL,IE,IRE,372,Ireland,
108 | ,,United Kingdom,IMN,IM,ISL,833,Isle of Man,Postal
109 | Israel,,,ISR,IL,ISR,376,Israel,
110 | Italy,,,ITA,IT,ITA,380,Italy,
111 | COTE D'IVOIRE,,,CIV,CI,IVO,384,Ivory Coast,
112 | Jamaica,,,JAM,JM,JAM,388,Jamaica,
113 | Japan,,,JPN,JP,JAP,392,Japan,
114 | JERSEY,,United Kingdom,JEY,JE,JER,832,Jersey,Postal
115 | JORDAN,,,JOR,JO,JOR,400,Jordan,
116 | KAZAKHSTAN,,,KAZ,KZ,KAZ,398,Kazakhstan,
117 | Kenya,,,KEN,KE,KEN,404,Kenya,
118 | KIRIBATI,,,KIR,KI,KII,296,Kiribati,
119 | ,,Serbia,,,KOS,,Kosovo,Postal; Currency; Telephone
120 | KUWAIT,,,KWT,KW,KUW,414,Kuwait,
121 | KYRGYZSTAN,,,KGZ,KG,KIR,417,Kyrgyzstan,
122 | "LAOS, PEOPLE'S DEMOCRATIC REPUBLIC",,,LAO,LA,LAO,418,Laos,
123 | Latvia,,,LVA,LV,LAT,428,Latvia,
124 | LEBANON,,,LBN,LB,LEB,422,Lebanon,
125 | LESOTHO,,,LSO,LS,LES,426,Lesotho,
126 | LIBERIA,,,LBR,LR,LIR,430,Liberia,
127 | LIBYA,,,LBY,LY,LIB,434,Libya,
128 | LIECHTENSTEIN,,,LIE,LI,LIE,438,Liechtenstein,
129 | LITUANIA,,,LTU,LT,LIT,440,Lithuania,
130 | Luxembourg,,,LUX,LU,LUX,442,Luxembourg,
131 | MACAO,,China,MAC,MO,MCA,446,Macau,Postal; Currency; Telephone
132 | "MACEDONIA, FORMER YUGOSLAV REPUBLIC OF",,,MKD,MK,MCE,807,Macedonia,
133 | MADAGASCAR,,,MDG,MG,MAD,450,Madagascar,
134 | MALAWI,,,MWI,MW,MAW,454,Malawi,
135 | Malaysia,,,MYS,MY,MAA,458,Malaysia,
136 | MALDIVES,,,MDV,MV,MAV,462,Maldives,
137 | MALI,,,MLI,ML,MAI,466,Mali,
138 | Malta,,,MLT,MT,MAL,470,Malta,
139 | MARSHALL ISLANDS,,,MHL,MH,MAR,584,Marshall Islands,
140 | MARTINIQUE,,France,MTQ,MQ,MAN,474,Martinique,Geographical; Postal; Telephone
141 | Mauritania,,,MRT,MR,MAU,478,Mauritania,
142 | MAURITIUS,,,MUS,MU,MAT,480,Mauritius,
143 | MAYOTTE,,France,MYT,YT,MAY,175,Mayotte,Geographical; Postal; Telephone
144 | Mexico,,,MEX,MX,MEX,484,Mexico,
145 | "MICRONESIA, FEDERATED STATES OF",,,FSM,FM,MIC,583,Micronesia,
146 | "MOLDOVA, REPUBLIC OF",,,MDA,MD,MOL,498,Moldova,
147 | Monaco,,,MCO,MC,MON,492,Monaco,
148 | MONGOLIA,,,MNG,MN,MOG,496,Mongolia,
149 | Montenegro,,,MNE,ME,MOE,499,Montenegro,
150 | ,,United Kingdom,MSR,MS,MOT,500,Montserrat,Geographical; Postal; Currency; Telephone
151 | Morocco,,,MAR,MA,MOR,504,Morocco,
152 | Mozambique,,,MOZ,MZ,MOZ,508,Mozambique,
153 | Myanmar,,,MMR,MM,BUR,104,Myanmar,
154 | ,,Azerbaijan,,,NAG,,Nagorno-Karabakh,De Facto
155 | NAMIBIA,,,NAM,NA,NAM,516,Namibia,
156 | NAURU,,,NRU,NR,NAU,520,Nauru,
157 | NEPAL,,,NPL,NP,NEP,524,Nepal,
158 | Netherlands Antilles,,,ANT,AN,NAN,530,Netherlands Antilles,Legacy
159 | Netherlands,,,NLD,NL,NET,528,Netherlands,
160 | NEW CALEDONIA,,France,NCL,NC,NCA,540,New Caledonia,Geographical; Postal; Currency; Telephone
161 | NEW ZEALAND,,,NZL,NZ,NEW,554,New Zealand,
162 | Nicaragua,,,NIC,NI,NIC,558,Nicaragua,
163 | Niger,,,NER,NE,NIE,562,Niger,
164 | Nigeria,,,NGA,NG,NIG,566,Nigeria,
165 | NIUE,,,NIU,NU,NIU,570,Niue,
166 | ,,Australia,NFK,NF,NOF,574,Norfolk Island,Geographical; Telephone
167 | "KOREA, PEOPLE'S DEMOCRATIC REPUBLIC OF",,,PRK,KP,NKO,408,North Korea,
168 | ,,Cyprus,,,NCY,,Northern Cyprus,De Facto; Postal; Currency; Telephone
169 | ,,United States of America,MNP,MP,NMI,580,Northern Mariana Islands,Geographical
170 | Norway,,,NOR,NO,NOR,578,Norway,
171 | OMAN,,,OMN,OM,OMA,512,Oman,
172 | Pakistan,,,PAK,PK,PAK,586,Pakistan,
173 | PALAU,,,PLW,PW,PAL,585,Palau,
174 | PALESTINIAN OCCUPIED TERRITORY,,Israel,PSE,PS,PLA,275,Palestinian Territories,
175 | PANAMA,,,PAN,PA,PAN,591,Panama,
176 | PAPUA NEW GUINEA,,,PNG,PG,PAP,598,Papua New Guinea,
177 | PARAGUAY,,,PRY,PY,PAR,600,Paraguay,
178 | PERU,,,PER,PE,PER,604,Peru,
179 | Philippines,,,PHL,PH,PHI,608,Philippines,
180 | ,,United Kingdom,PCN,PN,PIT,612,Pitcairn Islands,Geographical; Postal; Currency; Telephone
181 | Poland,,,POL,PL,POL,616,Poland,
182 | Portugal,,,PRT,PT,POR,620,Portugal,
183 | PUERTO RICO,,United States,PRI,PR,PUE,630,Puerto Rico,Geographical
184 | ,,Somalia,,,PUN,,Puntland,De Facto
185 | QATAR,,,QAT,QA,QAT,634,Qatar,
186 | Romania,,,ROU,RO,ROM,642,Romania,
187 | "RUSSIA, FEDERATION OF",,,RUS,RU,RUS,643,Russia,
188 | RUANDA,,,RWA,RW,RWA,646,Rwanda,
189 | REUNION,,France,REU,RE,REU,638,Réunion,Geographical; Postal; Currency; Telephone
190 | ,ISO codes added 28th Dec. 2010,The Netherlands,BES,BQ,SAB,535,Saba,Geographical; Postal; Currency; Telephone
191 | ,,France,BLM,BL,STB,652,Saint Barthélemy,Geographical; Postal; Currency; Telephone
192 | SAINT KITTS AND NEVIS,,,KNA,KN,STC,659,Saint Christopher & Nevis,
193 | ,,United Kingdom,SHN,SH,STH,654,Saint Helena,Geographical; Postal; Currency; Telephone
194 | SAINT LUCIA,,,LCA,LC,STL,662,Saint Lucia,
195 | ,,France,MAF,MF,STM,663,Saint Martin,Geographical; Postal; Currency; Telephone
196 | ,,France,SPM,PM,SPM,666,Saint Pierre & Miquelon,Geographical; Postal; Currency; Telephone
197 | SAINT VINCENT AND THE GRENADINES,,,VCT,VC,STV,670,Saint Vincent & The Grenadines,
198 | SAMOA,,,WSM,WS,WSM,882,Samoa,
199 | SAINT MARINO,,,SMR,SM,SAN,674,San Marino,
200 | SAO TOME AND PRINCIPE,,,STP,ST,SAO,678,Sao Tome & Principe,
201 | SUADI ARABIA,,,SAU,SA,SAU,682,Saudi Arabia,
202 | Senegal,,,SEN,SN,SEN,686,Senegal,
203 | Serbia,,,SRB,RS,YUG,688,Serbia,
204 | SEYCHELLES,,,SYC,SC,SEY,690,Seychelles,
205 | SIERRA LEONE,,,SLE,SL,SIE,694,Sierra Leone,
206 | SINGAPORE,,,SGP,SG,SIN,702,Singapore,
207 | ,ISO codes added 28th Dec. 2010,The Netherlands,BES,BQ,STE,535,Sint Eustatius,Geographical; Postal; Currency; Telephone
208 | ,ISO codes added 28th Dec. 2010,The Netherlands,SXM,SX,SMA,534,Sint Maarten,Geographical; Postal; Currency; Telephone
209 | Slovakia,,,SVK,SK,SLO,703,Slovakia,
210 | Slovenia,,,SVN,SI,SLV,705,Slovenia,
211 | SOLOMON ISLANDS,,,SLB,SB,SOL,090,Solomon Islands,
212 | SOMALIA,,,SOM,SO,SOM,706,Somalia,
213 | ,,Somalia,SOM,SO,SOA,706,Somaliland,De Facto
214 | South Africa,,,ZAF,ZA,SAF,710,South Africa,
215 | ,,United Kingdom,SGS,GS,SGE,239,South Georgia & The South Sandwish Islands,Geographical; Postal; Currency; Telephone
216 | "KOREA, REPUBLIC OF",,,KOR,KR,SKO,418,South Korea,
217 | ,,Georgia,,,SOS,,South Ossetia,De Facto; Currency
218 | SOUTH SUDAN,Added 22nd February 2011. ISO codes added 18th August 2011.,,SSD,SS,SSU,,South Sudan,
219 | Spain,,,ESP,ES,SPA,724,Spain,
220 | SRI LANKA,,,LKA,LK,SRI,144,Sri Lanka,
221 | Sudan,,,SDN,SD,SUD,736,Sudan,
222 | SURINAM,,,SUR,SR,SUR,740,Suriname,
223 | SWAZILAND,,,SWZ,SZ,SWA,748,Swaziland,
224 | Sweden,,,SWE,SE,SWE,752,Sweden,
225 | Switzerland,,,CHE,CH,SWI,756,Switzerland,
226 | "SYRIA, ARAB REPUBLIC",,,SYR,SY,SYR,760,Syria,
227 | TAIWAN,,China,TWN,TW,TAI,158,Taiwan,
228 | TAJIKISTAN,,,TJK,TJ,TAJ,762,Tajikistan,
229 | "TANZANIA, UNITED RE UBLIC OF",,,TZA,TZ,TAN,834,Tanzania,
230 | THAILAND,,,THA,TH,THA,764,Thailand,
231 | TOGO,,,TGO,TG,TOG,768,Togo,
232 | ,,New Zealand,TKL,TK,TOK,772,Tokelau,Geographical; Postal; Telephone
233 | TONGA,,,TON,TO,TON,776,Tonga,
234 | ,,Moldova,,,TRA,,Transdniestria,De Facto
235 | TRINIDAD AND TOBAGO,,,TTO,TT,TRI,780,Trinidad & Tobago,
236 | Tunisia,,,TUN,TN,TUN,788,Tunisia,
237 | Turkey,,,TUR,TR,TUR,792,Turkey,
238 | TURKMENISTAN,,,TKM,TM,TUK,795,Turkmenistan,
239 | ,,United Kingdom,TCA,TC,TUC,796,Turks & Caicos Islands,Geographical; Postal; Currency; Telephone
240 | TUVALU,,,TUV,TV,TUV,798,Tuvalu,
241 | Uganda,,,UGA,UG,UGA,800,Uganda,
242 | Ukraine,,,UKR,UA,UKR,804,Ukraine,
243 | United Arab Emirates,,,ARE,AE,UAE,784,United Arab Emirates,
244 | United Kingdom,,,GBR,GB,UNI,826,United Kingdom,
245 | United States,,,USA,US,USA,840,United States,
246 | US VIRGIN ISLANDS,,United States of America,VIR,VI,VIR,850,United States Virgin Islands,Geographical
247 | URUGUAY,,,URY,UY,URU,858,Uruguay,
248 | UZBEKISTAN,,,UZB,UZ,UZB,860,Uzbekistan,
249 | VANUATU,,,VUT,VU,VAN,548,Vanuatu,
250 | VENEZUELA,,,VEN,VE,VEN,862,Venezuela,
251 | VIETNAM,,,VNM,VN,VIE,704,Vietnam,
252 | ,,France,WLF,WF,WAL,876,Wallis & Futuna,Geographical; Postal; Currency; Telephone
253 | WESTERN SAHARA,,Morocco,ESH,EH,WSA,732,Western Sahara,Political
254 | Yemen,,,YEM,YE,YEM,887,Yemen,
255 | ZAMBIA,,,ZMB,ZM,ZAM,894,Zambia,
256 | ZIMBABWE,,,ZWE,ZW,ZIM,716,Zimbabwe,
257 |
--------------------------------------------------------------------------------
/flags.css:
--------------------------------------------------------------------------------
1 | .f16 .flag{display:inline-block;height:16px;width:16px;vertical-align:text-top;line-height:16px;background:url(images/flags/flags16.png) no-repeat;}
2 | .f16 ._African_Union{background-position:0 -16px;}
3 | .f16 ._Arab_League{background-position:0 -32px;}
4 | .f16 ._ASEAN{background-position:0 -48px;}
5 | .f16 ._CARICOM{background-position:0 -64px;}
6 | .f16 ._CIS{background-position:0 -80px;}
7 | .f16 ._Commonwealth{background-position:0 -96px;}
8 | .f16 ._England{background-position:0 -112px;}
9 | .f16 ._European_Union, .f16 .eu{background-position:0 -128px;}
10 | .f16 ._Islamic_Conference{background-position:0 -144px;}
11 | .f16 ._Kosovo{background-position:0 -160px;}
12 | .f16 ._NATO{background-position:0 -176px;}
13 | .f16 ._Northern_Cyprus{background-position:0 -192px;}
14 | .f16 ._Northern_Ireland{background-position:0 -208px;}
15 | .f16 ._Olimpic_Movement{background-position:0 -224px;}
16 | .f16 ._OPEC{background-position:0 -240px;}
17 | .f16 ._Red_Cross{background-position:0 -256px;}
18 | .f16 ._Scotland{background-position:0 -272px;}
19 | .f16 ._Somaliland{background-position:0 -288px;}
20 | .f16 ._Tibet{background-position:0 -304px;}
21 | .f16 ._United_Nations{background-position:0 -320px;}
22 | .f16 ._Wales{background-position:0 -336px;}
23 | .f16 .ad{background-position:0 -352px;}
24 | .f16 .ae{background-position:0 -368px;}
25 | .f16 .af{background-position:0 -384px;}
26 | .f16 .ag{background-position:0 -400px;}
27 | .f16 .ai{background-position:0 -416px;}
28 | .f16 .al{background-position:0 -432px;}
29 | .f16 .am{background-position:0 -448px;}
30 | .f16 .ao{background-position:0 -464px;}
31 | .f16 .aq{background-position:0 -480px;}
32 | .f16 .ar{background-position:0 -496px;}
33 | .f16 .as{background-position:0 -512px;}
34 | .f16 .at{background-position:0 -528px;}
35 | .f16 .au{background-position:0 -544px;}
36 | .f16 .aw{background-position:0 -560px;}
37 | .f16 .ax{background-position:0 -576px;}
38 | .f16 .az{background-position:0 -592px;}
39 | .f16 .ba{background-position:0 -608px;}
40 | .f16 .bb{background-position:0 -624px;}
41 | .f16 .bd{background-position:0 -640px;}
42 | .f16 .be{background-position:0 -656px;}
43 | .f16 .bf{background-position:0 -672px;}
44 | .f16 .bg{background-position:0 -688px;}
45 | .f16 .bh{background-position:0 -704px;}
46 | .f16 .bi{background-position:0 -720px;}
47 | .f16 .bj{background-position:0 -736px;}
48 | .f16 .bm{background-position:0 -752px;}
49 | .f16 .bn{background-position:0 -768px;}
50 | .f16 .bo{background-position:0 -784px;}
51 | .f16 .br{background-position:0 -800px;}
52 | .f16 .bs{background-position:0 -816px;}
53 | .f16 .bt{background-position:0 -832px;}
54 | .f16 .bw{background-position:0 -848px;}
55 | .f16 .by{background-position:0 -864px;}
56 | .f16 .bz{background-position:0 -880px;}
57 | .f16 .ca{background-position:0 -896px;}
58 | .f16 .cg{background-position:0 -912px;}
59 | .f16 .cf{background-position:0 -928px;}
60 | .f16 .cd{background-position:0 -944px;}
61 | .f16 .ch{background-position:0 -960px;}
62 | .f16 .ci{background-position:0 -976px;}
63 | .f16 .ck{background-position:0 -992px;}
64 | .f16 .cl{background-position:0 -1008px;}
65 | .f16 .cm{background-position:0 -1024px;}
66 | .f16 .cn{background-position:0 -1040px;}
67 | .f16 .co{background-position:0 -1056px;}
68 | .f16 .cr{background-position:0 -1072px;}
69 | .f16 .cu{background-position:0 -1088px;}
70 | .f16 .cv{background-position:0 -1104px;}
71 | .f16 .cy{background-position:0 -1120px;}
72 | .f16 .cz{background-position:0 -1136px;}
73 | .f16 .de{background-position:0 -1152px;}
74 | .f16 .dj{background-position:0 -1168px;}
75 | .f16 .dk{background-position:0 -1184px;}
76 | .f16 .dm{background-position:0 -1200px;}
77 | .f16 .do{background-position:0 -1216px;}
78 | .f16 .dz{background-position:0 -1232px;}
79 | .f16 .ec{background-position:0 -1248px;}
80 | .f16 .ee{background-position:0 -1264px;}
81 | .f16 .eg{background-position:0 -1280px;}
82 | .f16 .eh{background-position:0 -1296px;}
83 | .f16 .er{background-position:0 -1312px;}
84 | .f16 .es{background-position:0 -1328px;}
85 | .f16 .et{background-position:0 -1344px;}
86 | .f16 .fi{background-position:0 -1360px;}
87 | .f16 .fj{background-position:0 -1376px;}
88 | .f16 .fm{background-position:0 -1392px;}
89 | .f16 .fo{background-position:0 -1408px;}
90 | .f16 .fr{background-position:0 -1424px;} .f16 .bl, .f16 .cp, .f16 .mf, .f16 .yt{background-position:0 -1424px;}
91 | .f16 .ga{background-position:0 -1440px;}
92 | .f16 .gb{background-position:0 -1456px;} .f16 .sh{background-position:0 -1456px;}
93 | .f16 .gd{background-position:0 -1472px;}
94 | .f16 .ge{background-position:0 -1488px;}
95 | .f16 .gg{background-position:0 -1504px;}
96 | .f16 .gh{background-position:0 -1520px;}
97 | .f16 .gi{background-position:0 -1536px;}
98 | .f16 .gl{background-position:0 -1552px;}
99 | .f16 .gm{background-position:0 -1568px;}
100 | .f16 .gn{background-position:0 -1584px;}
101 | .f16 .gp{background-position:0 -1600px;}
102 | .f16 .gq{background-position:0 -1616px;}
103 | .f16 .gr{background-position:0 -1632px;}
104 | .f16 .gt{background-position:0 -1648px;}
105 | .f16 .gu{background-position:0 -1664px;}
106 | .f16 .gw{background-position:0 -1680px;}
107 | .f16 .gy{background-position:0 -1696px;}
108 | .f16 .hk{background-position:0 -1712px;}
109 | .f16 .hn{background-position:0 -1728px;}
110 | .f16 .hr{background-position:0 -1744px;}
111 | .f16 .ht{background-position:0 -1760px;}
112 | .f16 .hu{background-position:0 -1776px;}
113 | .f16 .id{background-position:0 -1792px;}
114 | .f16 .mc{background-position:0 -1792px;}
115 | .f16 .ie{background-position:0 -1808px;}
116 | .f16 .il{background-position:0 -1824px;}
117 | .f16 .im{background-position:0 -1840px;}
118 | .f16 .in{background-position:0 -1856px;}
119 | .f16 .iq{background-position:0 -1872px;}
120 | .f16 .ir{background-position:0 -1888px;}
121 | .f16 .is{background-position:0 -1904px;}
122 | .f16 .it{background-position:0 -1920px;}
123 | .f16 .je{background-position:0 -1936px;}
124 | .f16 .jm{background-position:0 -1952px;}
125 | .f16 .jo{background-position:0 -1968px;}
126 | .f16 .jp{background-position:0 -1984px;}
127 | .f16 .ke{background-position:0 -2000px;}
128 | .f16 .kg{background-position:0 -2016px;}
129 | .f16 .kh{background-position:0 -2032px;}
130 | .f16 .ki{background-position:0 -2048px;}
131 | .f16 .km{background-position:0 -2064px;}
132 | .f16 .kn{background-position:0 -2080px;}
133 | .f16 .kp{background-position:0 -2096px;}
134 | .f16 .kr{background-position:0 -2112px;}
135 | .f16 .kw{background-position:0 -2128px;}
136 | .f16 .ky{background-position:0 -2144px;}
137 | .f16 .kz{background-position:0 -2160px;}
138 | .f16 .la{background-position:0 -2176px;}
139 | .f16 .lb{background-position:0 -2192px;}
140 | .f16 .lc{background-position:0 -2208px;}
141 | .f16 .li{background-position:0 -2224px;}
142 | .f16 .lk{background-position:0 -2240px;}
143 | .f16 .lr{background-position:0 -2256px;}
144 | .f16 .ls{background-position:0 -2272px;}
145 | .f16 .lt{background-position:0 -2288px;}
146 | .f16 .lu{background-position:0 -2304px;}
147 | .f16 .lv{background-position:0 -2320px;}
148 | .f16 .ly{background-position:0 -2336px;}
149 | .f16 .ma{background-position:0 -2352px;}
150 | .f16 .md{background-position:0 -2368px;}
151 | .f16 .me{background-position:0 -2384px;}
152 | .f16 .mg{background-position:0 -2400px;}
153 | .f16 .mh{background-position:0 -2416px;}
154 | .f16 .mk{background-position:0 -2432px;}
155 | .f16 .ml{background-position:0 -2448px;}
156 | .f16 .mm{background-position:0 -2464px;}
157 | .f16 .mn{background-position:0 -2480px;}
158 | .f16 .mo{background-position:0 -2496px;}
159 | .f16 .mq{background-position:0 -2512px;}
160 | .f16 .mr{background-position:0 -2528px;}
161 | .f16 .ms{background-position:0 -2544px;}
162 | .f16 .mt{background-position:0 -2560px;}
163 | .f16 .mu{background-position:0 -2576px;}
164 | .f16 .mv{background-position:0 -2592px;}
165 | .f16 .mw{background-position:0 -2608px;}
166 | .f16 .mx{background-position:0 -2624px;}
167 | .f16 .my{background-position:0 -2640px;}
168 | .f16 .mz{background-position:0 -2656px;}
169 | .f16 .na{background-position:0 -2672px;}
170 | .f16 .nc{background-position:0 -2688px;}
171 | .f16 .ne{background-position:0 -2704px;}
172 | .f16 .ng{background-position:0 -2720px;}
173 | .f16 .ni{background-position:0 -2736px;}
174 | .f16 .nl{background-position:0 -2752px;} .f16 .bq{background-position:0 -2752px;}
175 | .f16 .no{background-position:0 -2768px;} .f16 .bv, .f16 .nq, .f16 .sj{background-position:0 -2768px;}
176 | .f16 .np{background-position:0 -2784px;}
177 | .f16 .nr{background-position:0 -2800px;}
178 | .f16 .nz{background-position:0 -2816px;}
179 | .f16 .om{background-position:0 -2832px;}
180 | .f16 .pa{background-position:0 -2848px;}
181 | .f16 .pe{background-position:0 -2864px;}
182 | .f16 .pf{background-position:0 -2880px;}
183 | .f16 .pg{background-position:0 -2896px;}
184 | .f16 .ph{background-position:0 -2912px;}
185 | .f16 .pk{background-position:0 -2928px;}
186 | .f16 .pl{background-position:0 -2944px;}
187 | .f16 .pr{background-position:0 -2960px;}
188 | .f16 .ps{background-position:0 -2976px;}
189 | .f16 .pt{background-position:0 -2992px;}
190 | .f16 .pw{background-position:0 -3008px;}
191 | .f16 .py{background-position:0 -3024px;}
192 | .f16 .qa{background-position:0 -3040px;}
193 | .f16 .re{background-position:0 -3056px;}
194 | .f16 .ro{background-position:0 -3072px;}
195 | .f16 .rs{background-position:0 -3088px;}
196 | .f16 .ru{background-position:0 -3104px;}
197 | .f16 .rw{background-position:0 -3120px;}
198 | .f16 .sa{background-position:0 -3136px;}
199 | .f16 .sb{background-position:0 -3152px;}
200 | .f16 .sc{background-position:0 -3168px;}
201 | .f16 .sd{background-position:0 -3184px;}
202 | .f16 .se{background-position:0 -3200px;}
203 | .f16 .sg{background-position:0 -3216px;}
204 | .f16 .si{background-position:0 -3232px;}
205 | .f16 .sk{background-position:0 -3248px;}
206 | .f16 .sl{background-position:0 -3264px;}
207 | .f16 .sm{background-position:0 -3280px;}
208 | .f16 .sn{background-position:0 -3296px;}
209 | .f16 .so{background-position:0 -3312px;}
210 | .f16 .sr{background-position:0 -3328px;}
211 | .f16 .st{background-position:0 -3344px;}
212 | .f16 .sv{background-position:0 -3360px;}
213 | .f16 .sy{background-position:0 -3376px;}
214 | .f16 .sz{background-position:0 -3392px;}
215 | .f16 .tc{background-position:0 -3408px;}
216 | .f16 .td{background-position:0 -3424px;}
217 | .f16 .tg{background-position:0 -3440px;}
218 | .f16 .th{background-position:0 -3456px;}
219 | .f16 .tj{background-position:0 -3472px;}
220 | .f16 .tl{background-position:0 -3488px;}
221 | .f16 .tm{background-position:0 -3504px;}
222 | .f16 .tn{background-position:0 -3520px;}
223 | .f16 .to{background-position:0 -3536px;}
224 | .f16 .tr{background-position:0 -3552px;}
225 | .f16 .tt{background-position:0 -3568px;}
226 | .f16 .tv{background-position:0 -3584px;}
227 | .f16 .tw{background-position:0 -3600px;}
228 | .f16 .tz{background-position:0 -3616px;}
229 | .f16 .ua{background-position:0 -3632px;}
230 | .f16 .ug{background-position:0 -3648px;}
231 | .f16 .us{background-position:0 -3664px;}
232 | .f16 .uy{background-position:0 -3680px;}
233 | .f16 .uz{background-position:0 -3696px;}
234 | .f16 .va{background-position:0 -3712px;}
235 | .f16 .vc{background-position:0 -3728px;}
236 | .f16 .ve{background-position:0 -3744px;}
237 | .f16 .vg{background-position:0 -3760px;}
238 | .f16 .vi{background-position:0 -3776px;}
239 | .f16 .vn{background-position:0 -3792px;}
240 | .f16 .vu{background-position:0 -3808px;}
241 | .f16 .ws{background-position:0 -3824px;}
242 | .f16 .ye{background-position:0 -3840px;}
243 | .f16 .za{background-position:0 -3856px;}
244 | .f16 .zm{background-position:0 -3872px;}
245 | .f16 .zw{background-position:0 -3888px;}
246 | .f16 .sx{background-position:0 -3904px;}
247 | .f16 .cw{background-position:0 -3920px;}
248 | .f16 .ss{background-position:0 -3936px;}
249 | .f16 .o1{background-position:0 -3952px;}
--------------------------------------------------------------------------------
/fonts.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Norse-Mapcons';
3 | src:url('fonts/Norse-Mapcons.eot?m6qc03');
4 | src:url('fonts/Norse-Mapcons.eot?#iefixm6qc03') format('embedded-opentype'),
5 | url('fonts/Norse-Mapcons.woff?m6qc03') format('woff'),
6 | url('fonts/Norse-Mapcons.ttf?m6qc03') format('truetype'),
7 | url('fonts/Norse-Mapcons.svg?m6qc03#Norse-Mapcons') format('svg');
8 | font-weight: normal;
9 | font-style: normal;
10 | }
11 |
12 | [class^="icon-"], [class*=" icon-"] {
13 | font-family: 'Norse-Mapcons';
14 | speak: none;
15 | font-style: normal;
16 | font-weight: normal;
17 | font-variant: normal;
18 | text-transform: none;
19 | line-height: 1;
20 |
21 | /* Better Font Rendering =========== */
22 | -webkit-font-smoothing: antialiased;
23 | -moz-osx-font-smoothing: grayscale;
24 | }
25 |
26 | .icon-country:before {
27 | content: "\61";
28 | }
29 | .icon-number:before {
30 | content: "\62";
31 | }
32 | .icon-military:before {
33 | content: "\64";
34 | }
35 | .icon-close:before {
36 | content: "\63";
37 | }
38 | .icon-play:before {
39 | content: "\65";
40 | }
41 | .icon-pause:before {
42 | content: "\66";
43 | }
44 | .icon-info:before {
45 | content: "\67";
46 | }
47 | .icon-open:before {
48 | content: "\68";
49 | }
50 | .icon-closed:before {
51 | content: "\69";
52 | }
53 | .icon-threattype:before {
54 | content: "\6a";
55 | }
56 | .icon-down:before {
57 | content: "\6b";
58 | }
59 | .icon-one:before {
60 | content: "\6c";
61 | }
62 | .icon-five:before {
63 | content: "\6d";
64 | }
65 | .icon-ten:before {
66 | content: "\6e";
67 | }
68 | .icon-twentyfive:before {
69 | content: "\6f";
70 | }
71 | .icon-onehundred:before {
72 | content: "\70";
73 | }
74 | .icon-twohundred:before {
75 | content: "\71";
76 | }
77 | .icon-fivehundred:before {
78 | content: "\72";
79 | }
80 | .icon-googleplus:before {
81 | content: "\73";
82 | }
83 | .icon-facebook:before {
84 | content: "\74";
85 | }
86 | .icon-linkedin:before {
87 | content: "\75";
88 | }
89 | .icon-youtube:before {
90 | content: "\76";
91 | }
92 | .icon-twitter:before {
93 | content: "\77";
94 | }
95 |
--------------------------------------------------------------------------------
/fonts/Norse-Mapcons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LubyRuffy/livemapdemo/b7454daea7ce3ea8359b4b6fcb78bd017d10140d/fonts/Norse-Mapcons.woff
--------------------------------------------------------------------------------
/images/DarkNoiseBackground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LubyRuffy/livemapdemo/b7454daea7ce3ea8359b4b6fcb78bd017d10140d/images/DarkNoiseBackground.png
--------------------------------------------------------------------------------
/images/flags/flags16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LubyRuffy/livemapdemo/b7454daea7ce3ea8359b4b6fcb78bd017d10140d/images/flags/flags16.png
--------------------------------------------------------------------------------
/images/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LubyRuffy/livemapdemo/b7454daea7ce3ea8359b4b6fcb78bd017d10140d/images/loading.gif
--------------------------------------------------------------------------------
/images/norse-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LubyRuffy/livemapdemo/b7454daea7ce3ea8359b4b6fcb78bd017d10140d/images/norse-white.png
--------------------------------------------------------------------------------
/images/unknown-poly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LubyRuffy/livemapdemo/b7454daea7ce3ea8359b4b6fcb78bd017d10140d/images/unknown-poly.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Norse - IPViking Live
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
Loading...
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | 国家
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | 国家
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | 类型
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | 攻击者
126 | 目标
127 | 行为
128 |
129 |
130 |
131 | 时间
132 | 位置
133 | IP
134 | 服务器IP
135 | 服务器位置
136 | 攻击类型
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
Norse Dark Intelligence
160 |
161 | Every second, Norse collects and analyzes live threat
162 | intelligence from darknets in hundreds of locations in
163 | over 40 countries. The attacks shown are based on a
164 | small subset of live flows against the Norse honeypot
165 | infrastructure, representing actual worldwide cyber
166 | attacks by bad actors. At a glance, one can see which
167 | countries are aggressors or targets at the moment, using
168 | which type of attacks (services-ports).
169 |
170 |
171 |
172 | Hovering over the Attack Origins ,
173 | Attack Targets , or
174 | Attack Types will
175 | highlight just the attacks emanating from that country
176 | or over that service-port respectively. Hovering over
177 | any bubble on the map, will highlight only the attacks
178 | from that location and type. Press s
179 | to toggle table sizes.
180 |
181 |
182 |
183 | Norse exposes its threat intelligence via
184 | high-performance, machine-readable APIs in a variety of
185 | forms. Norse also provides products and solutions that
186 | assist organizations in protecting and mitigating cyber
187 | attacks.
188 |
189 |
190 |
191 | For more information, please contact:
192 | inquiry@norse-corp.com
193 |
194 |
195 |
202 |
203 |
204 |
205 |
206 |
Each particle represents an attack
207 |
208 |
209 |
210 |
Attack origins are grouped into clusters
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
Countries are shaded in as they're attacked
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
243 |
244 |
245 |
246 |
247 |
250 |
251 |
252 | Close
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
--------------------------------------------------------------------------------
/ipviking.css:
--------------------------------------------------------------------------------
1 | @import url(http://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800);
2 | @import url(http://fonts.googleapis.com/css?family=Oswald:400,300,700);
3 |
4 | body {
5 | overflow: hidden;
6 | margin: 0;
7 | color: white;
8 | background: url(images/DarkNoiseBackground.png);
9 | font-family: "Oswald", "Open Sans", sans-serif;
10 | }
11 |
12 | ol {
13 | list-style-type: none;
14 | margin-left: -2.0em;
15 | }
16 |
17 | td {
18 | font-family: "Open Sans", "Oswald", sans-serif;
19 | font-weight: 400;
20 | }
21 |
22 |
23 | th {
24 | font-weight: normal;
25 | }
26 |
27 | h1, h2, h3, h4 {
28 | font-family: "Oswald", "Open Sans", sans-serif;
29 | }
30 |
31 | #drawer {
32 | position: absolute;
33 | top: 48px;
34 | right: 6px;
35 | z-index: 100;
36 | height: 385px;
37 | width: 595px;
38 | }
39 |
40 | .blue-bg {
41 | background: rgb(0, 78, 176);
42 | background: transparent\9;
43 | background-color: rgb(0, 78, 176, 0.95);
44 | border-radius: 4px;
45 | border: 1px solid rgba(0, 78, 176);
46 | border: 1px solid rgba(0, 78, 176, 0.95);
47 | -webkit-background-clip: padding-box; /* for Safari */
48 | background-clip: padding-box; /* for IE9+, Firefox 4+, Opera, Chrome */
49 | }
50 |
51 | #drawer-content {
52 | height: 100%;
53 | float: right;
54 | overflow: hidden;
55 | }
56 |
57 | #drawer-inner a,
58 | #drawer-content.info-btn {
59 | text-decoration: underline;
60 | color: #fff;
61 | }
62 |
63 | #drawer-inner a:hover,
64 | #drawer-content .info-btn:hover {
65 | color: rgb(20, 180, 255);
66 | }
67 |
68 | #drawer-inner {
69 | padding: 0 1em;
70 | font-size: 11px;
71 | font-family: "Open Sans", "Oswald", sans-serif;
72 | font-weight: 300;
73 | line-height: 13px;
74 | }
75 |
76 | #drawer-content h1 {
77 | margin-top: 5px;
78 | font-size: 24px;
79 | font-family: "Open Sans", "Oswald", sans-serif;
80 | font-weight: 300;
81 | line-height: 30px;
82 | }
83 |
84 | #drawer-left {
85 | float: left;
86 | width: 60%;
87 | }
88 |
89 | .table-ref {
90 | font-family: "Oswald", "Open Sans";
91 | font-weight: bold;
92 | text-transform: uppercase;
93 | font-size: 0.9em;
94 | }
95 |
96 | /*
97 | This has awful performance...
98 | #drawer-content .footer {
99 | width: 480px;
100 | position: absolute;
101 | bottom: 0;
102 | }
103 | */
104 |
105 | nav {
106 | /* background-color: rgba(0, 140, 240, 0.95);*/
107 | background: linear-gradient(rgba(0, 138, 255, 0.5),
108 | rgba(0, 150, 255, 0.5)),
109 | rgba(0, 0, 0, 0.8);
110 | float: left;
111 | width: 40px;
112 | border-bottom-left-radius: 6px;
113 | }
114 |
115 | nav ul {
116 | list-style-type: none;
117 | margin: 0 0 0 -2.4em;
118 | }
119 |
120 | nav ul li {
121 | margin: 0.2em;
122 | font-size: 1.4em;
123 | text-align: center;
124 | }
125 |
126 | nav ul li a {
127 | display: block;
128 | }
129 |
130 | nav ul li a:visited, a:link {
131 | color: white;
132 | text-decoration: none;
133 | }
134 |
135 | nav ul li a:hover {
136 | color: white;
137 | border-top-color: white;
138 | text-decoration: underline;
139 | }
140 |
141 | #content {
142 | width: 100%;
143 | opacity: 0;
144 | }
145 |
146 | #display-label-container {
147 | width: 100%;
148 | text-align: center;
149 | position: absolute;
150 | z-index: 6;
151 | text-shadow: -1px -1px 0 #000,
152 | 1px -1px 0 #000,
153 | -1px 1px 0 #000,
154 | 1px 1px 0 #000;
155 | }
156 |
157 | #top-line {
158 | width: 100%;
159 | background-color: rgb(1, 73, 128);
160 | height: 5px;
161 | }
162 |
163 | #logo {
164 | position: absolute;
165 | left: 6px;
166 | top: 12px;
167 | z-index: 100;
168 | }
169 |
170 | #loading {
171 | position: absolute;
172 | right: 4em;
173 | bottom: 1em;
174 | }
175 |
176 | #info {
177 | position: absolute;
178 | right: 20em;
179 | top: 1em;
180 | }
181 |
182 | .overlay {
183 | position: absolute;
184 | top: 0;
185 | left: 0;
186 | right: 0;
187 | z-index: 4;
188 | }
189 |
190 | .icon {
191 | width: 1em;
192 | }
193 |
194 | .buffer {
195 | visibility: hidden;
196 | }
197 |
198 | .shadow {
199 | -moz-box-shadow: 0 0 5px 5px rgb(40, 50, 80);
200 | -webkit-box-shadow: 0 0 5px 5px rgb(40, 50, 80);
201 | box-shadow: 0 0 5px 5px rgb(40, 50, 80);
202 | }
203 |
204 | .box {
205 | position: absolute;
206 | z-index: 20;
207 | 1px -1px 0 #000,
208 | -1px 1px 0 #000,
209 | 1px 1px 0 #000;
210 | }
211 |
212 | .gray-bg {
213 | background: rgb(51,51,51);
214 | background: transparent\9;
215 | background: rgba(51,51,51,0.5);
216 | border-radius: 4px;
217 | border: 1px solid rgba(51, 51, 51);
218 | border: 1px solid rgba(51, 51, 51, 0.5);
219 | -webkit-background-clip: padding-box; /* for Safari */
220 | background-clip: padding-box; /* for IE9+, Firefox 4+, Opera, Chrome */
221 | }
222 |
223 | .black-solid {
224 | background-color: rgba(10, 20, 30, 0.8);
225 | border: thin solid rgb(0, 180, 240);
226 | border-bottom-right-radius: 6px;
227 | border-bottom-left-radius: 6px;
228 | -webkit-box-shadow: 0 0 3px 1px rgb(0, 120, 240);
229 | -moz-box-shadow: 0 0 3px 1px rgb(0, 120, 240);
230 | box-shadow: 0 0 3px 1px rgb(0, 120, 240);
231 | }
232 |
233 | .table-container {
234 | z-index: -2;
235 | }
236 |
237 | /*
238 | .data table th {
239 | color: rgb(45, 255, 254);
240 | }
241 | */
242 |
243 | .data {
244 | width: 180px;
245 | }
246 |
247 | .data table tr {
248 | line-height: 18px;
249 | text-align: left;
250 | }
251 |
252 | .data table td,
253 | .data table th {
254 | font-size: 12px;
255 | }
256 |
257 | .data table th {
258 | font-size: 13px;
259 | font-family: "Open Sans Bold", "Oswald", sans-serif;
260 | font-weight: 700;
261 | text-transform: uppercase;
262 | }
263 |
264 | .data table th [class^="icon-"], .data table th [class*=" icon-"] {
265 | font-size: 16px;
266 | }
267 |
268 | .data table td span.numeric {
269 | font-size: 10px;
270 | font-family: "Open Sans Light", "Oswald", sans-serif;
271 | font-weight: 300;
272 | }
273 |
274 | .data .flag {
275 | margin-right: 20px;
276 | height: 1.0em;
277 | }
278 |
279 | .data .numeric {
280 | margin-right: 10px;
281 | }
282 |
283 | .data .icon-number {
284 | margin-right: 8px;
285 | }
286 |
287 | .data colgroup .bar-col { width: 0; }
288 | .data colgroup .total-count { width: 2.6em; }
289 | .data colgroup .data-label-small { width: 1.6em; }
290 | .data colgroup .data-label { width: 10em; }
291 | .data colgroup .port-label { width: 2.8em; }
292 |
293 |
294 | .data tr.row:hover {
295 | background-color: #0c2b4a;
296 | }
297 |
298 | .data table .bar {
299 | position: absolute;
300 | height: 20px;
301 | margin-top: -10px;
302 | background-color: #0c2b4a;
303 | z-index: -1;
304 | border-radius: 3px;
305 | max-width: 98%;
306 | }
307 |
308 | .data table tr td:nth-child(2),
309 | .data table tr th:nth-child(2) {
310 | text-align: right;
311 | padding-right: 0.4em;
312 | }
313 |
314 | .port-circle {
315 | font-size: 1.8em;
316 | text-align: center;
317 | line-height: 0.5em;
318 | }
319 |
320 | .table-header {
321 | text-align: center;
322 | color: rgb(40, 255, 255);
323 | color: rgb(255, 255, 255);
324 | text-transform: uppercase;
325 | border-top-right-radius: 6px;
326 | border-top-left-radius: 6px;
327 | margin-bottom: 4px;
328 | }
329 |
330 | .table-header h1 {
331 | margin: 0.4em 0.8em;
332 | font-family: "Open Sans", "Oswald", sans-serif;
333 | font-weight: 400;
334 | font-size: 16px;
335 | text-align: left;
336 | }
337 |
338 | .top-left {
339 | top: 72px;
340 | left: 6px;
341 | }
342 |
343 | .bottom {
344 | bottom: 6px;
345 | }
346 |
347 | .top-right {
348 | right: 6px;
349 | top: 48px;
350 | }
351 |
352 | .bottom-right {
353 | bottom: 50px;
354 | right: 6px;
355 | }
356 |
357 | .info-controls {
358 | position: absolute;
359 | top: 6px;
360 | right: 6px;
361 | z-index: 20;
362 | }
363 |
364 | .info-controls .icon-close {
365 | font-size: 14px;
366 | }
367 |
368 | .info-controls > div {
369 | float: right;
370 | width: 86px;
371 | height: 34px;
372 | }
373 |
374 | .info-controls > div:first-child {
375 | margin-left: 6px;
376 | }
377 |
378 | .controls {
379 | display: block;
380 | text-align: center;
381 | list-style: none;
382 | padding: 0;
383 | margin: 0;
384 | }
385 |
386 | .controls:hover {
387 | color: #00a6ff;
388 | cursor: pointer;
389 | }
390 |
391 | .controls > span {
392 | display: inline-block;
393 | line-height: 34px;
394 | }
395 |
396 | .information {
397 | display: block;
398 | text-align: center;
399 | list-style: none;
400 | padding: 0;
401 | margin: 0;
402 | }
403 |
404 | .information:hover {
405 | color: #00a6ff;
406 | cursor: pointer;
407 | }
408 |
409 | .information > span {
410 | line-height: 34px;
411 | display: inline-block;
412 | }
413 |
414 | .world {
415 | stroke: #555;
416 | stroke-linejoin: round;
417 | }
418 |
419 | .tick {
420 | stroke: white;
421 | }
422 |
423 | /* The data console */
424 | #console {
425 | left: 6px;
426 | bottom: 32px;
427 | pointer-events: none;
428 | padding: 6px 12px;
429 | }
430 |
431 | #console .table-header h1 {
432 | margin: 0;
433 | min-width: 156px;
434 | }
435 |
436 | #console .table-header {
437 | margin-bottom: 0;
438 | }
439 |
440 | #console table {
441 | font-size: 10px;
442 | font-family: "Open Sans Normal", "Oswald", sans-serif;
443 | font-weight: 400;
444 | line-height: 12px;
445 | border-collapse: collapse;
446 | }
447 |
448 | #console table td,
449 | #console table th {
450 | text-shadow: none;
451 | padding-right: 20px;
452 | }
453 |
454 | #console table td:last-child,
455 | #console table th:last-child {
456 | padding-right: 0px;
457 | }
458 |
459 | #console table tr.first-level {
460 | font-size: 12px;
461 | font-family: "Open Sans Bold", "Oswald", sans-serif;
462 | font-weight: 700;
463 | line-height: 16px;
464 | text-align: left;
465 | text-transform: uppercase;
466 | }
467 |
468 | #console table tr.second-level {
469 | font-size: 10px;
470 | font-family: "Open Sans Bold", "Oswald", sans-serif;
471 | font-weight: 700;
472 | line-height: 12px;
473 | text-align: left;
474 | padding-bottom: 0.2em;
475 | font-weight: light;
476 | text-transform: uppercase;
477 | }
478 |
479 | #console table tr.second-level th {
480 | font-weight: light !important;
481 | }
482 |
483 | #console colgroup col.left-border {
484 | padding-left: 0.5em;
485 | }
486 |
487 | #console table span.overflow {
488 | display: block;
489 | overflow: hidden;
490 | text-overflow: ellipsis;
491 | height: 1.4em;
492 | }
493 |
494 | #console colgroup col.timestamp-col { width: 11em; }
495 | #console colgroup col.location-col { width: 130px; }
496 | #console colgroup col.attacker-org-col { width: 160px; }
497 | #console colgroup col.attacker-ip-col { width: 98px; }
498 | #console colgroup col.service-col { width: 70px; }
499 | #console colgroup col.port-col { width: 30px; }
500 |
501 | a.toggle {
502 | color: rgb(55, 116, 172);
503 | pointer-events: all;
504 | }
505 |
506 | #rate-graph {
507 | z-index: 20;
508 | position: absolute;
509 | left: 6px;
510 | bottom: 6px;
511 | width: 100%;
512 | height: 20;
513 | }
514 |
515 | #drawer {
516 | display: none;
517 | }
518 |
519 | #drawer .social-media {
520 | list-style: none;
521 | padding: 0;
522 | margin: 0;
523 | }
524 |
525 | #drawer .social-media li {
526 | display: inline-block;
527 | margin-right: 35px;
528 | }
529 |
530 | #drawer .social-media li:last-child {
531 | margin-right: 0px;
532 | }
533 |
534 | #drawer .social-media a {
535 | text-decoration: none;
536 | font-size: 11px;
537 | font-family: "Open Sans Bold", "Oswald", sans-serif;
538 | font-weight: 700;
539 | }
540 |
541 | /* TODO -- sort these */
542 | .attacker {
543 | color: rgb(214, 39, 40);
544 | }
545 |
546 | .target {
547 | color: rgb(31, 119, 180);
548 | }
549 |
550 |
551 | /* LEGEND */
552 |
553 | #legend-container {
554 | float: left;
555 | width: 26%;
556 | margin-left: 10%;
557 | margin-top: 52px;
558 | padding-left: 10px;
559 | background: rgb(0,84,190); /* Old browsers */
560 | background: -moz-linear-gradient(left, rgba(0,84,190,1) 0px, rgba(0,84,190,1) 3px, rgba(0,78,176,1) 3px, rgba(0,78,176,1) 3px, rgba(0,78,176,1) 100%); /* FF3.6+ */
561 | background: -webkit-gradient(linear, left top, right top, color-stop(0px,rgba(0,84,190,1)), color-stop(3px,rgba(0,84,190,1)), color-stop(3px,rgba(0,78,176,1)), color-stop(3px,rgba(0,78,176,1)), color-stop(100%,rgba(0,78,176,1))); /* Chrome,Safari4+ */
562 | background: -webkit-linear-gradient(left, rgba(0,84,190,1) 0px,rgba(0,84,190,1) 3px,rgba(0,78,176,1) 3px,rgba(0,78,176,1) 3px,rgba(0,78,176,1) 100%); /* Chrome10+,Safari5.1+ */
563 | background: -o-linear-gradient(left, rgba(0,84,190,1) 0px,rgba(0,84,190,1) 3px,rgba(0,78,176,1) 3px,rgba(0,78,176,1) 3px,rgba(0,78,176,1) 100%); /* Opera 11.10+ */
564 | background: -ms-linear-gradient(left, rgba(0,84,190,1) 0px,rgba(0,84,190,1) 3px,rgba(0,78,176,1) 3px,rgba(0,78,176,1) 3px,rgba(0,78,176,1) 100%); /* IE10+ */
565 | background: linear-gradient(to right, rgba(0,84,190,1) 0px,rgba(0,84,190,1) 3px,rgba(0,78,176,1) 3px,rgba(0,78,176,1) 3px,rgba(0,78,176,1) 100%); /* W3C */
566 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#0054be', endColorstr='#004eb0',GradientType=1 ); /* IE6-9 */
567 | }
568 |
569 | #legend-container h4 {
570 | margin: 0;
571 | font-size: 9px;
572 | margin-bottom: 20px;
573 | font-family: "Open Sans Bold", "Oswald", sans-serif;
574 | font-weight: 400;
575 | line-height: 11px;
576 | text-align: left;
577 | }
578 |
579 | #legend > div {
580 | margin: auto 0.5%;
581 | text-align: left;
582 | }
583 |
584 | #legend ul {
585 | list-style-type: none;
586 | margin-left: -2em;
587 | }
588 |
589 | #legend .clusters ul > li {
590 | display: inline-block;
591 | margin: auto 0.8em;
592 | }
593 |
594 | #legend .country-colors ul > li {
595 | display: inline-block;
596 | margin: auto 0.2em;
597 | width: 1.2em;
598 | }
599 |
600 | #particle-legend > p {
601 | margin-left: 40px;
602 | }
603 |
604 | #origin-legend > p {
605 | margin-left: 15px;
606 | }
607 |
608 | #country-legend > p {
609 | margin-left: 5px;
610 | }
611 |
612 | #origin-legend p span {
613 | margin-right: 4px;
614 | }
615 |
616 | #origin-legend p .icon-one {
617 | font-size: 20px;
618 | padding-top: 12px;
619 | margin-right: ;
620 | }
621 |
622 | #origin-legend p .icon-ten {
623 | padding-top: 8px;
624 | font-size: 24px;
625 | }
626 |
627 | #origin-legend p .icon-twohundred {
628 | font-size: 32px;
629 | }
630 |
631 | h4 > span {
632 | margin-right: 5px;
633 | float: left;
634 | margin-top: 1px;
635 | }
636 |
637 | h4 > p {
638 | display: inline-block;
639 | width: 85%;
640 | margin: 0px;
641 | }
642 |
643 | #country-legend p [class^="icon-"], #country-legend p [class*=" icon-"] {
644 | font-size: 20px;
645 | }
646 |
647 | footer {
648 | width: 30%;
649 | float: right;
650 | font-size: 8px;
651 | font-family: "Open Sans", "Oswald", sans-serif;
652 | line-height: 10px;
653 | margin-top: 10px;
654 | }
655 |
656 | #events-data tr td:first-child {
657 | white-space: nowrap;
658 | }
659 |
660 | #message-panel {
661 | display: none;
662 | position: absolute;
663 | margin-left: auto;
664 | margin-right: auto;
665 | left: 0;
666 | right: 0;
667 | top: 300px;
668 | width: 600px;
669 | }
670 |
671 | #message-container {
672 | position: relative;
673 | min-height: 100px;
674 | padding: 10px;
675 | text-align: center;
676 | vertical-align: middle;
677 | }
678 |
679 | #message-container span {
680 | display: inline-block;
681 | vertical-align: middle ;
682 | }
683 |
684 | #close-button {
685 | position: absolute;
686 | width: 100px;
687 | left: 250px;
688 | bottom: 20px;
689 | height: 25px;
690 | color: white;
691 | border-radius: 3px;
692 | }
693 |
694 | #social-icons {
695 | position: absolute;
696 | height: 36px;
697 | width: 180px;
698 | bottom: 6px;
699 | right: 6px;
700 | font-size: 20px;
701 | line-height: 36px;
702 | text-align: center;
703 | z-index: 20;
704 | }
705 |
706 | #social-icons ul {
707 | list-style: none;
708 | padding: 0;
709 | margin: 0;
710 | }
711 |
712 | #social-icons li {
713 | display: inline-block;
714 | }
715 |
716 | #social-icons a {
717 | display: inline-block;
718 | cursor: pointer;
719 | }
720 |
721 | #social-icons a:visited {
722 | color: white;
723 | }
724 |
725 | #unknown-icon {
726 | position: absolute;
727 | width: 36px;
728 | height: 36px;
729 | opacity: 0.6;
730 | }
731 |
--------------------------------------------------------------------------------
/ipviking.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | // http://isc.sans.org
3 |
4 | var approvedDomains = ['norse-corp.com', 'mitsui.com', 'mbsd.jp'];
5 | if (top.location != self.location && approvedDomains.indexOf(top.location.hostname) === -1) {
6 | top.location = self.location.href
7 | }
8 |
9 | var refreshSeconds = 60 * 60 * 6; // 6 hours
10 | setTimeout("location.reload()", refreshSeconds * 1000);
11 |
12 | function showMessage (message) {
13 | document.getElementById('message-text').innerHTML = message;
14 | document.getElementById('message-panel').style.display = "block";
15 | }
16 |
17 | function hideMessage () {
18 | document.getElementById('message-panel').style.display = 'none';
19 | }
20 |
21 | (function(window) {
22 | var VSN = "1.1";
23 |
24 | var isChrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
25 |
26 | /*
27 | if(!isChrome) {
28 | showMessage("The IPViking digital attack map only supports the Google Chrome browser.");
29 | return;
30 | }
31 | */
32 |
33 | var settings = {
34 | // The data properties to parse into numbers
35 | numberProps: ["latitude", "longitude", "latitude2", "longitude2"],
36 | // Flash this color as statistics udpate
37 | triggerColor: "red",
38 | // Range text down to this opacity
39 | minTextOpacity: 0.35,
40 | // Begin dropping attacks after this number
41 | maxAttacks: 100,
42 | radius: 5,
43 | countryColor: d3.scale.log()
44 | .domain([1, 1200])
45 | .range([d3.rgb(30, 30, 30), d3.rgb(30, 65, 140)]),
46 | tableBarWidth: d3.scale.log()
47 | .domain([1, 500])
48 | .range([1, 130]),
49 |
50 | // Layout settings
51 | linkAnchor: false,
52 | linkSiblings: false,
53 |
54 | // Table Rows
55 | topTableRows: 10,
56 | portTableRows: 8,
57 | consoleTableRows: 8,
58 | pruneInterval: 3600,
59 | dataPruneInterval: 60,
60 |
61 | // Websocket settings
62 | wsHost: "ws://103.28.11.231:8085/",
63 | psk: "echo-protocol",
64 | //wsHost: "ws://64.19.78.244:443/",
65 | //psk: "18c989796c61724d4661b019f2779848dd69ae62",
66 | wsTimeout: 30000
67 | };
68 |
69 | /*
70 | * HTML Interface
71 | */
72 | d3.selectAll(".vsn").text(VSN);
73 |
74 | var timestampedData = [];
75 |
76 | function prune () {
77 | // using the lodash library, where _.select implements binary search to find start of range
78 | // in logarithmic time
79 |
80 | var now = new Date().getTime() / 1000;
81 |
82 | for (var i in timestampedData) {
83 | if (timestampedData[i].pruneTS > now) {
84 | break;
85 | }
86 | }
87 |
88 | var expiredData = [];
89 |
90 | if (i > 0) {
91 | var expiredData = timestampedData.splice(0, i);
92 | }
93 |
94 | for (var n = 0; n < expiredData.length; n++) {
95 | // todo: //statsManager.remove(timestampData[n]);
96 | for (var model in linkModels) {
97 | linkModels[model].remove(expiredData[n]);
98 | }
99 | }
100 | }
101 |
102 | var displayLabel = {
103 | // Label for displaying general info
104 | elt: d3.select("#display-label"),
105 |
106 | set: function(text) {
107 | this.elt.text(text);
108 | },
109 |
110 | clear: function() {
111 | this.elt.text("");
112 | }
113 | }
114 |
115 | if (!window.chrome) {
116 | displayLabel.set("Too slow? Try Chrome.");
117 | }
118 |
119 | d3.selectAll(".info-btn").on("click", function() {
120 | d3.event.preventDefault();
121 | var drawerContent = d3.select("#drawer");
122 | if (drawerContent.style("display") === "none") {
123 | drawerContent
124 | .transition()
125 | .style("display", "block");
126 |
127 | d3.selectAll(".info-btn").classed("blue-bg", true);
128 | d3.selectAll(".info-btn").classed("gray-bg", false);
129 | d3.selectAll(".info-text").classed('icon-info', false);
130 | d3.selectAll(".info-text").classed('icon-close', true);
131 | } else {
132 | drawerContent
133 | .transition()
134 | .style("display", "none");
135 | d3.selectAll(".info-btn").classed("gray-bg", true);
136 | d3.selectAll(".info-btn").classed("blue-bg", false);
137 | d3.selectAll(".info-text").classed('icon-info', true);
138 | d3.selectAll(".info-text").classed('icon-close', false);
139 | }
140 | });
141 |
142 | var loadingToggle = (function() {
143 | // Toggle for the loading html state
144 | var loading = true;
145 |
146 | return function() {
147 | if (loading) {
148 | d3.select("#content")
149 | .transition()
150 | .duration(1000)
151 | .style("opacity", 1);
152 |
153 | d3.select("#loading")
154 | .transition()
155 | .duration(1000)
156 | .style("opacity", 0);
157 | } else {
158 | d3.select("#content").style("opacity", 0);
159 | d3.select("#loading")
160 | .transition()
161 | .duration(1000)
162 | .style("opacity", 1);
163 | }
164 | }
165 | })();
166 | loadingToggle();
167 |
168 | /*
169 | * Variable definitions
170 | */
171 |
172 | // Listen for .toggles
173 | (function() {
174 | var toggles = d3.selectAll(".toggle");
175 | var data = toggles[0]
176 | .map(function(elt) { return d3.select(elt.getAttribute("data-target")); });
177 |
178 | toggles
179 | .data(data)
180 | .on("click", function(d) {
181 | d3.event.preventDefault();
182 | if (d.style("display") === "none") {
183 | d.style("display", "block");
184 | } else {
185 | d.style("display", "none");
186 | }
187 | });
188 | })();
189 |
190 |
191 | // Set up the map in d3
192 | var width = window.innerWidth,
193 | height = window.innerHeight;
194 |
195 | // Project from latlng to pixel coords
196 | var projection = d3.geo.mercator()
197 | .scale(width / 8.5)
198 | .translate([width / 2, height / 1.7]);
199 |
200 | // Draw geojson to svg path using the projection
201 | var path = d3.geo.path().projection(projection);
202 |
203 | // The svg -- our blank canvas
204 | var svg = d3.select("#content").append("svg")
205 | .attr("class", "overlay")
206 | .attr("width", width)
207 | .attr("height", height);
208 |
209 | svg.append("defs")
210 | .append("filter")
211 | .attr("id", "blur")
212 | .append("feGaussianBlur")
213 | .attr("stdDeviation", 2);
214 |
215 |
216 | // Attacks are added to the .attacks svg group and based on data
217 | var node = svg.selectAll(".node"),
218 | link = svg.selectAll(".link");
219 |
220 | // Cluster on target city
221 | var _clusters = d3.map();
222 |
223 | var colorizer = d3.scale.category20();
224 | // Mapping of ports to properties
225 | var ports;
226 |
227 |
228 | /**************
229 | * Internal API
230 | */
231 |
232 | function spanWrap(content, classes) {
233 | // Returns the content wrapped in the span
234 | return '' +
235 | content + ' '
236 | }
237 |
238 | function dist(x1, y1, x2, y2) {
239 | // Returns the distance between two points
240 | return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
241 | }
242 |
243 | function rgbaString(c, a) {
244 | // Helper to get the color as an rgba string
245 | return "rgba(" + c.r + "," + c.g + "," + c.b + "," + a + ")";
246 | }
247 |
248 | function parsePorts(rawPorts) {
249 | // Given the csv list of ports, process it
250 | var ports = [];
251 | for (var i = 0; i < rawPorts.length; ++i) {
252 | var port = parseInt(rawPorts[i].port);
253 | if (port in ports) {
254 | ports[port] = ports[port] + ", " + rawPorts[i].service;
255 | } else {
256 | ports[port] = rawPorts[i].service;
257 | }
258 | }
259 |
260 | // Fix certain port strings
261 | ports[80] = "http";
262 | return ports;
263 | }
264 |
265 | var getID = (function() {
266 | // Generate unique enough IDs
267 | var i = 0;
268 | return function() {
269 | return i++;
270 | }
271 | })();
272 |
273 |
274 | function flagPath(iso) {
275 | // Return the path to the flag for the given countrycode
276 | if (iso === "O1") {
277 | return "images/militarywhite.svg";
278 | } else {
279 | return "images/flags/" + iso + ".png";
280 | }
281 | }
282 |
283 | function flagTag(iso) {
284 | return ' ';
285 | }
286 |
287 | function isNumber(n) {
288 | // Returns true if n is a number
289 | return !isNaN(parseFloat(n)) && isFinite(n);
290 | }
291 |
292 | var particler = function() {
293 | // Returns a function that will generate colored particles
294 | var particle = new Image(),
295 | tempFileCanvas = d3.select("#content")
296 | .append("canvas")
297 | .attr("class", "buffer")
298 | .node();
299 |
300 | particle.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAB3RJTUUH1wQUCC4hoGmo9QAACvlJREFUaN69mltz00gQhS3NSCMlNjEmBYTi//8zCipUsIMd6zKytA/fctKMDITArh5ctqxLX06fvsxkiz84sizLsizPc74sFotpmvSZHPO/fnLxb8jwbNH1yZc8z8dx1HedT+Q7nU6LxWIcxz+U+zkKIC7CSYEsy7z3CDoMQ5ZlRVFwXiJO0zRNE7eM4zgMA2dQ5g+dkD0dKlKA9xVFYZVJjouLixhj13V5nnvvh2GY+wQd+MQnz9DE/VL0PM/zPHfOIX2e50VROOecc4KKvb4sS+yti8uyxPZnH44m2OUZCmS/tDqPFmZkeL1MQBrH0XtPMKAGpkXz0+mUZRkQUgzIe1w8DIN89UcKIJNzTqIvFgvvPX7QgWeKorBBoovHcYwxEiGCO0eMcRxHzlur931v1X4+hJDMGl74wd15npdl6b333kt67/00TUALbhXSsL2FYlEU6GZlBYFzhX/PA5bap2mSlJiKoIRqnHOWSefPEdNbqPDX6XSKMSqK2raVJlmWxRjx0i+j4owC2Iy3OudkJ8wplsTMNishMZ/EQIzxLEdxPfIh9ziOfd8TJ1xAtPR9/3sQEjMgeoIQ+IS/rI1FsvoSQkCZoiiUB6wfEj/zk8gRjKXJb3gAmPIsvQ/E6xpodB7x0oFIEOSIVM7IzHNcgZk8z2V4PN80zU90cHMFMLa40jlnDQ+QEo+BK8WuTDtnYfTUeRsVymXOObETj/pJTLs5eybIqetaNrbJSxgTz6iekwm4KymfcC/PgUx1XhcTcsitQutsQPsfxYDgpACw4chfmNM+V8WFrlceSCg//3ZYpuJpMcayLJXRkJ53zV2RJqayLCV0CIHXz6Uvy9JSEJaG2rEu71NgiLJsoSqWm+d1xYmA9KPy1idCCPryss4Iu1YfQUtqKxPrU9UEcaxqIqlw9QruGoahqqrj8SirJT5MPUDVJb+HEJS2FJGYWXGpUkKxS8QrPEIINmSVW9Q8JCWjJVwZmzhB86QMe1SAHC5PIRPS2/hDQ8mErDr4qfDI87yqKhUROkRuSQ/knKNVSDokgkG1WRLNLmFPHq0vFvpoKCvK8IjOT8tIhNA4jqfTyZZGArfVR5/iJesf6anM/Z0CiC6BhAFRSpKVrfRiUoku26OwrTgQRbaUDkIOr7CZDu9Rn8r51gl+Xn5KepuA8IllcVQVxpCbJM2VIYSiKIhCTsYYZWZyH84pikJZDKfJD+ouuq6TAN9BiFOErGgbR8sDokUuQAEMz/U8AcygQ1EUIQRbWsuHCKca21JnUucpEriYnluN6KMCtimR35VWLQywq3DPi8uyBHVlWVZVdXFxgSZ84UZ5RnDni3NO9lbehZGtmcdvh0j5OwiJsM5WyDYY8LtKbs5776uqEk29evWqLMvT6XR5eVkUxeFw2O12VMvg2znXtq0tGdCnKAphjDmArfnAcIwR9WKM/3pAQoj15QEZWHAkdv23Q967vLy8uLgoy3Kz2SyXy7quh2EIIVRVdTgc8jxfr9dVVbVty4tVCGF7Acb6wfbNakgEHingbZmu65I2yprfVhaQj/c+xrharW5ubrquy7JstVqFENbrtXOO4KOQXi6XwzB0XSfixvzee25E+qR5SHp/Tcf+ZReroi13bXE2r91VYClkKb+ur6+dc5vNBlagrQkhfPjwIcZYVdV6vd7v93QFIYSu6wAVwYCNLc/YQQY6E5aPtZCClackxYbQb2shEZS4CApqmubq6ur9+/dXV1ebzQaVNpvNp0+fQghv377tuq7ruhhj27bOORCvx1oRbfjKUaqg7GU+qW9t6WcLdFsO2WYf2rm+vq7rOoRQ1/Visbi5uXn37h2RsN1uMeput/v48WPf90lGR435oJeEYMeSSJhkYn8WbbpHYWS7MGUJuJnhwjRNq9Xq9evXb968Wa/XL1++xDlwy+Fw2O/3x+NRhY1NzDKnJVBbF3HX2dHdY5Kn57DMxeRD/47msNNZWtjj8fj169emaZxzNHFgtyxL6Gi1Wq3Xa6omSNOWusloUVRh7Xh+hGWjk0OZQonWjmPtpEAFRQhhuVyu1+sXL16IzsWV2IJ8V9c1OtgGRaKLQ+2AI/F8OgK0aUu4tJaw/Y0tnsmyIQQywHK5jDFut1tO1nVd1/XpdNrtdnd3dw8PD1++fNlut23bQqxaLpgPXZK/ZLL5LPlMTwxCxJ5iBpXKKsoV1k3T3N7eAp6+76uq+vz5M5VFjJHYZcLVdd0wDIfDwU61kh5F1Z7QO4eQvdhLVwmq3Mw0BfNohA9tM4gdx/H+/h6VLi8vYTpofhgGVGrbFg+M41jXddu2h8NhGAZCjrfbUicZYdi0o6Hvd9Uor6/rGolV9CsYLOWrU9PYEMAg+tXV1TRN+/3ee9/3/d3d3f39fdd1+/1+t9vt9/tpmo7HY9/3TdMQ+sgkZVQLqRGzIYfaWFP/OiUjiif1E+ggiSU3L8NdVKZnkYACbdviE+S7vb09HA4xRtYBGMUJLZzRSpSdoEBo8LUI81EB8aYaK+KdVCVq0joKdZH3XpYAVE3TnE4nPImZeU3btg8PD/v9/uHhoe/7vu9ZfZKftfInFAmxMpDeJSM+BjExoKrV8kDbtmJrbhOx4ge7bkda3W63fd8z4lwsFoRE0zQxRhKLTM6N3GtNru/yhu0NVcM+lhJaehnHkWU51UVIbFMbGb5pGgJGRE711jRNURS4247cEJ1QAUKiBMwHvm3SFIw5T7mq9PLYkYEKNXusc4mUxM12aqnq1RZOmj0JD8Qo0iAxtbTY3brCsr7tGLV6qwYATz52ZCoKkvWvZJBvl+JoyWkDtAKgZS+WNmwxoyqSF2N7WJi320Gdxbc1h1ydzOecxdZ8iijkAPF5eaeBuCKShb1pmsC90II+ElEYw1GS2C7JKBhY/MOHybKaS4Z7Wp5IloEBlbykqU5ShijvyNH2EJmIxe13lYl2wUpxP78mnY3aVVQ7N7fBZLt+HqSpt6UO7K0tBQAMw1s40Y5ZrrScI/yIPW20pAokwADlyGGjmSdqIJ4sVkuNLMsge5toVThoTduuzUjDJBKQQaxgG+LUA8liMNdpWde+TIW0TSvJqpEFhq0oiYpkxAm4bXeulAz6bUgkhV26xKSaW3lRDCv8KJhsF6JKi4QvhsG0IEosJJRj16TsUVHTtq3sTdCf2XCR/C6KQrshtEY2jiNlT9LvayBpuxPbIp4tg20LZXsDhTVSIr3Cw5LVz1YpbQrTdIl4UAqz5SrWFaLsrDyZLFmEWCa1a/fyUtd1mnlZMnjSQrcoT/NX2VXtTmJjMECVYafCtqwSThTcyaIY+lAXC0WqWH+00no++wrrdpJhk4Dd6mNlVadi14UksY1CywpIzLs0SVBo/XzzSvaj3SrIJ+gDJHKFXKk1qGT9Yr7fw2puvye9mLZ8UGsklcVvbzlDPrvJgCi33ki2HSSCzsPANuzCJ+gCZvKJ8saf7pmr69qKqMlFCEGTYPU9lr4SFrLVmBRQTrCuG4ZB8/e/sOlPyx/ahjOvPuZbl4TDZAsZqGCI2zTNHG/EwNM3nj112yUdpkZdli5ZTTrLcfNhjga6yW4i9TR/Z8/cL73BpC0ZoWm+WZalYpEmTpSf5AdVfr9km7+z8dWOr9XKnN18OUf/Wf+oyn9KvD5n3+icXpTUYIwkDc+rhiRR2KbEVqzP3rz7zL3TZ+s/NRJ2LR4IKSUlLc7/unf6iQfZw3pARLn4D46/4IEklOfZ92xN+rd2r/8DebSckAm1i/EAAAAASUVORK5CYII=";
301 |
302 | tempFileCanvas.width = 64;
303 | tempFileCanvas.height = 64;
304 |
305 | return function (r, g, b, a) {
306 | var imgCtx = tempFileCanvas.getContext("2d"),
307 | imgData, i;
308 |
309 | imgCtx.drawImage(particle, 0, 0);
310 |
311 | //if(particle.width > self.innerWidth){particle.width=self.innerWidth;} if(particle.width < 1){particle.width=1;}
312 | //if(particle.height > self.innerHeight){particle.height=self.innerHeight;} if(particle.height < 1){particle.height=1;}
313 | imgData = imgCtx.getImageData(2, 2,64,64);
314 |
315 | //imgData = imgCtx.getImageData(0, 0, particle.width, particle.height);
316 |
317 | i = imgData.data.length;
318 | while((i -= 4) > -1) {
319 | imgData.data[i + 3] = imgData.data[i] * a;
320 | if (imgData.data[i + 3]) {
321 | imgData.data[i] = r;
322 | imgData.data[i + 1] = g;
323 | imgData.data[i + 2] = b;
324 | }
325 | }
326 |
327 | imgCtx.putImageData(imgData, 0, 0);
328 | return tempFileCanvas;
329 | }
330 | }();
331 |
332 | var nodeModel = {
333 | /*
334 | * Provides an API for managing the various force layout nodes
335 | *
336 | * Node Types:
337 | * - Attack Nodes {type: attack}
338 | * - Target Nodes {type: target}
339 | * - Anchor Nodes, ie City {type: anchor}
340 | */
341 |
342 | // Configuration
343 | linkSiblings: true,
344 | linkAnchor: false,
345 | target: true,
346 | interval: 50,
347 | pathLength: 15,
348 | targetMaxAge: 200,
349 | scaleTargetVel: d3.scale.log().domain([1, 40]).range([40, 100]),
350 |
351 | // Constants
352 | ATTACKS: "attacks",
353 | TARGETS: "targets",
354 | ANCHORS: "anchors",
355 |
356 | lastPrune: new Date().getTime() / 1000,
357 |
358 | // The list of nodes, shared with the force layout
359 | nodes: undefined,
360 | // The list of links, shared with the force layout
361 | links: undefined,
362 |
363 | // Force layout to make the elements move correctly
364 | force: d3.layout.force()
365 | .size([width, height])
366 | .friction(0.25)
367 | .gravity(0)
368 | .charge(-10)
369 | .chargeDistance(50)
370 | .linkDistance(15)
371 | .linkStrength(function(d) { return d.linkStrength || 0.5; }),
372 |
373 | prune: function () {
374 | var now = new Date().getTime() / 1000;
375 |
376 | if (now - this.lastPrune > 10) {
377 | this.lastPrune = now;
378 |
379 | for (var i in this.nodes) {
380 | if (this.nodes[i].pruneTS > now) {
381 | if (i > 0) {
382 | this.nodes.splice(0, i);
383 | }
384 | break;
385 | }
386 | }
387 |
388 | for (var i in this.links) {
389 | if (this.links[i].pruneTS > now) {
390 | if (i > 0) {
391 | this.links.splice(0, i);
392 | }
393 | break;
394 | }
395 | }
396 | }
397 | },
398 |
399 | get: function(type) {
400 | return this.nodes.filter(function(n) { return n.type === type; });
401 | },
402 |
403 | _mapKey: function(d) {
404 | return d.city + d.latitude + d.longitude;
405 | },
406 |
407 | _remove: function(n, j) {
408 | for (var i = 0; i < this.links.length; i++) {
409 | if (this.links[i].source.id === n.id ||
410 | this.links[i].target.id === n.id) {
411 | this.links.splice(i--, 1);
412 | }
413 | }
414 |
415 | if (typeof j !== 'undefined') this.nodes.splice(j, 1);
416 |
417 | // Remove a node, and its associated links
418 | for (var i = 0; i < this.nodes.length; i++) {
419 | if (n.id === this.nodes[i].id) {
420 | this.nodes.splice(i--, 1);
421 | }
422 | }
423 |
424 | },
425 |
426 | _shift: function(type) {
427 | for (var i = 0; i < this.nodes.length; i++) {
428 | if (this.nodes[i].type === type) {
429 | this._remove(this.nodes[i], i);
430 | break;
431 | }
432 | }
433 | },
434 |
435 | _getsertAnchorFor: function(attack) {
436 | // Get the anchor for the given node, inserting it if its not present
437 | var key = this._mapKey(attack),
438 | anchor = this.nodes.filter(function(n) { return n.key === key; })[0];
439 |
440 | if ( anchor ) {
441 | return anchor;
442 | } else {
443 | var newAnchor = {
444 | id: getID(),
445 | key: key,
446 | type: this.ANCHORS,
447 | x: attack.cx,
448 | y: attack.cy,
449 | cx: attack.cx,
450 | cy: attack.cy,
451 | country: attack.country,
452 | city: attack.city,
453 | fixed: true,
454 | pruneTS: (new Date()).getTime() / 1000 + settings.dataPruneInterval
455 | }
456 | this.nodes.push(newAnchor);
457 | return newAnchor;
458 | }
459 | },
460 |
461 | pushAttack: function(attack) {
462 | /*
463 | * Push a new Attack
464 | * Nodes are inserted at the source location and linked to an anchor
465 | * centered at this source, and all of the adjacent nodes. Links
466 | * are stronger to nodes of the same type.
467 | */
468 | // Clear out old nodes
469 | while (this.get(this.ATTACKS).length > 50) {
470 | this._shift(this.ATTACKS);
471 | }
472 | if (this.linkSiblings) {
473 | var key = this._mapKey(attack),
474 | that = this;
475 | this.nodes.forEach(function(n) {
476 | if ( that._mapKey(n) === key ) {
477 | that.links.push({
478 | source: n,
479 | target: attack,
480 | pruneTS: (new Date()).getTime() / 1000 + settings.dataPruneInterval,
481 | linkStrength: n.service === attack.service ? 0.5 : 0.25});
482 | }
483 | });
484 | }
485 |
486 | // Anchor
487 | var anchor = this._getsertAnchorFor(attack);
488 | if (this.linkAnchor) {
489 | this.links.push({source: anchor, target: attack, linkStrength: 1.0});
490 | }
491 |
492 | // Target
493 | if (this.target) {
494 | var initialVelocity = -0.0001;
495 | var target = {
496 | type: this.TARGETS,
497 | age: 0,
498 | path: [],
499 | h: dist(attack.x, attack.y, attack.targetX, attack.targetY),
500 | id: getID(),
501 | x: attack.x,
502 | y: attack.y,
503 | cx: attack.targetX,
504 | cy: attack.targetY,
505 | startX: attack.x,
506 | startY: attack.y,
507 | city: attack.city2,
508 | country: attack.country2,
509 | theta: Math.atan((attack.targetY - attack.y) /
510 | (attack.targetX - attack.x)),
511 |
512 | service: attack.service,
513 | pruneTS: (new Date()).getTime() / 1000 + settings.dataPruneInterval
514 | }
515 | // this.links.push({source: this._getsertAnchorFor(target),
516 | // target: target, linkStrength: 1.0});
517 | this.nodes.push(target);
518 | }
519 |
520 | // Decorate and add the attack node
521 | attack.type = this.ATTACKS;
522 | attack.age = 0;
523 | this.nodes.push(attack);
524 |
525 | // TODO - is this necessary?!
526 | this.force.start();
527 | },
528 |
529 | step: function() {
530 | // Step the simulation
531 | this.nodes.forEach(function (n) {
532 | n.age++;
533 | });
534 |
535 | this.get(this.TARGETS)
536 | .filter(function(t) {
537 | return t.age > this.targetMaxAge ||
538 | "arrivalAge" in t && t["arrivalAge"] + 40 < t.age; }, this)
539 | .forEach(function (t) {
540 | this._remove(t);
541 | }, this);
542 | },
543 |
544 | start: function() {
545 | // Start the layout
546 | var that = this;
547 |
548 | // Initialize the array references
549 | this.nodes = [];
550 | this.links = [];
551 | this.force
552 | .nodes(this.nodes)
553 | .links(this.links)
554 | .on("tick", (function() {
555 | //var targetTrack;
556 |
557 | return function(e) {
558 | // Tick the force layout
559 | that.step();
560 | that.get(that.ATTACKS).forEach(function(d) {
561 | var scale = 0.1;
562 | d.x += scale * (d.cx - d.x) * e.alpha;
563 | d.y += scale * (d.cy - d.y) * e.alpha; });
564 |
565 | that.get(that.TARGETS).forEach(function(d) {
566 | //DEBUGGING
567 | // if (!targetTrack) targetTrack = d.id;
568 | // Update the target's path
569 | d.path.unshift({x: d.x, y: d.y});
570 | if (d.path.length > that.pathLength)
571 | d.path.pop();
572 |
573 | if (d.arrivalAge) {
574 | d.fixed = true;
575 | } else {
576 | var travelled = dist(d.x, d.y, d.startX, d.startY),
577 | //v = (Math.sqrt(travelled * 50) + 180) * e.alpha,
578 | v = that.scaleTargetVel(d.age) * e.alpha,
579 | toTarget = dist(d.cx, d.cy, d.x, d.y);
580 |
581 | if (v <= toTarget) {
582 | var theta = Math.atan2(d.cy - d.y, d.cx - d.x);
583 | //r = v / d.h;
584 | d.x += v * Math.cos(theta);
585 | d.y += v * Math.sin(theta);
586 | } else {
587 | //debugger;
588 | // Arrived at target
589 | d.x = d.cx;
590 | d.y = d.cy;
591 | d.arrivalAge = d.age;
592 | }
593 | }
594 | });
595 | that.force.resume();
596 | }
597 | })())
598 | .start();
599 |
600 | // Prevent the alpha from 'cooling' to 0
601 | d3.timer(this.force.resume);
602 | }
603 | }
604 |
605 | // An abstract model for caching and querying city <=> city links
606 | var LinksModel = {
607 | // {ORIGINCOUNTRY: {ORIGINCITY: {TRGTCOUNTRY: {TRGTCOUNTRY: {DPORT: COUNT}}}}}
608 | // Created in via .extend: _links: {},
609 | // {COUNTRY: {CITY: {latitude: LAT, longitude: LON}}}
610 | _locs: {},
611 |
612 | insertLink: function(origin, target, port) {
613 | if (!(origin.country in this._links)) {
614 | this._links[origin.country] = {};
615 | }
616 |
617 | if (!(origin.city in this._links[origin.country])) {
618 | this._links[origin.country][origin.city] = {};
619 | }
620 |
621 | var originLinks = this._links[origin.country][origin.city];
622 | if (!(target.country in originLinks)) {
623 | originLinks[target.country] = {};
624 | }
625 |
626 | if (!(target.city in originLinks[target.country])) {
627 | originLinks[target.country][target.city] = {};
628 | }
629 |
630 | var targetLinks = originLinks[target.country][target.city]
631 | if (!(port in targetLinks)) {
632 | targetLinks[port] = 1;
633 | } else {
634 | targetLinks[port] = targetLinks[port] + 1;
635 | }
636 | },
637 |
638 | removeLink: function(origin, target, port) {
639 | var link1 = this._links[origin.country];
640 |
641 | if (!link1) return
642 |
643 | var link2 = this._links[origin.country][origin.city];
644 |
645 | if (!link2) return
646 |
647 | var target1 = link2[target.country];
648 |
649 | if (!target1) return
650 |
651 | var target2 = link2[target.country][target.city]
652 |
653 | if (!target2) return
654 |
655 | if (target2[port] > 1) {
656 | target2[port]--;
657 | } else if (target2[port] !== undefined){
658 | delete target2[port];
659 | }
660 | },
661 |
662 | insertLoc: function(loc) {
663 | if (!(loc.country in this._locs)) {
664 | this._locs[loc.country] = {}
665 | }
666 |
667 | if (!(loc.city in this._locs)) {
668 | this._locs[loc.country][loc.city] =
669 | {latitude: loc.latitude, longitude: loc.longitude};
670 | }
671 | },
672 |
673 | removeLoc: function(loc, origin, target, port) {
674 | var link1 = this._links[origin.country];
675 |
676 | if (!link1) return
677 |
678 | var link2 = this._links[origin.country][origin.city];
679 |
680 | if (!link2) return
681 |
682 | var target1 = link2[target.country];
683 |
684 | if (!target1) return
685 |
686 | var target2 = link2[target.country][target.city]
687 |
688 | if (!target2) return
689 |
690 | if (!target2[port]) {
691 | delete this._links[origin.country][origin.city];
692 | delete this._locs[loc.country][loc.city]
693 | }
694 | },
695 |
696 | _distanceBetween: function(pt1, pt2) {
697 | return Math.sqrt(Math.pow(pt1[0] - pt2[0], 2) +
698 | Math.pow(pt1[1] - pt2[1], 2));
699 | },
700 |
701 | getCity: function(country, city) {
702 | if (country in this._locs && city in this._locs[country] ) {
703 | var loc = this._locs[country][city],
704 | pt = projection([loc.longitude, loc.latitude]),
705 | info = {
706 | country: country,
707 | city: city,
708 | latitude: loc.latitude,
709 | longitude: loc.longitude,
710 | pt: pt};
711 |
712 | if (country in this._links && city in this._links[country]) {
713 | info.counts = this._links[country][city];
714 | }
715 |
716 | return info;
717 | }
718 | },
719 |
720 | getCities: function() {
721 | // Returns list of all cities
722 | var cities = [];
723 | for (var country in this._locs) {
724 | for (var city in this._locs[country]) {
725 | cities.push(this.getCity(country, city));
726 | }
727 | }
728 | return cities;
729 | },
730 |
731 | getCountry: function(country) {
732 | var cities = [];
733 | for (var city in this._links[country] || {}) {
734 | cities.push(this.getCity(country, city));
735 | }
736 | return cities;
737 | },
738 |
739 | pixelsFromNearest: function(pt) {
740 | // Returns the pixels from the nearest source
741 | var closest;
742 | for (var country in this._links) {
743 | for (var city in this._links[country]) {
744 | var info = this.getCity(country, city);
745 |
746 | if (info) {
747 | var distance = this._distanceBetween(pt, info.pt);
748 | if (!closest || distance < closest.distance) {
749 | info.distance = distance;
750 | closest = info;
751 | }
752 | }
753 | }
754 | }
755 | return closest
756 | },
757 |
758 | total: function (counts) {
759 | // Total up a counts array, recursive
760 | if (isNumber(counts)) {
761 | return counts;
762 | } else {
763 | var sum = 0;
764 | for (var key in counts) {
765 | sum += this.total(counts[key]);
766 | }
767 | return sum;
768 | }
769 | },
770 |
771 | cityToLinks: function(city, strokeOrigin, strokeTarget) {
772 | if (!city) return [];
773 |
774 | var links = [];
775 | for (var country in city.counts) {
776 | if (!city.counts[country]) continue;
777 | for (var cityKey in city.counts[country]) {
778 | var info = this.getCity(country, cityKey),
779 | counts = city.counts[country][cityKey];
780 |
781 | if (!info || !counts || !Object.keys(counts).length) continue;
782 |
783 | for (var service in counts) {
784 | var r = circleScale(counts[service]),
785 | color = colorizer(service),
786 | source = { x: city.pt[0], y: city.pt[1], r: r },
787 | target = { x: info.pt[0], y: info.pt[1], r: r };
788 |
789 | if (strokeTarget) {
790 | source.strokeStyle = color;
791 | } else {
792 | source.fillStyle = color;
793 | }
794 |
795 | if (strokeOrigin) {
796 | target.strokeStyle = color;
797 | } else {
798 | target.fillStyle = color;
799 | }
800 |
801 | links.push({
802 | count: counts[service],
803 | source: source,
804 | target: target,
805 | width: lineScale(counts[service]),
806 | color: color
807 | });
808 | }
809 | }
810 | }
811 | return links.sort(function(l1, l2) { return l2.count - l1.count; });
812 | },
813 |
814 | dPortLinks: function(service) {
815 | var links = []
816 | for (var sourceCountry in this._links) {
817 | for (var sourceCity in this._links[sourceCountry]) {
818 | var s = this.getCity(sourceCountry, sourceCity);
819 | for (var targetCountry in s.counts) {
820 | for (var targetCity in s.counts[targetCountry]) {
821 | var t = this.getCity(targetCountry, targetCity);
822 | for (var targetservice in s.counts[targetCountry][targetCity]) {
823 | var c = s.counts[targetCountry][targetCity][targetservice];
824 | if (service && service === targetservice) {
825 | links.push({
826 | count: c,
827 | source: s,
828 | target: t,
829 | service: service
830 | });
831 | }
832 | }
833 | }
834 | }
835 | }
836 | }
837 | return links;
838 | },
839 |
840 | extend: function(o) {
841 | o.__proto__ = this;
842 | o._links = {};
843 | return o;
844 | }
845 | };
846 |
847 | // Set up the link models, one for origins, and one for targets
848 | var linkModels = {
849 | origins: LinksModel.extend({
850 | insert: function(d) {
851 | this.insertLink(
852 | {country: d.country, city: d.city},
853 | {country: d.country2, city: d.city2},
854 | d.service);
855 |
856 | this.insertLoc(
857 | {country: d.country,
858 | city: d.city,
859 | latitude: d.latitude,
860 | longitude: d.longitude});
861 | },
862 | remove: function(d) {
863 | this.removeLink(
864 | {country: d.country, city: d.city},
865 | {country: d.country2, city: d.city2},
866 | d.service);
867 |
868 | this.removeLoc(
869 | {country: d.country,
870 | city: d.city,
871 | latitude: d.latitude,
872 | longitude: d.longitude}, {country: d.country, city: d.city},
873 | {country: d.country2, city: d.city2},
874 | d.service);
875 | }
876 | }),
877 |
878 | targets: LinksModel.extend({
879 | insert: function(d) {
880 | this.insertLink(
881 | {country: d.country2, city: d.city2},
882 | {country: d.country, city: d.city},
883 | d.service);
884 |
885 | this.insertLoc(
886 | {country: d.country2,
887 | city: d.city2,
888 | latitude: d.latitude2,
889 | longitude: d.longitude2});
890 | },
891 | remove: function(d) {
892 | this.removeLink(
893 | {country: d.country2, city: d.city2},
894 | {country: d.country, city: d.city},
895 | d.service);
896 |
897 | this.removeLoc(
898 | {country: d.country2,
899 | city: d.city2,
900 | latitude: d.latitude2,
901 | longitude: d.longitude2}, {country: d.country2, city: d.city2},
902 | {country: d.country, city: d.city},
903 | d.service);
904 | }
905 | })
906 | }
907 |
908 | var countryModel = {
909 | // The raw list of data
910 | _raw: undefined,
911 | _iso2: undefined,
912 | _iso3: undefined,
913 | _countries: undefined,
914 |
915 | push: function(country) {
916 | // Push a new country
917 | this._raw.push(country);
918 | if (country.iso2) this._iso2[country.iso2] = country;
919 | if (country.iso3) this._iso3[country.iso3] = country;
920 | if (country.country) this._countries[country.country] = country;
921 | },
922 |
923 | set: function(raw) {
924 | this._raw = [];
925 | this._iso2 = {};
926 | this._iso3 = {};
927 | this._countries = {};
928 | for (var i = 0; i < raw.length; i++) { this.push(raw[i]); };
929 | },
930 |
931 | getByIso2: function(iso2) {
932 | return this._iso2[iso2.toUpperCase()];
933 | },
934 |
935 | getByIso3: function(iso3) {
936 | return this._iso3[iso3.toUpperCase()];
937 | },
938 |
939 | getByCountry: function(country) {
940 | return this._countries[country];
941 | }
942 | }
943 |
944 | /*
945 | * painter handles rendering to the canvas
946 | */
947 |
948 | // Prepare canvas and buffer
949 | var canvas = d3.select("#content").append("canvas")
950 | .text("This browser doesn't support Canvas elements")
951 | .attr("id", "visible-canvas")
952 | .attr("class", "overlay")
953 | .attr("width", width)
954 | .attr("height", height)
955 |
956 | var bufCanvas = d3.select("#content").append("canvas")
957 | .attr("class", "buffer overlay")
958 | .attr("width", width)
959 | .attr("height", height);
960 |
961 | // Allows for consistent scaling of drawn elements
962 | var logScale = d3.scale.log()
963 | .domain([1, 200])
964 | .range([1, 10]);
965 |
966 |
967 | var lineScale = function(x) { return logScale(x) };
968 | var circleScale = function(x) { return Math.ceil(1.4 * logScale(x)) };
969 | var colorScale = (function() {
970 | var log = d3.scale.log()
971 | .domain([1, 600])
972 | .range([1, 100]);
973 | return function(v) {
974 | return log(v);
975 | }
976 | })();
977 |
978 | var painter = {
979 | // The various drawings
980 | drawings: {
981 | // Draw the attack nodes
982 | nodes: {
983 | // The visible nodes
984 | active: true,
985 | nodeModel: nodeModel,
986 | // Canvas composition: "lighter", "darker", ...
987 | compositeOperation: undefined,
988 |
989 | getRadius: function(d) {
990 | // Given a node, return the radius
991 | var growthEnd = 60, growthMax = 80,
992 | growthStep = growthMax / growthEnd,
993 | shrinkEnd = 120, shrinkMin = 20,
994 | shrinkStep = (growthMax - shrinkMin) / (shrinkEnd - growthEnd);
995 |
996 | if (d.age >= 0 && d.age < growthEnd) {
997 | return growthStep * d.age;
998 | } else if (d.age < shrinkEnd) {
999 | return growthMax - shrinkStep * (d.age - growthEnd);
1000 | } else {
1001 | return shrinkMin;
1002 | }
1003 | },
1004 |
1005 | draw: function(context) {
1006 | nodeModel.prune();
1007 |
1008 | if (this.compositeOperation) {
1009 | context.globalCompositeOperation = this.compositeOperation;
1010 | }
1011 |
1012 | var that = this;
1013 | nodeModel.get(nodeModel.ATTACKS)
1014 | .forEach(function(n) {
1015 | var c = d3.rgb(colorizer(n.service)),
1016 | r = that.getRadius(n);
1017 | context.drawImage(particler(c.r, c.g, c.b, 1),
1018 | n.x - r / 2, n.y - r / 2, r, r);
1019 | });
1020 |
1021 | }
1022 | },
1023 |
1024 | // Draw new node pings
1025 | pings: {
1026 | active: true,
1027 | order: -1,
1028 | duration: 80,
1029 | scaleRadius: d3.scale.linear().domain([1, 80]).range([1, 48]),
1030 | scaleOpacity: d3.scale.linear().domain([1, 80]).range([1, 0]),
1031 | draw: function(context) {
1032 | var pi = Math.PI;
1033 | for (var i = 0; i < nodeModel.nodes.length; i++) {
1034 | var n = nodeModel.nodes[i];
1035 | if (n.type === nodeModel.ATTACKS && n.age < this.duration) {
1036 | context.globalAlpha = this.scaleOpacity(n.age);
1037 | context.strokeStyle = colorizer(n.service);
1038 | context.lineWidth = 3;
1039 | context.beginPath();
1040 | context.arc(n.x, n.y, this.scaleRadius(n.age),
1041 | 0, 2 * pi);
1042 | context.stroke();
1043 | }
1044 | }
1045 | }
1046 | },
1047 |
1048 | // Draw the origin nodes
1049 | origins: {
1050 | active: true,
1051 | order: -2,
1052 | draw: function(context) {
1053 | context.globalAlpha = 0.65;
1054 | context.fillStyle = "#fff";
1055 |
1056 | var cities = linkModels.origins.getCities();
1057 |
1058 | var ceil = Math.ceil;
1059 | var pi = Math.PI;
1060 |
1061 | for (var i = 0; i < cities.length; i++) {
1062 | var total = linkModels.origins.total(cities[i].counts),
1063 | latlng = projection([cities[i].longitude,
1064 | cities[i].latitude]),
1065 | r = ceil(circleScale(total));
1066 | context.beginPath();
1067 | context.arc(latlng[0], latlng[1], r, 0, pi * 2);
1068 | context.fill();
1069 | }
1070 | }
1071 | },
1072 |
1073 | // Draw the city nodes
1074 | targets: {
1075 | active: true,
1076 | order: -2,
1077 | draw: function(context) {
1078 | context.globalAlpha = 0.65;
1079 | context.strokeStyle = "#fff";
1080 | context.fillStyle = "#fff";
1081 |
1082 | var cities = linkModels.targets.getCities();
1083 |
1084 | var ceil = Math.ceil;
1085 | var pi = Math.PI;
1086 |
1087 | for (var i = 0; i < cities.length; i++) {
1088 | var total = linkModels.targets.total(cities[i].counts),
1089 | latlng = projection([cities[i].longitude,
1090 | cities[i].latitude]),
1091 | r = ceil(circleScale(total));
1092 | context.beginPath();
1093 | context.arc(latlng[0], latlng[1], r, 0, pi * 2);
1094 | context.stroke();
1095 | context.fillRect(latlng[0] - 1, latlng[1] - 1, 2, 2);
1096 | }
1097 | }
1098 | },
1099 |
1100 |
1101 | // Draw the target impact
1102 | targetImpact: {
1103 | active: true,
1104 | impactRadiusScale: d3.scale.linear().domain([1, 40]).range([1, 30]),
1105 | impactOpacityScale: d3.scale.linear().domain([1, 40]).range([1, 0]),
1106 | impactWidth: 1,
1107 |
1108 | draw: function(ctx) {
1109 | var pi = Math.PI;
1110 |
1111 | ctx.fillStyle = "#f00";
1112 | nodeModel.get(nodeModel.TARGETS)
1113 | .forEach(function(n) {
1114 | var c = d3.rgb(colorizer(n.service)),
1115 | afterArrival = n.age - n["arrivalAge"];
1116 | r = 10;
1117 |
1118 | if ("arrivalAge" in n) {
1119 | var r = this.impactRadiusScale(afterArrival);
1120 | ctx.save();
1121 | ctx.globalAlpha = this.impactOpacityScale(afterArrival);
1122 | ctx.strokeStyle = c.toString();
1123 | ctx.lineWidth = this.impactWidth;
1124 | ctx.beginPath();
1125 | ctx.arc(n.x, n.y, r, 0, 2 * pi);
1126 | ctx.closePath();
1127 | ctx.stroke();
1128 | ctx.restore();
1129 | }
1130 |
1131 | if (n.path.length > 0) {
1132 | var point = n.path[n.path.length - 1];
1133 | if (n.x != point.x && n.y != point.y) {
1134 | ctx.save();
1135 | var grd = ctx.createLinearGradient(
1136 | n.x, n.y, point.x, point.y);
1137 | grd.addColorStop(0, rgbaString(c, 1));
1138 | grd.addColorStop(1, rgbaString(c, 0));
1139 | ctx.lineCap = 'round';
1140 | ctx.lineWidth = 2;
1141 | ctx.beginPath();
1142 | ctx.moveTo(n.x, n.y);
1143 | ctx.strokeStyle = grd;
1144 | ctx.lineTo(point.x, point.y);
1145 | ctx.closePath();
1146 | ctx.stroke();
1147 | ctx.restore();
1148 | }
1149 | }
1150 |
1151 | ctx.drawImage(particler(c.r, c.g, c.b, 1),
1152 | n.x - r / 2, n.y - r / 2, r, r);
1153 |
1154 | }, this);
1155 | }
1156 | },
1157 |
1158 | // Draw the provided links
1159 | // A link: {source: _, target: _, color: _, width: _}
1160 | // source/target: {x: _, y: _, strokeStyle: _, fillStyle: _}
1161 | links: {
1162 | active: true,
1163 | order: -1,
1164 | data: [],
1165 |
1166 | draw: function(context) {
1167 | var pi = Math.PI;
1168 |
1169 | for (var i = 0; i < this.data.length; i++) {
1170 | context.beginPath();
1171 | context.strokeStyle = this.data[i].color;
1172 | context.moveTo(this.data[i].source.x, this.data[i].source.y);
1173 | context.lineTo(this.data[i].target.x, this.data[i].target.y);
1174 | context.lineWidth = this.data[i].width;
1175 | context.lineCap = "round";
1176 | context.stroke();
1177 |
1178 | context.lineWidth = 2;
1179 | context.beginPath();
1180 | context.arc(this.data[i].source.x, this.data[i].source.y,
1181 | this.data[i].source.r || 5, 0, pi * 2);
1182 | if (this.data[i].source.fillStyle) {
1183 | context.fillStyle = this.data[i].source.fillStyle;
1184 | context.fill();
1185 | }
1186 | if (this.data[i].source.strokeStyle) {
1187 | context.strokeStyle = this.data[i].source.strokeStyle;
1188 | context.stroke();
1189 | }
1190 |
1191 | context.beginPath();
1192 | context.fillStyle = this.data[i].target.fillStyle || "#fff";
1193 | context.arc(this.data[i].target.x, this.data[i].target.y,
1194 | this.data[i].target.r || 5, 0, pi * 2);
1195 | if (this.data[i].target.fillStyle) {
1196 | context.fillStyle = this.data[i].target.fillStyle;
1197 | context.fill();
1198 | }
1199 | if (this.data[i].target.strokeStyle) {
1200 | context.strokeStyle = this.data[i].target.strokeStyle;
1201 | context.stroke();
1202 | }
1203 | }
1204 | }
1205 | }
1206 |
1207 | },
1208 |
1209 | // State
1210 | _activeCanvas: {
1211 | canvas: canvas,
1212 | context: canvas.node().getContext("2d")
1213 | },
1214 |
1215 | _clearContext: function(context) {
1216 | context.save();
1217 | context.clearRect(0, 0, width, height)
1218 | context.restore();
1219 | },
1220 |
1221 | _drawSort: function (d1, d2) { return d1.order || 0 - d2.order || 0; },
1222 |
1223 | redraw: function() {
1224 | this.drawStart = new Date().getTime();
1225 |
1226 | // Draw the active drawings
1227 | this._clearContext(this._activeCanvas.context);
1228 |
1229 | for (var drawing in this.drawings) {
1230 | if (this.drawings[drawing].active) {
1231 | this.drawings[drawing].draw(this._activeCanvas.context);
1232 | }
1233 | }
1234 |
1235 | var that = this;
1236 |
1237 | var nextFrame = 1000 / 30 - (new Date().getTime() - this.drawStart);
1238 |
1239 | if (nextFrame < 0) nextFrame = 0;
1240 |
1241 | this._timeout = setTimeout(function() { that.redraw() }, nextFrame);
1242 | },
1243 |
1244 | start: function(interval) {
1245 | this.redraw();
1246 | },
1247 |
1248 | stop: function() {
1249 | clearTimeout(this._timeout);
1250 | }
1251 | }
1252 |
1253 | // Event handling for setting the painter's links
1254 | var _ = (function() {
1255 | var previous;
1256 | function cityKey(n) {
1257 | return [n.country, n.city];
1258 | }
1259 |
1260 | canvas.on("mousemove", function() {
1261 | // TODO -- this is a hacky mess
1262 | var nearestOrigin = linkModels.origins.pixelsFromNearest(d3.mouse(this)),
1263 | nearestTarget = linkModels.targets.pixelsFromNearest(d3.mouse(this)),
1264 | nearest, msg, model, mapfn, strokeOrigin, strokeTarget;
1265 | if (nearestOrigin || nearestTarget) {
1266 | if (!nearestTarget || nearestOrigin.distance <= nearestTarget.distance) {
1267 | nearest = nearestOrigin;
1268 | msg = "Attacks originating from: ";
1269 | model = linkModels.origins;
1270 | strokeOrigin = true;
1271 | }
1272 | if (!nearestOrigin || nearestTarget.distance < nearestOrigin.distance) {
1273 | nearest = nearestTarget;
1274 | msg = "Attacks targeting: ";
1275 | model = linkModels.targets;
1276 | strokeTarget = true;
1277 | }
1278 | }
1279 |
1280 | if (nearest && nearest.distance < 20) {
1281 | var key = cityKey(nearest);
1282 | if (key !== previous) {
1283 | painter.drawings.links.data =
1284 | model.cityToLinks(nearest, strokeOrigin, strokeTarget);
1285 | displayLabel.set(msg +
1286 | (nearest.city === "" ? "" : nearest.city)
1287 | + ", " + countryModel.getByIso2(nearest.country).country);
1288 | }
1289 | } else {
1290 | previous = key;
1291 | painter.drawings.links.data.length = 0;
1292 | displayLabel.clear();
1293 | }
1294 | });
1295 | })();
1296 |
1297 | /*
1298 | * The legend
1299 | */
1300 |
1301 | var _ = (function() {
1302 | var attack = d3.select("#particle-legend-content"),
1303 | width = 20, height = 20;
1304 |
1305 | attack.append("canvas")
1306 | .attr("width", width * 1)
1307 | .attr("height", height * 1)
1308 | .node().getContext("2d")
1309 | .drawImage(particler(255, 255, 255, 1),
1310 | width / 8, height / 8, width, height);
1311 | /*var legend = d3.select("#legend-container")
1312 | .append("div")
1313 | .attr("id", "legend");
1314 |
1315 | var attack = legend.append("div"),
1316 | width = 20, height = 20;
1317 | attack.append("h4").text("Each particle represents an attack.");
1318 | attack.append("canvas")
1319 | .attr("width", width * 2)
1320 | .attr("height", height * 2)
1321 | .node().getContext("2d")
1322 | .drawImage(particler(255, 255, 255, 1),
1323 | width / 2, height / 2, width, height);
1324 |
1325 | var clusters = legend.append("div").attr("class", "clusters");
1326 | clusters.append("h4").text("Attack origins are grouped into clusters.");
1327 |
1328 | var height = 30;
1329 | var clusterList = clusters.append("ul").selectAll("li")
1330 | .data([1, 10, 200])
1331 | .enter().append("li");
1332 | clusterList.append("svg")
1333 | .style("width", function(d) { return circleScale(d) * 2; })
1334 | .style("height", height)
1335 | .append("circle")
1336 | .attr("fill", "white")
1337 | .attr("cy", function(d) { return height - circleScale(d); })
1338 | .attr("cx", function(d) { return circleScale(d); })
1339 | .attr("r", function(d) { return circleScale(d); });
1340 | clusterList.append("p")
1341 | .text(function(d) { return d; });
1342 |
1343 | var countryColors = legend.append("div").attr("class", "country-colors");
1344 | countryColors.append("h4").text("Countries are shaded in as they're attacked.");
1345 |
1346 | var r = 4;
1347 | var countryColorList = countryColors.append("ul").selectAll("li")
1348 | .data([1, 5, 25, 100, 500])
1349 | .enter().append("li");
1350 | countryColorList.append("svg")
1351 | .style("width", r * 2)
1352 | .style("height", r * 2)
1353 | .append("circle")
1354 | .attr("fill", function(d) { return settings.countryColor(d); })
1355 | .attr("cy", r)
1356 | .attr("cx", r)
1357 | .attr("r", r);
1358 | countryColorList.append("p")
1359 | .text(function(d) { return d; });*/
1360 | })();
1361 |
1362 | /*
1363 | * Stats the state machine
1364 | */
1365 | function Stats(params) {
1366 | this.state = params.state || d3.map();
1367 | this.elt = params.elt || d3.select("body");
1368 | this.tag = params.tag || "div";
1369 |
1370 | this.insert = function(incoming) {
1371 | // Insert a new item, updating the state. params.insert should mutate
1372 | params.insert(incoming, this.state);
1373 | };
1374 |
1375 | this.data = function() {
1376 | // Get the data as a list
1377 | if (params.data) return params.data(this.state); else this.state;
1378 | }
1379 |
1380 | this.redraw = function() {
1381 | if (params.redraw) {
1382 | params.redraw()
1383 | } else {
1384 | this.elt.selectAll(this.tag)
1385 | .data(this.data())
1386 | .enter().append(this.tag)
1387 | .text(function(d) { return d});
1388 | }
1389 | }
1390 | }
1391 |
1392 |
1393 | var statsManager = {
1394 | insert: function(incoming) {
1395 | for (var i = 0; i < this.stats.length; ++i) {
1396 | this.stats[i].insert(incoming);
1397 | }
1398 | },
1399 |
1400 | redraw: function() {
1401 | for (var i = 0; i < this.stats.length; i++) {
1402 | this.stats[i].redraw();
1403 | }
1404 | },
1405 |
1406 | stats: [
1407 | new Stats({
1408 | // Color countries
1409 | state: {sources: {}, targets: {}},
1410 |
1411 | insert: function(d, state) {
1412 | function pushState(m, key) {
1413 | if (key in m) {
1414 | m[key] = m[key] + 1;
1415 | } else {
1416 | m[key] = 1;
1417 | }
1418 | }
1419 |
1420 | //pushState(state.sources, d.country);
1421 | pushState(state.targets, d.country2);
1422 |
1423 | //d3.select("#" + d.country)
1424 | // .attr("fill", d3.rgb(colorScale(state.sources[d.country]), 0, 0).toString());
1425 | d3.select("#" + d.country2)
1426 | .attr("fill", settings.countryColor(state.targets[d.country2]));
1427 | },
1428 |
1429 | redraw: function() {}
1430 | }),
1431 |
1432 | // Origin data table
1433 | new Stats({
1434 | state: d3.map(),
1435 |
1436 | insert: function(incoming, state) {
1437 | this.updated = incoming.country;
1438 | if (state.has(incoming.country)) {
1439 | state.set(incoming.country,
1440 | state.get(incoming.country) + 1);
1441 | } else {
1442 | state.set(incoming.country, 1);
1443 | }
1444 | },
1445 |
1446 | redraw: function() {
1447 | var data = this.state.entries()
1448 | .sort(function(d1, d2) { return d2.value - d1.value; })
1449 | .slice(0, settings.topTableRows),
1450 | updated = this.updated;
1451 |
1452 | var rows = d3.select("#left-data").selectAll("tr.row")
1453 | .data(data, function(d) { return d.key; });
1454 | rows.enter()
1455 | .append("tr")
1456 | .attr("class", "row")
1457 | .on("mouseenter", function(d) {
1458 | var country = countryModel.getByIso2(d.key);
1459 | displayLabel.set("Attacks originating from: " +
1460 | (country ? country.country : d.key));
1461 |
1462 | // On mouseenter, use all country data to create links
1463 | painter.drawings.links.data =
1464 | linkModels.origins.getCountry(d.key)
1465 | .reduce(function(acc, city) {
1466 | return acc.concat(
1467 | linkModels.origins.cityToLinks(
1468 | city, true, false));
1469 | }, []);
1470 | })
1471 | .on("mouseleave", function() {
1472 | displayLabel.clear();
1473 | });
1474 | rows.sort(function(d1, d2) { return d2.value - d1.value; });
1475 | rows.exit().remove();
1476 |
1477 | rows.filter(function(d) {return d.key == updated})
1478 | .style("color", settings.triggerColor)
1479 | .transition()
1480 | .duration(1000)
1481 | .style("color", "white");
1482 |
1483 | var cols = rows.selectAll("td")
1484 | .data(function(d) {
1485 | var country = countryModel.getByIso2(d.key);
1486 | return [
1487 | '
',
1489 | spanWrap(d.value, ["numeric"]),
1490 | flagTag(d.key),
1491 | (country ? country.country : d.key)]; });
1492 | cols.enter().append("td");
1493 | cols.html(function(d) { return d; });
1494 | cols.exit().remove();
1495 | }
1496 | }),
1497 |
1498 | // Targeted data table
1499 | new Stats({
1500 | state: d3.map(),
1501 |
1502 | insert: function(incoming, state) {
1503 | this.updated = incoming.country2;
1504 | if (state.has(incoming.country2)) {
1505 | state.set(incoming.country2,
1506 | state.get(incoming.country2) + 1);
1507 | } else {
1508 | state.set(incoming.country2, 1);
1509 | }
1510 | },
1511 |
1512 | redraw: function() {
1513 | var data = this.state.entries()
1514 | .sort(function(d1, d2) { return d2.value - d1.value; })
1515 | .slice(0, settings.topTableRows),
1516 | updated = this.updated;
1517 |
1518 | var rows = d3.select("#right-data").selectAll("tr.row")
1519 | .data(data, function(d) { return d.key; });
1520 | rows.enter()
1521 | .append("tr")
1522 | .attr("class", "row")
1523 | .on("mouseenter", function(d) {
1524 | var country = countryModel.getByIso2(d.key);
1525 | displayLabel.set("Attacks targeting: " +
1526 | (country ? country.country : d.key));
1527 |
1528 | // On mouseenter, use all country data to create links
1529 | painter.drawings.links.data =
1530 | linkModels.targets.getCountry(d.key)
1531 | .reduce(function(acc, city) {
1532 | return acc.concat(
1533 | linkModels.targets.cityToLinks(
1534 | city, false, true));
1535 | }, []);
1536 | })
1537 | .on("mouseleave", function() {
1538 | displayLabel.clear();
1539 | });
1540 | rows.sort(function(d1, d2) { return d2.value - d1.value; });
1541 | rows.exit().remove();
1542 |
1543 | rows.filter(function(d) {return d.key == updated})
1544 | .style("color", "blue")
1545 | .transition()
1546 | .duration(1000)
1547 | .style("color", "white");
1548 |
1549 | var cols = rows.selectAll("td")
1550 | .data(function(d) {
1551 | var country = countryModel.getByIso2(d.key);
1552 | return [
1553 | '
',
1555 | spanWrap(d.value, ["numeric"]),
1556 | flagTag(d.key),
1557 | (country ? country.country : d.key)]; });
1558 | cols.enter().append("td");
1559 | cols.html(function(d) { return d; });
1560 | cols.exit().remove();
1561 | }
1562 | }),
1563 |
1564 | new Stats(
1565 | {state: d3.map(),
1566 |
1567 | insert: function(incoming) {
1568 | this.updated = incoming.service;
1569 | if (this.state.has(incoming.service)) {
1570 | this.state.set(incoming.service,
1571 | this.state.get(incoming.service) + 1);
1572 | } else {
1573 | this.state.set(incoming.service, 1);
1574 | }
1575 | },
1576 |
1577 | redraw: function() {
1578 | var data = this.state.entries()
1579 | .sort(function(d1, d2) { return d2.value - d1.value; })
1580 | .slice(0, settings.portTableRows),
1581 | updated = this.updated;
1582 |
1583 | var rows = d3.select("#bottom-right-data").selectAll("tr.row")
1584 | // XXX - I'm not sure why d is undef the first time through.
1585 | .data(data, function(d, i) { return d ? d.key : i; });
1586 | rows.enter()
1587 | .append("tr")
1588 | .attr("class", "row")
1589 | .on("mouseenter", function(d) {
1590 | displayLabel.set("Attacks made over: " +
1591 | (d.service ? d.service : "unknown") +
1592 | " [" + d.key + "]");
1593 | painter.drawings.links.data =
1594 | linkModels.origins.dPortLinks(d.key).map(function(c) {
1595 | var r = circleScale(c.count),
1596 | color = colorizer(c.service);
1597 | return {
1598 | source: {
1599 | x: c.source.pt[0],
1600 | y: c.source.pt[1],
1601 | fillStyle: color,
1602 | r: r
1603 | },
1604 | target: {
1605 | x: c.target.pt[0],
1606 | y: c.target.pt[1],
1607 | strokeStyle: color,
1608 | r: r
1609 | },
1610 | width: lineScale(c.count),
1611 | color: colorizer(c.service)
1612 | }
1613 | });
1614 | })
1615 | .on("mouseleave", function(d) {
1616 | displayLabel.clear();
1617 | })
1618 | rows.sort(function(d1, d2) { return d2.value - d1.value; });
1619 | rows.exit().remove();
1620 |
1621 | rows.filter(function(d) {return d.key == updated})
1622 | .style("color", function(d) { return colorizer(d.key); })
1623 | .transition()
1624 | .duration(1000)
1625 | .style("color", "white");
1626 |
1627 | var cols = rows.selectAll("td")
1628 | .data(function(d) {
1629 | return [
1630 | '
',
1632 | spanWrap(d.value, ["numeric"]),
1633 | '● ',
1635 | d.key
1636 | ]; });
1637 | //function(d) { return d; });
1638 | cols.enter().append("td");
1639 | cols.html(function(d) { return d; });
1640 | cols.exit().remove();
1641 | }
1642 | }),
1643 |
1644 | new Stats({
1645 | // #console stats manager
1646 | state: [],
1647 |
1648 | insert: function(incoming, state) {
1649 | state.push(incoming);
1650 | while (state.length > settings.consoleTableRows) {
1651 | state.shift();
1652 | }
1653 | return state;
1654 | },
1655 |
1656 | redraw: function() {
1657 | var that = this;
1658 | var rows = d3.select("#events-data").selectAll("tr.row")
1659 | .data(this.state, function(d) { return d.id; });
1660 |
1661 | rows.enter().append("tr")
1662 | .style("color", function(d) { return colorizer(d.service); })
1663 | .attr("class", "row");
1664 | rows.exit().remove();
1665 |
1666 | var cols = rows.selectAll("td")
1667 | .data(function(d) {
1668 | return [
1669 | d.datetime,
1670 | spanWrap(
1671 | (d.city === "" ? "unknown" : d.city) + ", " +
1672 | countryModel.getByIso2(d.country).country,
1673 | ["location", "overflow"]),
1674 | d.md5,
1675 | d.hostip,
1676 | spanWrap(
1677 | (d.city2 === "" ? "unknown" : d.city2) + ", " +
1678 | countryModel.getByIso2(d.country2).country,
1679 | ["location", "overflow", "numeric"]),
1680 | d.service]; });
1681 | cols.enter().append("td")
1682 | .html(function(d) { return d; });
1683 | cols.exit().remove();
1684 | }
1685 |
1686 | })
1687 | ]};
1688 |
1689 | // Keep track of the rate
1690 | var rateTicker = {
1691 | data: [],
1692 | interval: 90000,
1693 | graph: d3.select("#content")
1694 | .append("svg")
1695 | .attr("id", "rate-graph"),
1696 | x: d3.time.scale().range([800, 0]),
1697 | opacity: d3.time.scale().range([0, 1]),
1698 |
1699 | push: function(d) {
1700 | this.data.push({date: Date.now(), key: d.service});
1701 | },
1702 |
1703 | clean: function(toDate) {
1704 | // Clean out old data
1705 | while (this.data.length > 0 && this.data[0].date < toDate) {
1706 | this.data.shift();
1707 | }
1708 | },
1709 |
1710 | step: function() {
1711 | var that = this,
1712 | now = Date.now(),
1713 | range = [now - this.interval, now];
1714 | this.clean(range[0]);
1715 | this.x.domain(range);
1716 | this.opacity.domain(range);
1717 |
1718 | var simpleLine = function(h) {
1719 | return function(d) {
1720 | var cx = that.x(d.date);
1721 | return d3.svg.line()([[cx, 0], [cx, h || 20]])}};
1722 | var ticks = this.graph.selectAll("path.tick")
1723 | .data(this.data, function(d) { return d.date; });
1724 |
1725 | ticks.enter().append("path")
1726 | .attr("class", "tick")
1727 | .attr("d", simpleLine())
1728 | .style("stroke", function(d) { return colorizer(d.key); });
1729 |
1730 | ticks.exit().remove();
1731 |
1732 | ticks
1733 | //.transition().duration(30)
1734 | .attr("d", simpleLine())
1735 | .style("opacity", function(d) { return that.opacity(d.date); });
1736 | },
1737 |
1738 | start: function() {
1739 | var that = this;
1740 | setInterval(function() { that.step(); }, 50);
1741 | }
1742 | };
1743 |
1744 |
1745 | var wsDiscTime = 0;
1746 |
1747 | function start(loc, psk) {
1748 | var webSocket = new WebSocket(loc || settings.wsHost);
1749 |
1750 | var pauser = {
1751 | elt: d3.selectAll(".controls"),
1752 | _buffer: [],
1753 |
1754 | unbuffer: function(d) {
1755 | while (this._buffer.length > 0) {
1756 | this.insert(this._buffer.shift());
1757 | }
1758 | statsManager.redraw();
1759 | },
1760 |
1761 | insert: function(d) {
1762 | nodeModel.pushAttack(d);
1763 | statsManager.insert(d);
1764 | for (var model in linkModels) {
1765 | linkModels[model].insert(d);
1766 | }
1767 | rateTicker.push(d);
1768 |
1769 | d.pruneTS = new Date().getTime() / 1000 + settings.pruneInterval;
1770 | timestampedData.push(d);
1771 | },
1772 |
1773 | push: function(d) {
1774 | if (this.paused()) {
1775 | this._buffer.push(d);
1776 | } else {
1777 | this.insert(d);
1778 | statsManager.redraw();
1779 | }
1780 | },
1781 |
1782 | paused: function() {
1783 | return this.elt.node().dataset.paused === "true";
1784 | },
1785 |
1786 | toggle: function() {
1787 | var dataset = this.elt.node().dataset;
1788 | var button = d3.selectAll(".play-pause");
1789 |
1790 | if (this.paused()) {
1791 | button.classed("icon-play", false);
1792 | button.classed("icon-pause", true);
1793 | this.elt.node().dataset.paused = "false";
1794 | this.unbuffer();
1795 | } else {
1796 | button.classed("icon-pause", false);
1797 | button.classed("icon-play", true);
1798 | this.elt.node().dataset.paused = "true";
1799 | }
1800 | }
1801 | }
1802 | pauser.elt.on("click", function() { pauser.toggle(); });
1803 |
1804 | webSocket.onopen = function() {
1805 | wsDiscTime = 0;
1806 | d3.select("#events-data").selectAll("tr.row").remove();
1807 | webSocket.send(psk || settings.psk);
1808 | };
1809 |
1810 | webSocket.onmessage = function(evt) {
1811 | if (!evt) {
1812 | return;
1813 | }
1814 |
1815 |
1816 | // Parse the json to a js obj and clean the data
1817 | var datum = eval("(" + evt.data + ")");
1818 |
1819 | if (datum.longitude == 0 && datum.latitude == 0) {
1820 | datum.longitude = -5;
1821 | datum.latitude = -50;
1822 | }
1823 |
1824 | var startLoc = projection([datum.longitude, datum.latitude]);
1825 | var endLoc = projection([datum.longitude2, datum.latitude2]);
1826 |
1827 | if (datum.error) {
1828 | showMessage("ERROR: " + datum.error.msg);
1829 | }
1830 |
1831 | for (var prop in datum) {
1832 | if (settings.numberProps.indexOf(prop) !== -1) {
1833 | datum[prop] = Number(datum[prop]);
1834 | }
1835 | }
1836 |
1837 | function cleanCountry(country) {
1838 | // Clean incoming country code
1839 | if (country === "USA") {
1840 | return "US";
1841 | }
1842 | return country
1843 | }
1844 |
1845 | datum.country = cleanCountry(datum.country);
1846 | datum.country2 = cleanCountry(datum.country2);
1847 |
1848 | datum.service = datum.type;
1849 | datum.cx = startLoc[0];
1850 | datum.cy = startLoc[1];
1851 | datum.x = startLoc[0];
1852 | datum.y = startLoc[1];
1853 | datum.targetX = endLoc[0];
1854 | datum.targetY = endLoc[1];
1855 | datum.id = getID();
1856 | datum.datetime = (new Date()).toISOString()
1857 | .replace("T", " ")
1858 | .slice(0, -2);
1859 |
1860 | console.log(datum);
1861 | pauser.push(datum);
1862 | };
1863 |
1864 | webSocket.onclose = function() {
1865 | //try to reconnect in 5 seconds
1866 | var interval = 500;
1867 |
1868 | wsDiscTime += 500;
1869 |
1870 | d3.select("#events-data").selectAll("tr.row").remove();
1871 | d3.select("#events-data").append("tr").attr('class', 'row').html(" Loading... ");
1872 |
1873 | if (wsDiscTime > settings.wsTimeout) {
1874 | showMessage("We are having difficulties in the WebSocket connectivity. We will continue trying...");
1875 | wsDiscTime = 0;
1876 | }
1877 |
1878 | setTimeout(function(){
1879 | console.log("websocket closed, reconnecting in " + interval + "ms");
1880 | start(loc, psk);
1881 | }, interval);
1882 | };
1883 |
1884 | return webSocket;
1885 | }
1886 |
1887 | /*
1888 | * Load external data, and manage loading state
1889 | */
1890 |
1891 | queue()
1892 | .defer(d3.json, "data/readme-world.json")
1893 | .defer(d3.csv, "data/country-codes.csv")
1894 | .await(function (error, world, rawPorts, countryCodes) {
1895 | // Update the countryModel
1896 | countryModel.set(countryCodes);
1897 | countryModel.push({iso2: "O1", country: "Mil/Gov"});
1898 |
1899 | // Temporary mapping to key the map
1900 | var mapCodes = {};
1901 | countryCodes.forEach(function(d) { mapCodes[Number(d.isonum)] = d.iso2; });
1902 |
1903 | // Enter the countries
1904 | svg.append("g")
1905 | .attr("class", "world")
1906 | .selectAll("path")
1907 | .data(topojson.feature(world, world.objects.countries).features)
1908 | .enter().insert("path")
1909 | .attr("class", "country")
1910 | .attr("id", function(d) { return mapCodes[d.id]; })
1911 | .attr("fill", settings.countryColor(0))
1912 | .attr("d", path);
1913 |
1914 | ports = parsePorts(rawPorts);
1915 |
1916 | loadingToggle();
1917 | var webSocket = start();
1918 | nodeModel.start();
1919 | painter.start();
1920 | rateTicker.start();
1921 | });
1922 |
1923 | // Export the external API
1924 | window.IPViking = {
1925 | settings: settings
1926 | }
1927 |
1928 | var unknownLoc = projection([-5, -50]);
1929 |
1930 | d3.selectAll("#unknown-icon").style({'left': unknownLoc[0] - 18, 'top': unknownLoc[1] - 18});
1931 |
1932 | setInterval(function () { prune(); }, 30000);
1933 | })(window);
1934 |
--------------------------------------------------------------------------------
/nodejs/main.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | var ws = require("nodejs-websocket")
3 | var sleep = require('sleep');
4 | var geoip = require('geoip-lite');
5 | var _ = require('underscore');
6 | var mysql = require('mysql');
7 | var connection = mysql.createConnection({
8 | host : '127.0.0.1',
9 | user : 'your_user',
10 | password : 'your_password',
11 | port : 3306,
12 | database : 'your_database'
13 | });
14 | var id=0;
15 |
16 | //连接mysql
17 | connection.connect();
18 |
19 | //创建服务器
20 | var server = ws.createServer(function (conn) {
21 | console.log("New connection")
22 | conn.on("text", function (str) {
23 | console.log("Received "+str)
24 | })
25 | conn.on("close", function (code, reason) {
26 | console.log("Connection closed")
27 | })
28 | }).listen(8085)
29 |
30 | //发送实时消息
31 | setInterval(function () {
32 | try {
33 | sql = 'SELECT * from td_protectclient_attack_log2 where id>'+id+' and attacktype!=\'360webscan scan\'';
34 | if(id==0)
35 | sql = sql+' order by id desc limit 100';
36 | else
37 | sql = sql+'limit 10';
38 | connection.query(sql, function(err, rows, fields) {
39 | if (err) throw err;
40 | _.each(rows, function(a) {
41 | //console.log(a);
42 | id = Math.max(id, a.id);
43 | var attack_ll = geoip.lookup(a.clientip);
44 | var host_ll = geoip.lookup(a.ipstr);
45 | //console.log(host_ll);
46 | server.connections.forEach(function (conn) {
47 | if (attack_ll && attack_ll.ll && host_ll && host_ll.ll)
48 | conn.sendText('{"latitude":"'+attack_ll.ll[0]+'","longitude":"'+attack_ll.ll[1]+'","countrycode":"'+attack_ll.country+'","country":"'+attack_ll.country+'","city":"'+attack_ll.city+'","latitude2":"'+host_ll.ll[0]+'","longitude2":"'+host_ll.ll[1]+'","countrycode2":"'+host_ll.country+'","country2":"'+host_ll.country+'","city2":"'+host_ll.city+'","type":"'+a.attacktype+'","md5":"'+a.clientip+'","hostip":"'+a.ipstr+'"}');
49 | });
50 | });
51 | });
52 | } catch (e) {
53 | console.log('Error!');
54 | console.log(e);
55 | }
56 | }, 1000);
57 |
--------------------------------------------------------------------------------
/presentations.js:
--------------------------------------------------------------------------------
1 | ;"use strict";
2 | (function(IPViking) {
3 | // Toggle table size settings
4 | state = false;
5 | states = [{topTableRows: 16, portTableRows: 15, consoleTableRows: 16},
6 | {topTableRows: 10, portTableRows: 8, consoleTableRows: 8}];
7 | d3.select("body").on("keydown", function() {
8 | d3.event.preventDefault;
9 | if (d3.event.keyCode == 83) {
10 | for (var setting in states[state + 0]) {
11 | IPViking.settings[setting] = states[state + 0][setting];
12 | }
13 | state = !state;
14 | }
15 | });
16 | })(window.IPViking);
17 |
--------------------------------------------------------------------------------