WassUp Real Time Analytics - Version 1.8.3

Version Description

Download this release

Release Info

Developer michelem
Plugin Icon 128x128 WassUp Real Time Analytics
Version 1.8.3
Comparing to
See all releases

Code changes from version 1.8.2 to 1.8.3

badhosts.txt CHANGED
@@ -737,7 +737,7 @@ hgh\-.*
737
  hidor\.com
738
  himailer\.com
739
  himsearch\.com
740
- hinet\.net
741
  hitprofile\.com
742
  hj68\.com
743
  hlplmanhds\.biz
737
  hidor\.com
738
  himailer\.com
739
  himsearch\.com
740
+ \.sg[0-9]+\.myweb\.hinet\.net
741
  hitprofile\.com
742
  hj68\.com
743
  hlplmanhds\.biz
css/images/Thumbs.db ADDED
Binary file
css/images/list-bg.png CHANGED
Binary file
css/images/list-bg2.png CHANGED
Binary file
css/images/list-bg3.png CHANGED
Binary file
css/wassup.css CHANGED
@@ -3,17 +3,20 @@
3
  * wassup.css - stylesheet for WassUp plugin
4
  */
5
  #wassup-wrap {
6
- padding: 1px 5px 3px;
7
  min-height: 500px;
8
- background-color: #efebef;
 
 
9
  border:1px solid #d6d7d6;
10
- -moz-border-radius: 10px 10px 0 0;
11
- -webkit-border-top-left-radius: 10px;
12
- -webkit-border-top-right-radius: 10px;
13
- -khtml-border-top-left-radius: 10px;
14
- -khtml-border-top-right-radius: 10px;
15
- border-top-right-radius: 10px;
16
- border-top-left-radius: 10px;
 
 
17
  }
18
  #wassup-wrap table { border-collapse: collapse; padding: 2px; }
19
  #wassup-wrap h2 {
@@ -23,7 +26,7 @@
23
  }
24
  #wassup-wrap img {
25
  display: inline;
26
- vertical-align:bottom;
27
  margin: 0 2px 2px 0;
28
  padding:0;
29
  }
@@ -34,14 +37,16 @@
34
  }
35
  #wassup-wrap td.legend a { border-bottom: 1px solid; }
36
  #wassup-wrap a:visited { color: #229; }
37
- #wassup-wrap a:hover { color: #d11; }
 
38
  .wassup-icon {}
39
  .wassup-content { min-height:225px; }
40
  /*
41
  * for wassup admin top menu styles in Wordpress 2.7+ */
42
  .wassup-menu-link {
43
  float: right;
44
- font-family: "Lucida Grande", Verdana, Arial, "Bitstream Vera Sans", sans-serif;
 
45
  height: 22px;
46
  padding: 0;
47
  margin: 0 4px 0 0;
@@ -85,7 +90,6 @@
85
  padding: 0 6px 0 6px;
86
  height: 22px;
87
  line-height: 22px;
88
- font-size: 10px;
89
  }
90
  #wassup-menu li.current a {
91
  color: #00284a;
@@ -109,6 +113,8 @@
109
  border-bottom: 0 none;
110
  }
111
  #wassup-menu li.current, #wassup-menu-link:active {
 
 
112
  color: #00284a;
113
  background: url("images/link.png") no-repeat bottom center;
114
  border-top: 1px solid #c8c8c4;
@@ -132,13 +138,17 @@ div.main-tabs {
132
  padding: 2px 1px 1px;
133
  color: #445;
134
  background-color: #dedade;
135
- box-shadow: 0 0 5px rgba(24, 24, 64, 0.9); /* 0 0 2px rgba(108,108,168, 0.8); */
136
- -moz-box-shadow: 0 0 5px rgba(24, 24, 64, 0.9);
137
- -webkit-box-shadow: 0 0 5px rgba(24, 24, 64, 0.9);
138
- border: 1px solid #c9d9e9; /* #a5a5bb; #efebef; */
139
- /* border-radius: 3px;
140
- -webkit-border-radius: 3px;
141
- -moz-border-radius: 3px; */
 
 
 
 
142
  }
143
  .main-tabs a, .main-tabs a:link {
144
  color: #00b;
@@ -184,9 +194,9 @@ div.main-tabs {
184
  color: #dedede;
185
  background-color: #778;
186
  border: 1px solid #fafeee;
187
- box-shadow: 0 0 2px rgba(50, 80, 80, 0.3);
188
  -moz-box-shadow:0 0 2px rgba(50, 80, 80, 0.3);
189
  -webkit-box-shadow:0 0 2px rgba(50, 80, 80, 0.3);
 
190
  }
191
  .pagination .disabled {
192
  padding: 2px 5px 2px 5px;
@@ -215,19 +225,22 @@ div.main-tabs {
215
  padding: 1px 0 0 !important;
216
  font-size: 11px;
217
  background-color: #f4f6f6;
218
- border: 1px solid #c7c7cc; /* 89a; */
219
- border-bottom: 3px solid #347;
 
220
  }
221
  .sum-nav, .sum-nav-mark, .sum-spy {
222
  position: relative;
223
  clear: left;
224
- width: 100%;
225
  min-height: 50px;
226
  margin: 0 !important;
227
  padding: 22px 0 0;
228
  font-size: 11px;
229
  border-top: 1px solid #fffcff;
230
- border-bottom: 1px solid #ddd;
 
 
231
  background: url("images/list-bg.png") repeat-x;
232
  }
233
  .wassup-online .sum-nav { height:60px; }
@@ -246,15 +259,15 @@ div.main-tabs {
246
  div.sum-spy {
247
  margin: 12px 0 0 0 !important;
248
  padding: 1px 1px 0 !important;
249
- border-top: 1px solid #89a;
250
- border-right: 1px solid #789;
251
- border-left: 1px solid #789;
252
  border-bottom: 3px solid #347;
253
  min-height: 50px;
254
  background: #f4f6f6 url("images/list-bg.png") repeat-x;
255
- -webkit-box-shadow: 0 0 5px rgba(80, 100, 100, 0.5);
256
- box-shadow: 0 0 5px rgba(80, 100, 100, 0.5);
257
- -moz-box-shadow:0 0 5px rgba(80, 100, 100, 0.5);
258
  }
259
  .delbut {
260
  position: absolute;
@@ -272,9 +285,9 @@ div.sum-spy {
272
  margin: 0 !important;
273
  padding: 0;
274
  /* width: 100%; */
275
- height: 1px;
276
  clear: both;
277
- background-color: #347 /* #899; */
278
  }
279
  .sum-det, .sum-det-spy {
280
  display:block;
@@ -299,7 +312,7 @@ div.sum-spy {
299
  .det3 { padding-left: 20px; }
300
  .det1 a { font-weight: bold; border-bottom: 1px solid !important; }
301
  .det2 a, .det2 a:link, .sum-det span.det2 a {
302
- color: #349 !important; /*#00008c #00284a */
303
  }
304
  .det2 a:hover, .sum-det span.det2 a:hover {
305
  color: #d54d22 !important;
@@ -327,7 +340,10 @@ div.sum-spy {
327
  width: 140px;
328
  height: 28px;
329
  padding-top: 5px !important;
330
- border: 1px solid #cacad0;
 
 
 
331
  }
332
  .sum-box-ip {
333
  font-family: tahoma, verdana, arial, sans-serif;
@@ -364,36 +380,54 @@ div.sum-spy {
364
  margin: 5px auto 0 auto !important;
365
  line-height: 1.1em;
366
  }
367
- #toptenchart a { color: #464646; }
 
 
 
 
 
 
 
368
  #toptenchart a:hover { color: #d54d22; }
369
  ul.charts {
370
  list-style-type: none;
371
  margin: 0;
372
  padding: 0;
 
 
373
  border-bottom: 1px solid #dedede;
 
374
  }
375
  li.charts {
 
376
  list-style-type: none;
377
- font-size: 11px;
 
378
  border-top: 1px #ddd solid;
379
- margin: 0px 0 4px 0;
380
- padding: 2px 4px 4px 4px;
381
  background: url("images/list-bg3.png");
382
  }
383
  li.chartsT {
 
 
 
384
  list-style-type: none;
385
  color: #2683ae;
386
- font-size: 11px;
387
  border-bottom: 2px solid #bfd0dd;
388
- margin: 2px 0 0 0;
389
- padding: 2px 4px 2px 4px;
390
  background: #cee1ef;
391
  }
 
392
  .sum-rec ul { border-top: 1px solid #999; }
393
  .detail-data {
394
  margin: 0 auto !important;
395
  clear:both;
396
- border-bottom: 0 none;
 
 
 
397
  color: #445;
398
  font-size: 11px;
399
  }
@@ -401,15 +435,16 @@ li.chartsT {
401
  .detail-data a:hover { color: #c64 !important; }
402
  .detail-data ul {
403
  list-style-type: none;
404
- width: 100%;
405
  margin: 0;
406
  padding: 3px 0 4px 0;
407
  font-size: 11px;
408
  border-top: 1px solid #ddd;
409
  border-bottom: 1px solid #bbb;
410
  }
 
411
  ul.searcheng {
412
- background-color: #abdbff; /* #adf; */
413
  border-color: #9cd;
414
  }
415
  .searchimage {
@@ -424,7 +459,7 @@ li.searcheng {
424
  border-right: 1px dotted #8e8e8e;
425
  }
426
  ul.useragent {
427
- padding: 4px 0 2px 0;
428
  background-color: #67a;
429
  border-bottom: 1px #ccc solid;
430
  }
@@ -432,7 +467,8 @@ li.useragent {
432
  list-style-type: none;
433
  color: #f5f5f5;
434
  width: 100%;
435
- padding: 0 6px 0 0;
 
436
  text-align: center;
437
  }
438
  ul.spam {
@@ -466,7 +502,12 @@ li.feed {
466
  padding: 0 4px 0 4px;
467
  border-right: 1px dotted #8e8e8e;
468
  }
469
- ul.agent { border-color: #ddd; }
 
 
 
 
 
470
  li.agent {
471
  list-style-type: none;
472
  display: inline; width: 100%;
@@ -494,29 +535,24 @@ li.users {
494
  }
495
  ul.url {
496
  list-style-type: none;
497
- width: 100%;
498
  margin: 0;
499
  padding: 0;
500
- border: none;
501
- border-top: 1px #999 solid;
502
  clear: left;
503
  }
504
- li.url {
505
  list-style-type: none;
506
  width: 100%;
507
  margin: 0;
508
  padding: 0;
509
- line-height: 2em;
 
510
  background-image: url("images/list-bg2.png");
511
- border-bottom: 1px #ddd solid;
512
  }
513
- li.urlodd {
514
- list-style-type: none;
515
- width: 100%;
516
- margin: 0;
517
- padding: 4px 0 6px 0;
518
- background-image: url("images/list-bg3.png");
519
- border-bottom: 1px #ddd solid;
520
  }
521
  .url a, .url a:link { border-bottom: 1px solid !important; }
522
  .indent-li { padding-left: 165px; }
@@ -552,10 +588,14 @@ li.urlodd {
552
  margin: 5px auto !important;
553
  padding: 1px 1px 2px !important;
554
  background-color: #dedade;
555
- box-shadow: 0 0 5px rgba(24, 24, 64, 0.9); /* 0 0 5px rgba(44,44,104, 0.9); */
556
- -moz-box-shadow: 0 0 5px rgba(24, 24, 64, 0.9);
557
- -webkit-box-shadow: 0 0 5px rgba(24, 24, 64, 0.9);
558
- border: 1px solid #c9d9e9; /* #efebef; */
 
 
 
 
559
  }
560
  #spyContainer { clear: both; padding: 5px 5px 0 0; }
561
  #settings {
@@ -602,23 +642,26 @@ ul.usage-title li { display: inline; list-style-type: none; }
602
  font-size: .9em !important;
603
  }
604
  .bubble { font-size:11px; }
605
- .top10 { color: #542; }
 
606
 
607
  /* wassup-option tabs styles */
608
  #tabcontainer {
609
- list-style:none;
610
  /* width: 97%; */
611
  margin: 10px auto 3px auto;
612
- padding: 2px 5px 1px;
 
 
 
613
  border: 1px solid #efebef;
614
  border-radius: 3px;
615
  -webkit-border-radius: 3px;
616
  -moz-border-radius: 3px;
617
  background-color: #dedade;
618
- color: #445;
619
- box-shadow: 0 0 5px rgba(44,44,104, 0.9);
620
- -moz-box-shadow: 0 0 5px rgba(44,44,104, 0.9);
621
- -webkit-box-shadow: 0 0 5px rgba(44,44,104, 0.9);
622
  }
623
  #tabcontainer ul.ui-tabs-nav {
624
  background: none !important;
@@ -657,6 +700,16 @@ ul.ui-tabs-nav li.ui-state-active {
657
  border-top-left-radius: 4px;
658
  border-top-right-radius: 4px;
659
  }
 
 
 
 
 
 
 
 
 
 
660
  #wassup_opt_frag-1, #wassup_opt_frag-2, #wassup_opt_frag-3,
661
  #wassup_opt_frag-4 {
662
  height: 100%;
@@ -696,18 +749,29 @@ ul.varlist { list-style:none; margin:0; padding:5px 0 0 17px; }
696
  }
697
  #spy-pause a, #spy-play a { text-decoration: none; border-bottom: 0 none; }
698
  .wassup-button {
699
- - width; 160px;
700
  background: url("images/button.png") top center no-repeat;
701
  border-color: #999 !important;
 
 
 
 
702
  }
703
  .wassup-hot-button {
704
- width; 160px;
705
  background: url("images/button2.png") top center no-repeat;
706
  border-color: #777 !important;
 
 
 
 
707
  }
708
  .wassup-button:hover {
709
  background-image: url("images/button2.png");
 
 
710
  }
711
  .wassup-hot-button:hover {
712
  background-image: url("images/hot-button.png");
713
  }
 
3
  * wassup.css - stylesheet for WassUp plugin
4
  */
5
  #wassup-wrap {
 
6
  min-height: 500px;
7
+ padding: 1px 7px 3px;
8
+ font-family: "Lucida Grande",Verdana,Arial,"Bitstream Vera Sans",sans-serif;
9
+ font-size: 13px;
10
  border:1px solid #d6d7d6;
11
+ background: #efebef ; */
12
+ /* background: #efebef url("images/menu-shadow-rtl.png") left top repeat-y; */
13
+ -moz-border-radius: 5px 5px 0 0;
14
+ -webkit-border-top-left-radius: 5px;
15
+ -webkit-border-top-right-radius: 5px;
16
+ -khtml-border-top-left-radius: 5px;
17
+ -khtml-border-top-right-radius: 5px;
18
+ border-top-right-radius: 5px;
19
+ border-top-left-radius: 5px;
20
  }
21
  #wassup-wrap table { border-collapse: collapse; padding: 2px; }
22
  #wassup-wrap h2 {
26
  }
27
  #wassup-wrap img {
28
  display: inline;
29
+ vertical-align: middle;
30
  margin: 0 2px 2px 0;
31
  padding:0;
32
  }
37
  }
38
  #wassup-wrap td.legend a { border-bottom: 1px solid; }
39
  #wassup-wrap a:visited { color: #229; }
40
+ #wassup-wrap a:hover { color: #ff6d06; }
41
+ #wassup-wrap a:active { color: #d11; }
42
  .wassup-icon {}
43
  .wassup-content { min-height:225px; }
44
  /*
45
  * for wassup admin top menu styles in Wordpress 2.7+ */
46
  .wassup-menu-link {
47
  float: right;
48
+ font-family: Arial,"Bitstream Vera Sans",Helvetica,Verdana,sans-serif;
49
+ font-size: 12px;
50
  height: 22px;
51
  padding: 0;
52
  margin: 0 4px 0 0;
90
  padding: 0 6px 0 6px;
91
  height: 22px;
92
  line-height: 22px;
 
93
  }
94
  #wassup-menu li.current a {
95
  color: #00284a;
113
  border-bottom: 0 none;
114
  }
115
  #wassup-menu li.current, #wassup-menu-link:active {
116
+ height: 24px !important;
117
+ margin-bottom: -2px !important;
118
  color: #00284a;
119
  background: url("images/link.png") no-repeat bottom center;
120
  border-top: 1px solid #c8c8c4;
138
  padding: 2px 1px 1px;
139
  color: #445;
140
  background-color: #dedade;
141
+ -moz-box-shadow: 0 0 3px rgba(24, 24, 30, 0.9);
142
+ -webkit-box-shadow: 0 0 3px rgba(24, 24, 30, 0.9);
143
+ box-shadow: 0 0 3px rgba(24, 24, 30, 0.9);
144
+ border: 1px solid #e9e9ee;
145
+ -moz-border-radius: 3px 3px 0 0;
146
+ -webkit-border-top-left-radius: 3px;
147
+ -webkit-border-top-right-radius: 3px;
148
+ -khtml-border-top-left-radius: 3px;
149
+ -khtml-border-top-right-radius: 3px;
150
+ border-top-right-radius: 3px;
151
+ border-top-left-radius: 3px;
152
  }
153
  .main-tabs a, .main-tabs a:link {
154
  color: #00b;
194
  color: #dedede;
195
  background-color: #778;
196
  border: 1px solid #fafeee;
 
197
  -moz-box-shadow:0 0 2px rgba(50, 80, 80, 0.3);
198
  -webkit-box-shadow:0 0 2px rgba(50, 80, 80, 0.3);
199
+ box-shadow: 0 0 2px rgba(50, 80, 80, 0.3);
200
  }
201
  .pagination .disabled {
202
  padding: 2px 5px 2px 5px;
225
  padding: 1px 0 0 !important;
226
  font-size: 11px;
227
  background-color: #f4f6f6;
228
+ border: 1px solid #ababca; /* 89a; */
229
+ border-top: 1px solid #cdccdc; /* #c7c7cc; */
230
+ /* border-bottom: 3px solid #347; */
231
  }
232
  .sum-nav, .sum-nav-mark, .sum-spy {
233
  position: relative;
234
  clear: left;
235
+ /* width: 100%; */
236
  min-height: 50px;
237
  margin: 0 !important;
238
  padding: 22px 0 0;
239
  font-size: 11px;
240
  border-top: 1px solid #fffcff;
241
+ border-left: 1px solid #efefe0;
242
+ border-right: 1px solid #efefe0;
243
+ border-bottom: 0 none;
244
  background: url("images/list-bg.png") repeat-x;
245
  }
246
  .wassup-online .sum-nav { height:60px; }
259
  div.sum-spy {
260
  margin: 12px 0 0 0 !important;
261
  padding: 1px 1px 0 !important;
262
+ border-top: 1px solid #fefffe;
263
+ border-right: 1px solid #779;
264
+ border-left: 1px solid #779;
265
  border-bottom: 3px solid #347;
266
  min-height: 50px;
267
  background: #f4f6f6 url("images/list-bg.png") repeat-x;
268
+ -moz-box-shadow:0 2px 5px #779;
269
+ -webkit-box-shadow: 0 2px 5px #779;
270
+ box-shadow: 0 2px 5px #779;
271
  }
272
  .delbut {
273
  position: absolute;
285
  margin: 0 !important;
286
  padding: 0;
287
  /* width: 100%; */
288
+ height: 3px;
289
  clear: both;
290
+ background-color: #77799f;
291
  }
292
  .sum-det, .sum-det-spy {
293
  display:block;
312
  .det3 { padding-left: 20px; }
313
  .det1 a { font-weight: bold; border-bottom: 1px solid !important; }
314
  .det2 a, .det2 a:link, .sum-det span.det2 a {
315
+ color: #349 !important;
316
  }
317
  .det2 a:hover, .sum-det span.det2 a:hover {
318
  color: #d54d22 !important;
340
  width: 140px;
341
  height: 28px;
342
  padding-top: 5px !important;
343
+ border: 1px solid #c0cccf;
344
+ /* -moz-box-shadow: 0 -2px 10px #BFBFBD inset;
345
+ -webkit-box-shadow: 0 -2px 10px #BFBFBD inset;
346
+ box-shadow: 0 --2px 10px #BFBFBD inset; */
347
  }
348
  .sum-box-ip {
349
  font-family: tahoma, verdana, arial, sans-serif;
380
  margin: 5px auto 0 auto !important;
381
  line-height: 1.1em;
382
  }
383
+ #toptenchart { margin:0 auto; padding:0; }
384
+ #toptenchart table {
385
+ margin: 0;
386
+ padding: 0;
387
+ border-collapse: collapse;
388
+ border: 0 none;
389
+ }
390
+ #toptenchart a { color: #464646; margin-left: 1px; }
391
  #toptenchart a:hover { color: #d54d22; }
392
  ul.charts {
393
  list-style-type: none;
394
  margin: 0;
395
  padding: 0;
396
+ font: 8pt sans-serif;
397
+ line-height: 1.1em;
398
  border-bottom: 1px solid #dedede;
399
+ border-right: 1px solid #fff;
400
  }
401
  li.charts {
402
+ height: 25px !important;
403
  list-style-type: none;
404
+ /* font-size: 11px; */
405
+ line-height: 22px;
406
  border-top: 1px #ddd solid;
407
+ margin: 0;
408
+ padding: 0 2px 0 2px;
409
  background: url("images/list-bg3.png");
410
  }
411
  li.chartsT {
412
+ height: 25px !important;
413
+ margin: 0;
414
+ padding: 2px 2px 0 2px;
415
  list-style-type: none;
416
  color: #2683ae;
417
+ /* font-size: 11px; */
418
  border-bottom: 2px solid #bfd0dd;
419
+ vertical-align: bottom;
 
420
  background: #cee1ef;
421
  }
422
+ ul.rownums { background-color: #e6e9ef !important; }
423
  .sum-rec ul { border-top: 1px solid #999; }
424
  .detail-data {
425
  margin: 0 auto !important;
426
  clear:both;
427
+ border-left: 1px solid #eeeeef;
428
+ border-right: 1px solid #eeeeef;
429
+ border-top: 0 none;
430
+ border-bottom: 1px solid #bcbcbf;
431
  color: #445;
432
  font-size: 11px;
433
  }
435
  .detail-data a:hover { color: #c64 !important; }
436
  .detail-data ul {
437
  list-style-type: none;
438
+ /* width: 100%; */
439
  margin: 0;
440
  padding: 3px 0 4px 0;
441
  font-size: 11px;
442
  border-top: 1px solid #ddd;
443
  border-bottom: 1px solid #bbb;
444
  }
445
+ .detail-data ul li { height: 25px; line-height: 22px; }
446
  ul.searcheng {
447
+ background-color: #abdbff;
448
  border-color: #9cd;
449
  }
450
  .searchimage {
459
  border-right: 1px dotted #8e8e8e;
460
  }
461
  ul.useragent {
462
+ padding: 0;
463
  background-color: #67a;
464
  border-bottom: 1px #ccc solid;
465
  }
467
  list-style-type: none;
468
  color: #f5f5f5;
469
  width: 100%;
470
+ padding: 4px 6px 0 0;
471
+ line-height: 1.5em !important;
472
  text-align: center;
473
  }
474
  ul.spam {
502
  padding: 0 4px 0 4px;
503
  border-right: 1px dotted #8e8e8e;
504
  }
505
+ ul.agent {
506
+ border-color: #ddd;
507
+ /* -moz-box-shadow: 0 -2px 10px #CDD0EE inset;
508
+ -webkit-box-shadow: 0 -2px 10px #CDD0EE inset;
509
+ box-shadow: 0 -2px 10px #CDD0EE inset; */
510
+ }
511
  li.agent {
512
  list-style-type: none;
513
  display: inline; width: 100%;
535
  }
536
  ul.url {
537
  list-style-type: none;
538
+ /* width: 100%; */
539
  margin: 0;
540
  padding: 0;
541
+ border: 0 none;
 
542
  clear: left;
543
  }
544
+ li.url, li.urlodd {
545
  list-style-type: none;
546
  width: 100%;
547
  margin: 0;
548
  padding: 0;
549
+ height: 25px;
550
+ line-height: 22px;
551
  background-image: url("images/list-bg2.png");
552
+ border-top: 1px solid #c0cfcf;
553
  }
554
+ ul.url li.url {
555
+ background-image: url("images/list-bg3.png") !important;
 
 
 
 
 
556
  }
557
  .url a, .url a:link { border-bottom: 1px solid !important; }
558
  .indent-li { padding-left: 165px; }
588
  margin: 5px auto !important;
589
  padding: 1px 1px 2px !important;
590
  background-color: #dedade;
591
+ box-shadow: 0 0 4px rgba(24, 24, 30, 0.9);
592
+ -moz-box-shadow: 0 0 4px rgba(24, 24, 30, 0.9);
593
+ -webkit-box-shadow: 0 0 4px rgba(24, 24, 30, 0.9);
594
+ border: 1px solid #ededef;
595
+ -moz-border-radius: 3px;
596
+ -webkit-border-radius: 3px;
597
+ -khtml-border-radius: 3px;
598
+ border-radius: 3px;
599
  }
600
  #spyContainer { clear: both; padding: 5px 5px 0 0; }
601
  #settings {
642
  font-size: .9em !important;
643
  }
644
  .bubble { font-size:11px; }
645
+ .top10 { color: #542; padding-left: 1px; }
646
+ .fixed { font-size:11px; font-family: monospace; color: #887; }
647
 
648
  /* wassup-option tabs styles */
649
  #tabcontainer {
 
650
  /* width: 97%; */
651
  margin: 10px auto 3px auto;
652
+ padding: 2px 2px 1px;
653
+ font-family: "Lucida Grande",Verdana,Arial,"Bitstream Vera Sans",sans-serif !important;
654
+ font-size: 14px;
655
+ color: #445;
656
  border: 1px solid #efebef;
657
  border-radius: 3px;
658
  -webkit-border-radius: 3px;
659
  -moz-border-radius: 3px;
660
  background-color: #dedade;
661
+ list-style:none;
662
+ -moz-box-shadow: 0 0 3px rgba(24, 24, 30, 0.9);
663
+ -webkit-box-shadow: 0 0 3px rgba(24, 24, 30, 0.9);
664
+ box-shadow: 0 0 3px rgba(24, 24, 30, 0.9);
665
  }
666
  #tabcontainer ul.ui-tabs-nav {
667
  background: none !important;
700
  border-top-left-radius: 4px;
701
  border-top-right-radius: 4px;
702
  }
703
+ .ui-widget-header a {
704
+ color: #999 !important;
705
+ font-size: 1.1em;
706
+ font-weight: bold;
707
+ text-shadow: 0 -1px 0 rgba(255,255,221,0.5);
708
+ }
709
+ .ui-state-active a, .ui-widget-header a:hover {
710
+ color: #212121 !important;
711
+ }
712
+
713
  #wassup_opt_frag-1, #wassup_opt_frag-2, #wassup_opt_frag-3,
714
  #wassup_opt_frag-4 {
715
  height: 100%;
749
  }
750
  #spy-pause a, #spy-play a { text-decoration: none; border-bottom: 0 none; }
751
  .wassup-button {
752
+ width: 155px !important;
753
  background: url("images/button.png") top center no-repeat;
754
  border-color: #999 !important;
755
+ border-radius: 10px !important;
756
+ -moz-border-radius: 10px;
757
+ -webkit-border-radius: 10px;
758
+ -khtml-border-radius: 10px;
759
  }
760
  .wassup-hot-button {
761
+ width: 155px;
762
  background: url("images/button2.png") top center no-repeat;
763
  border-color: #777 !important;
764
+ border-radius: 10px !important;
765
+ -moz-border-radius: 10px;
766
+ -webkit-border-radius: 10px;
767
+ -khtml-border-radius: 10px;
768
  }
769
  .wassup-button:hover {
770
  background-image: url("images/button2.png");
771
+ background-color: transparent !important;
772
+ color: #157 !important;
773
  }
774
  .wassup-hot-button:hover {
775
  background-image: url("images/hot-button.png");
776
  }
777
+ .button-primary { border-color: #157 !important; }
img/Thumbs.db ADDED
Binary file
img/b_delete.png ADDED
Binary file
img/b_delete2.png ADDED
Binary file
img/b_select.png ADDED
Binary file
img/b_select2.png ADDED
Binary file
img/error_add.png CHANGED
Binary file
img/error_delete.png CHANGED
Binary file
img/flags/Thumbs.db ADDED
Binary file
js/jquery.min.js ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ /*! jQuery v1.6.4 http://jquery.com/ | http://jquery.org/license */
2
+ (function(a,b){function cu(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cr(a){if(!cg[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cq(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cp(){cn=b}function co(){setTimeout(cp,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function bZ(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function bY(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bA.test(a)?d(a,e):bY(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)bY(a+"["+e+"]",b[e],c,d);else d(a,b)}function bX(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bW(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bP,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bW(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bW(a,c,d,e,"*",g));return l}function bV(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bL),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function by(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bt:bu;if(d>0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bv(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bl(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bd,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bk(a){f.nodeName(a,"input")?bj(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bj)}function bj(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bi(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bh(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bg(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i<j;i++)f.event.add(b,h+(g[h][i].namespace?".":"")+g[h][i].namespace,g[h][i],g[h][i].data)}}}}function bf(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function V(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(Q.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function U(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function M(a,b){return(a&&a!=="*"?a+".":"")+b.replace(y,"`").replace(z,"&")}function L(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;i<s.length;i++)g=s[i],g.origType.replace(w,"")===a.type?q.push(g.selector):s.splice(i--,1);e=f(a.target).closest(q,a.currentTarget);for(j=0,k=e.length;j<k;j++){m=e[j];for(i=0;i<s.length;i++){g=s[i];if(m.selector===g.selector&&(!n||n.test(g.namespace))&&!m.elem.disabled){h=m.elem,d=null;if(g.preType==="mouseenter"||g.preType==="mouseleave")a.type=g.preType,d=f(a.relatedTarget).closest(g.selector)[0],d&&f.contains(h,d)&&(d=h);(!d||d!==h)&&p.push({elem:h,handleObj:g,level:m.level})}}}for(j=0,k=p.length;j<k;j++){e=p[j];if(c&&e.level>c)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function J(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function D(){return!0}function C(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function K(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(K,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z]|[0-9])/ig,x=/^-ms-/,y=function(a,b){return(b+"").toUpperCase()},z=d.userAgent,A,B,C,D=Object.prototype.toString,E=Object.prototype.hasOwnProperty,F=Array.prototype.push,G=Array.prototype.slice,H=String.prototype.trim,I=Array.prototype.indexOf,J={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.4",length:0,size:function(){return this.length},toArray:function(){return G.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?F.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),B.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(G.apply(this,arguments),"slice",G.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:F,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;B.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!B){B=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",C,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",C),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&K()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):J[D.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!E.call(a,"constructor")&&!E.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||E.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(x,"ms-").replace(w,y)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:H?function(a){return a==null?"":H.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?F.call(c,a):e.merge(c,a)}return c},inArray:function(a,b){if(!b)return-1;if(I)return I.call(b,a);for(var c=0,d=b.length;c<d;c++)if(b[c]===a)return c;return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=G.call(arguments,2),g=function(){return a.apply(c,f.concat(G.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=s.exec(a)||t.exec(a)||u.exec(a)||a.indexOf("compatible")<0&&v.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){J["[object "+b+"]"]=b.toLowerCase()}),A=e.uaMatch(z),A.browser&&(e.browser[A.browser]=!0,e.browser.version=A.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?C=function(){c.removeEventListener("DOMContentLoaded",C,!1),e.ready()}:c.attachEvent&&(C=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",C),e.ready())});return e}(),g="done fail isResolved isRejected promise then always pipe".split(" "),h=[].slice;f.extend({_Deferred:function(){var a=[],b,c,d,e={done:function(){if(!d){var c=arguments,g,h,i,j,k;b&&(k=b,b=0);for(g=0,h=c.length;g<h;g++)i=c[g],j=f.type(i),j==="array"?e.done.apply(e,i):j==="function"&&a.push(i);k&&e.resolveWith(k[0],k[1])}return this},resolveWith:function(e,f){if(!d&&!b&&!c){f=f||[],c=1;try{while(a[0])a.shift().apply(e,f)}finally{b=[e,f],c=0}}return this},resolve:function(){e.resolveWith(this,arguments);return this},isResolved:function(){return!!c||!!b},cancel:function(){d=1,a=[];return this}};return e},Deferred:function(a){var b=f._Deferred(),c=f._Deferred(),d;f.extend(b,{then:function(a,c){b.done(a).fail(c);return this},always:function(){return b.done.apply(b,arguments).fail.apply(this,arguments)},fail:c.done,rejectWith:c.resolveWith,reject:c.resolve,isRejected:c.isResolved,pipe:function(a,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[c,"reject"]},function(a,c){var e=c[0],g=c[1],h;f.isFunction(e)?b[a](function(){h=e.apply(this,arguments),h&&f.isFunction(h.promise)?h.promise().then(d.resolve,d.reject):d[g+"With"](this===b?d:this,[h])}):b[a](d[g])})}).promise()},promise:function(a){if(a==null){if(d)return d;d=a={}}var c=g.length;while(c--)a[g[c]]=b[g[c]];return a}}),b.done(c.cancel).fail(b.cancel),delete b.cancel,a&&a.call(b,b);return b},when:function(a){function i(a){return function(c){b[a]=arguments.length>1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c<d;c++)b[c]&&f.isFunction(b[c].promise)?b[c].promise().then(i(c),g.reject):--e;e||g.resolveWith(g,b)}else g!==a&&g.resolveWith(g,d?[a]:[]);return g.promise()}}),f.support=function(){var a=c.createElement("div"),b=c.documentElement,d,e,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u;a.setAttribute("className","t"),a.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},m&&f.extend(p,{position:"absolute",left:"-1000px",top:"-1000px"});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="<div style='width:4px;'></div>",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i=f.expando,j=typeof c=="string",k=a.nodeType,l=k?f.cache:a,m=k?a[f.expando]:a[f.expando]&&f.expando;if((!m||e&&m&&l[m]&&!l[m][i])&&j&&d===b)return;m||(k?a[f.expando]=m=++f.uuid:m=f.expando),l[m]||(l[m]={},k||(l[m].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?l[m][i]=f.extend(l[m][i],c):l[m]=f.extend(l[m],c);g=l[m],e&&(g[i]||(g[i]={}),g=g[i]),d!==b&&(g[f.camelCase(c)]=d);if(c==="events"&&!g[c])return g[i]&&g[i].events;j?(h=g[c],h==null&&(h=g[f.camelCase(c)])):h=g;return h}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e=f.expando,g=a.nodeType,h=g?f.cache:a,i=g?a[f.expando]:f.expando;if(!h[i])return;if(b){d=c?h[i][e]:h[i];if(d){d[b]||(b=f.camelCase(b)),delete d[b];if(!l(d))return}}if(c){delete h[i][e];if(!l(h[i]))return}var j=h[i][e];f.support.deleteExpando||!h.setInterval?delete h[i]:h[i]=null,j?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=j):g&&(f.support.deleteExpando?delete a[f.expando]:a.removeAttribute?a.removeAttribute(f.expando):a[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h<i;h++)g=e[h].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),k(this[0],g,d[g]))}}return d}if(typeof a=="object")return this.each(function(){f.data(this,a)});var j=a.split(".");j[1]=j[1]?"."+j[1]:"";if(c===b){d=this.triggerHandler("getData"+j[1]+"!",[j[0]]),d===b&&this.length&&(d=f.data(this[0],a),d=k(this[0],a,d));return d===b&&j[1]?this.data(j[0]):d}return this.each(function(){var b=f(this),d=[j[0],c];b.triggerHandler("setData"+j[1]+"!",d),f.data(this,a,c),b.triggerHandler("changeData"+j[1]+"!",d)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,c){a&&(c=(c||"fx")+"mark",f.data(a,c,(f.data(a,c,b,!0)||0)+1,!0))},_unmark:function(a,c,d){a!==!0&&(d=c,c=a,a=!1);if(c){d=d||"fx";var e=d+"mark",g=a?0:(f.data(c,e,b,!0)||1)-1;g?f.data(c,e,g,!0):(f.removeData(c,e,!0),m(c,d,"mark"))}},queue:function(a,c,d){if(a){c=(c||"fx")+"queue";var e=f.data(a,c,b,!0);d&&(!e||f.isArray(d)?e=f.data(a,c,f.makeArray(d),!0):e.push(d));return e||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e;d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),d.call(a,function(){f.dequeue(a,b)})),c.length||(f.removeData(a,b+"queue",!0),m(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(){var c=this;setTimeout(function(){f.dequeue(c,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f._Deferred(),!0))h++,l.done(m);m();return d.promise()}});var n=/[\n\t\r]/g,o=/\s+/,p=/\r/g,q=/^(?:button|input)$/i,r=/^(?:button|input|object|select|textarea)$/i,s=/^a(?:rea)?$/i,t=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,u,v;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(o);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(o);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(n," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(o);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ";for(var c=0,d=this.length;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(n," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h<i;h++){var j=e[h];if(j.selected&&(f.support.optDisabled?!j.disabled:j.getAttribute("disabled")===null)&&(!j.parentNode.disabled||!f.nodeName(j.parentNode,"optgroup"))){b=f(j).val();if(g)return b;d.push(b)}}if(g&&!d.length&&e.length)return f(e[c]).val();return d},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=v:u&&(i=u)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.attr(a,b,""),a.removeAttribute(b),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(u&&f.nodeName(a,"button"))return u.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(u&&f.nodeName(a,"button"))return u.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==null?g:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabIndex=f.propHooks.tabIndex,v={get:function(a,c){var d;return f.prop(a,c)===!0||(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(u=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var w=/\.(.*)$/,x=/^(?:textarea|input|select)$/i,y=/\./g,z=/ /g,A=/[^\w\s.|`]/g,B=function(a){return a.replace(A,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=C;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=C);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),B).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j<p.length;j++){q=p[j];if(l||n.test(q.namespace))f.event.remove(a,r,q.handler,j),p.splice(j--,1)}continue}o=f.event.special[h]||{};for(j=e||0;j<p.length;j++){q=p[j];if(d.guid===q.guid){if(l||n.test(q.namespace))e==null&&p.splice(j--,1),o.remove&&o.remove.call(a,q);if(e!=null)break}}if(p.length===0||e!=null&&p.length===1)(!o.teardown||o.teardown.call(a,m)===!1)&&f.removeEvent(a,h,s.handle),g=null,delete
3
+ t[h]}if(f.isEmptyObject(t)){var u=s.handle;u&&(u.elem=null),delete s.events,delete s.handle,f.isEmptyObject(s)&&f.removeData(a,b,!0)}}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){var h=c.type||c,i=[],j;h.indexOf("!")>=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h<i;h++){var j=d[h];if(e||c.namespace_re.test(j.namespace)){c.handler=j.handler,c.data=j.data,c.handleObj=j;var k=j.handler.apply(this,g);k!==b&&(c.result=k,k===!1&&(c.preventDefault(),c.stopPropagation()));if(c.isImmediatePropagationStopped())break}}return c.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[f.expando])return a;var d=a;a=f.Event(d);for(var e=this.props.length,g;e;)g=this.props[--e],a[g]=d[g];a.target||(a.target=a.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),!a.relatedTarget&&a.fromElement&&(a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement);if(a.pageX==null&&a.clientX!=null){var h=a.target.ownerDocument||c,i=h.documentElement,j=h.body;a.pageX=a.clientX+(i&&i.scrollLeft||j&&j.scrollLeft||0)-(i&&i.clientLeft||j&&j.clientLeft||0),a.pageY=a.clientY+(i&&i.scrollTop||j&&j.scrollTop||0)-(i&&i.clientTop||j&&j.clientTop||0)}a.which==null&&(a.charCode!=null||a.keyCode!=null)&&(a.which=a.charCode!=null?a.charCode:a.keyCode),!a.metaKey&&a.ctrlKey&&(a.metaKey=a.ctrlKey),!a.which&&a.button!==b&&(a.which=a.button&1?1:a.button&2?3:a.button&4?2:0);return a},guid:1e8,proxy:f.proxy,special:{ready:{setup:f.bindReady,teardown:f.noop},live:{add:function(a){f.event.add(this,M(a.origType,a.selector),f.extend({},a,{handler:L,guid:a.handler.guid}))},remove:function(a){f.event.remove(this,M(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}}},f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!this.preventDefault)return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?D:C):this.type=a,b&&f.extend(this,b),this.timeStamp=f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=D;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=D;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=D,this.stopPropagation()},isDefaultPrevented:C,isPropagationStopped:C,isImmediatePropagationStopped:C};var E=function(a){var b=a.relatedTarget,c=!1,d=a.type;a.type=a.data,b!==this&&(b&&(c=f.contains(this,b)),c||(f.event.handle.apply(this,arguments),a.type=d))},F=function(a){a.type=a.data,f.event.handle.apply(this,arguments)};f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={setup:function(c){f.event.add(this,b,c&&c.selector?F:E,a)},teardown:function(a){f.event.remove(this,b,a&&a.selector?F:E)}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(a,b){if(!f.nodeName(this,"form"))f.event.add(this,"click.specialSubmit",function(a){var b=a.target,c=f.nodeName(b,"input")||f.nodeName(b,"button")?b.type:"";(c==="submit"||c==="image")&&f(b).closest("form").length&&J("submit",this,arguments)}),f.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,c=f.nodeName(b,"input")||f.nodeName(b,"button")?b.type:"";(c==="text"||c==="password")&&f(b).closest("form").length&&a.keyCode===13&&J("submit",this,arguments)});else return!1},teardown:function(a){f.event.remove(this,".specialSubmit")}});if(!f.support.changeBubbles){var G,H=function(a){var b=f.nodeName(a,"input")?a.type:"",c=a.value;b==="radio"||b==="checkbox"?c=a.checked:b==="select-multiple"?c=a.selectedIndex>-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},I=function(c){var d=c.target,e,g;if(!!x.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=H(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:I,beforedeactivate:I,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&I.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&I.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",H(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in G)f.event.add(this,c+".specialChange",G[c]);return x.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return x.test(this.nodeName)}},G=f.event.special.change.filters,G.focus=G.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i<j;i++)f.event.add(this[i],a,g,d);return this}}),f.fn.extend({unbind:function(a,b){if(typeof a=="object"&&!a.preventDefault)for(var c in a)this.unbind(c,a[c]);else for(var d=0,e=this.length;d<e;d++)f.event.remove(this[d],a,b);return this},delegate:function(a,b,c,d){return this.live(b,c,d,a)},undelegate:function(a,b,c){return arguments.length===0?this.unbind("live"):this.die(b,null,c,a)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f.data(this,"lastToggle"+a.guid)||0)%d;f.data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var K={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};f.each(["live","die"],function(a,c){f.fn[c]=function(a,d,e,g){var h,i=0,j,k,l,m=g||this.selector,n=g?this:f(this.context);if(typeof a=="object"&&!a.preventDefault){for(var o in a)n[c](o,d,a[o],m);return this}if(c==="die"&&!a&&g&&g.charAt(0)==="."){n.unbind(g);return this}if(d===!1||f.isFunction(d))e=d||C,d=b;a=(a||"").split(" ");while((h=a[i++])!=null){j=w.exec(h),k="",j&&(k=j[0],h=h.replace(w,""));if(h==="hover"){a.push("mouseenter"+k,"mouseleave"+k);continue}l=h,K[h]?(a.push(K[h]+k),h=h+k):h=(K[h]||h)+k;if(c==="live")for(var p=0,q=n.length;p<q;p++)f.event.add(n[p],"live."+M(h,m),{data:d,selector:m,handler:e,origType:h,origHandler:e,preType:l});else n.unbind("live."+M(h,m),e)}return this}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}if(i.nodeType===1){f||(i.sizcache=c,i.sizset=g);if(typeof b!="string"){if(i===b){j=!0;break}}else if(k.filter(b,[i]).length>0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}i.nodeType===1&&!f&&(i.sizcache=c,i.sizset=g);if(i.nodeName.toLowerCase()===b){j=i;break}i=i[a]}d[g]=j}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},k.matches=function(a,b){return k(a,null,null,b)},k.matchesSelector=function(a,b){return k(b,null,null,[a]).length>0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e<f;e++){var g,h=l.order[e];if(g=l.leftMatch[h].exec(a)){var j=g[1];g.splice(1,1);if(j.substr(j.length-1)!=="\\"){g[1]=(g[1]||"").replace(i,""),d=l.find[h](g,b,c);if(d!=null){a=a.replace(l.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},k.filter=function(a,c,d,e){var f,g,h=a,i=[],j=c,m=c&&c[0]&&k.isXML(c[0]);while(a&&c.length){for(var n in l.filter)if((f=l.leftMatch[n].exec(a))!=null&&f[2]){var o,p,q=l.filter[n],r=f[1];g=!1,f.splice(1,1);if(r.substr(r.length-1)==="\\")continue;j===i&&(i=[]);if(l.preFilter[n]){f=l.preFilter[n](f,j,d,i,e,m);if(!f)g=o=!0;else if(f===!0)continue}if(f)for(var s=0;(p=j[s])!=null;s++)if(p){o=q(p,f,s,j);var t=e^!!o;d&&o!=null?t?g=!0:j[s]=!1:t&&(i.push(p),g=!0)}if(o!==b){d||(j=i),a=a.replace(l.match[n],"");if(!g)return[];break}}if(a===h)if(g==null)k.error(a);else break;h=a}return j},k.error=function(a){throw"Syntax error, unrecognized expression: "+a};var l=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!j.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&k.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&k.filter(b,a,!0)}},"":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("parentNode",b,f,a,e,c)},"~":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("previousSibling",b,f,a,e,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(i,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}k.error(e)},CHILD:function(a,b){var c=b[1],d=a;switch(c){case"only":case"first":while(d=d.previousSibling)if(d.nodeType===1)return!1;if(c==="first")return!0;d=a;case"last":while(d=d.nextSibling)if(d.nodeType===1)return!1;return!0;case"nth":var e=b[2],f=b[3];if(e===1&&f===0)return!0;var g=b[0],h=a.parentNode;if(h&&(h.sizcache!==g||!a.nodeIndex)){var i=0;for(d=h.firstChild;d;d=d.nextSibling)d.nodeType===1&&(d.nodeIndex=++i);h.sizcache=g}var j=a.nodeIndex-f;return e===0?j===0:j%e===0&&j/e>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c<f;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var r,s;c.documentElement.compareDocumentPosition?r=function(a,b){if(a===b){g=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(r=function(a,b){if(a===b){g=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],h=a.parentNode,i=b.parentNode,j=h;if(h===i)return s(a,b);if(!h)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return s(e[k],f[k]);return k===c?s(a,f[k],-1):s(e[k],b,1)},s=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),k.getText=function(a){var b="",c;for(var d=0;a[d];d++)c=a[d],c.nodeType===3||c.nodeType===4?b+=c.nodeValue:c.nodeType!==8&&(b+=k.getText(c.childNodes));return b},function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g<h;g++)k(a,f[g],d);return k.filter(e,d)};f.find=k,f.expr=k.selectors,f.expr[":"]=f.expr.filters,f.unique=k.uniqueSort,f.text=k.getText,f.isXMLDoc=k.isXML,f.contains=k.contains}();var N=/Until$/,O=/^(?:parents|prevUntil|prevAll)/,P=/,/,Q=/^.[^:#\[\.,]*$/,R=Array.prototype.slice,S=f.expr.match.POS,T={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(V(this,a,!1),"not",a)},filter:function(a){return this.pushStack(V(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d<e;d++)i=a[d],j[i]||(j[i]=S.test(i)?f(i,b||this.context):i);while(g&&g.ownerDocument&&g!==b){for(i in j)h=j[i],(h.jquery?h.index(g)>-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=S.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(l?l.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(U(c[0])||U(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=R.call(arguments);N.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!T[a]?f.unique(e):e,(this.length>1||P.test(d))&&O.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|object|embed|option|style)/i,bb=/checked\s*(?:[^=]|=\s*.checked.)/i,bc=/\/(java|ecma)script/i,bd=/^\s*<!(?:\[CDATA\[|\-\-)/,be={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};be.optgroup=be.option,be.tbody=be.tfoot=be.colgroup=be.caption=be.thead,be.th=be.td,f.support.htmlSerialize||(be._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!be[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bb.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bf(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bl)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i;b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof a[0]=="string"&&a[0].length<512&&i===c&&a[0].charAt(0)==="<"&&!ba.test(a[0])&&(f.support.checkClone||!bb.test(a[0]))&&(g=!0,h=f.fragments[a[0]],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean
4
+ (a,i,e,d)),g&&(f.fragments[a[0]]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bh(a,d),e=bi(a),g=bi(d);for(h=0;e[h];++h)g[h]&&bh(e[h],g[h])}if(b){bg(a,d);if(c){e=bi(a),g=bi(d);for(h=0;e[h];++h)bg(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=be[l]||be._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bk(k[i]);else bk(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||bc.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.expando,g=f.event.special,h=f.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&f.noData[j.nodeName.toLowerCase()])continue;c=j[f.expando];if(c){b=d[c]&&d[c][e];if(b&&b.events){for(var k in b.events)g[k]?f.event.remove(j,k):f.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[f.expando]:j.removeAttribute&&j.removeAttribute(f.expando),delete d[c]}}}});var bm=/alpha\([^)]*\)/i,bn=/opacity=([^)]*)/,bo=/([A-Z]|^ms)/g,bp=/^-?\d+(?:px)?$/i,bq=/^-?\d/,br=/^([\-+])=([\-+.\de]+)/,bs={position:"absolute",visibility:"hidden",display:"block"},bt=["Left","Right"],bu=["Top","Bottom"],bv,bw,bx;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bv(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=br.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bv)return bv(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return by(a,b,d);f.swap(a,bs,function(){e=by(a,b,d)});return e}},set:function(a,b){if(!bp.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bn.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bm,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bm.test(g)?g.replace(bm,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bv(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bw=function(a,c){var d,e,g;c=c.replace(bo,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bx=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bp.test(d)&&bq.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bv=bw||bx,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bz=/%20/g,bA=/\[\]$/,bB=/\r?\n/g,bC=/#.*$/,bD=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bE=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bF=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bG=/^(?:GET|HEAD)$/,bH=/^\/\//,bI=/\?/,bJ=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bK=/^(?:select|textarea)/i,bL=/\s+/,bM=/([?&])_=[^&]*/,bN=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bO=f.fn.load,bP={},bQ={},bR,bS,bT=["*/"]+["*"];try{bR=e.href}catch(bU){bR=c.createElement("a"),bR.href="",bR=bR.href}bS=bN.exec(bR.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bO)return bO.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bJ,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bK.test(this.nodeName)||bE.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bB,"\r\n")}}):{name:b.name,value:c.replace(bB,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?bX(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),bX(a,b);return a},ajaxSettings:{url:bR,isLocal:bF.test(bS[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bT},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bV(bP),ajaxTransport:bV(bQ),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?bZ(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=b$(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bD.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bC,"").replace(bH,bS[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bL),d.crossDomain==null&&(r=bN.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bS[1]&&r[2]==bS[2]&&(r[3]||(r[1]==="http:"?80:443))==(bS[3]||(bS[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bW(bP,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bG.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bI.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bM,"$1_="+x);d.url=y+(y===d.url?(bI.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bT+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bW(bQ,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){s<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bz,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+b_++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cl,cm=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cn;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cq("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cr(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cq("hide",3),a,b,c);for(var d=0,e=this.length;d<e;d++)if(this[d].style){var g=f.css(this[d],"display");g!=="none"&&!f._data(this[d],"olddisplay")&&f._data(this[d],"olddisplay",g)}for(d=0;d<e;d++)this[d].style&&(this[d].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cq("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return this[e.queue===!1?"each":"queue"](function(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(f.support.inlineBlockNeedsLayout?(j=cr(this.nodeName),j==="inline"?this.style.display="inline-block":(this.style.display="inline",this.style.zoom=1)):this.style.display="inline-block"))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)k=new f.fx(this,b,i),h=a[i],cj.test(h)?k[h==="toggle"?d?"show":"hide":h]():(l=ck.exec(h),m=k.cur(),l?(n=parseFloat(l[2]),o=l[3]||(f.cssNumber[i]?"":"px"),o!=="px"&&(f.style(this,i,(n||1)+o),m=(n||1)/k.cur()*m,f.style(this,i,m+o)),l[1]&&(n=(l[1]==="-="?-1:1)*n+m),k.custom(m,n,o)):k.custom(m,h,""));return!0})},stop:function(a,b){a&&this.queue([]),this.each(function(){var a=f.timers,c=a.length;b||f._unmark(!0,this);while(c--)a[c].elem===this&&(b&&a[c](!0),a.splice(c,1))}),b||this.dequeue();return this}}),f.each({slideDown:cq("show",1),slideUp:cq("hide",1),slideToggle:cq("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default,d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue!==!1?f.dequeue(this):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function g(a){return d.step(a)}var d=this,e=f.fx;this.startTime=cn||co(),this.start=a,this.end=b,this.unit=c||this.unit||(f.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,g.elem=this.elem,g()&&f.timers.push(g)&&!cl&&(cl=setInterval(e.tick,e.interval))},show:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=cn||co(),c=!0,d=this.elem,e=this.options,g,h;if(a||b>=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b<a.length;++b)a[b]()||a.splice(b--,1);a.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cl),cl=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cs=/^t(?:able|d|h)$/i,ct=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cu(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);f.offset.initialize();var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.offset.supportsFixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.offset.doesNotAddBorder&&(!f.offset.doesAddBorderForTableAndCells||!cs.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.offset.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.offset.supportsFixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={initialize:function(){var a=c.body,b=c.createElement("div"),d,e,g,h,i=parseFloat(f.css(a,"marginTop"))||0,j="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=ct.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!ct.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cu(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cu(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,"padding")):null},f.fn["outer"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNaN(j)?i:j}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window);
lib/action.php CHANGED
@@ -106,7 +106,7 @@ if (!$hashfail) {
106
  unset ($wassupurl); //to free memory
107
  }
108
 
109
- $debug_mode=false; //debug set below
110
  //echo "Debug: Starting action.php from directory ".dirname(__FILE__).". ABSPATH=".$wpabspath.".<br />\n"; //debug
111
 
112
  // ### Separate "delete" action because it has no output
@@ -126,7 +126,7 @@ if (!$hashfail) {
126
 
127
  // ### Begin actions that have output...
128
  if (!empty($_GET['debug_mode'])) {
129
- $debug_mode=true;
130
  $mode_reset=ini_get('display_errors');
131
  error_reporting(E_ALL); //debug, E_STRICT=php5 only
132
  ini_set('display_errors','On'); //debug
@@ -190,25 +190,25 @@ if (!$hashfail) {
190
  // ACTION: SUMMARY PIE CHART - TODO
191
  } elseif ($_GET['action'] == "piechart") {
192
  // Prepare Pie Chart
193
- $Tot = New MainItems($table_name,$from_date,$to_date);
194
- $items_pie[] = $Tot->calc_tot("count", $search, "AND spam>0", "DISTINCT");
195
- $items_pie[] = $Tot->calc_tot("count", $search, "AND searchengine!='' AND spam=0", "DISTINCT");
196
- $items_pie[] = $Tot->calc_tot("count", $search, "AND searchengine='' AND referrer NOT LIKE '%".$this->WpUrl."%' AND referrer!='' AND spam=0", "DISTINCT");
197
- $items_pie[] = $Tot->calc_tot("count", $search, "AND searchengine='' AND (referrer LIKE '%".$this->WpUrl."%' OR referrer='') AND spam=0", "DISTINCT"); ?>
198
  <div style="text-align: center"><img src="http://chart.apis.google.com/chart?cht=p3&amp;chco=0000ff&amp;chs=600x300&amp;chl=Spam|Search%20Engine|Referrer|Direct&amp;chd=<?php Gchart_data($items_pie, null, null, null, 'pie'); ?>" /></div>
199
 
200
  <?php
201
  // ACTION: LINE CHART - TODO
202
  //} elseif ($_GET['action'] == "chart") {
203
- // $chart = mainItems::theChart($from_date,$to_date,$search);
204
 
205
  // ACTION: DISPLAY RAW RECORDS - no longer used (deprecated)
206
  //} elseif ($_GET['action'] == "displayraw") {
207
 
208
  // ACTION: SHOW TOP TEN
209
  } elseif ($_GET['action'] == "topten") {
210
- $top_limit=10;
211
- if ($debug_mode) {
212
  $title='WassUp '.__('Top Stats for Period','wassup');
213
  $wdformat = get_option("date_format");
214
  if (($to_date - $from_date) > 24*60*60) {
@@ -224,7 +224,7 @@ if (!$hashfail) {
224
  } else {
225
  echo '<span style="color:red;">Action.php '.__("ERROR: Missing or unknown parameters","wassup").', action='.attribute_escape($_GET["action"]).'</span>';
226
  }
227
- if ($debug_mode) {
228
  if (function_exists('profiler_endSection')) {
229
  profiler_endSection('(Tot)Action.php');
230
  profiler_printResults();
106
  unset ($wassupurl); //to free memory
107
  }
108
 
109
+ $wdebug_mode=false; //debug set below
110
  //echo "Debug: Starting action.php from directory ".dirname(__FILE__).". ABSPATH=".$wpabspath.".<br />\n"; //debug
111
 
112
  // ### Separate "delete" action because it has no output
126
 
127
  // ### Begin actions that have output...
128
  if (!empty($_GET['debug_mode'])) {
129
+ $wdebug_mode=true;
130
  $mode_reset=ini_get('display_errors');
131
  error_reporting(E_ALL); //debug, E_STRICT=php5 only
132
  ini_set('display_errors','On'); //debug
190
  // ACTION: SUMMARY PIE CHART - TODO
191
  } elseif ($_GET['action'] == "piechart") {
192
  // Prepare Pie Chart
193
+ $wTot = New WassupItems($table_name,$from_date,$to_date);
194
+ $items_pie[] = $wTot->calc_tot("count", $search, "AND spam>0", "DISTINCT");
195
+ $items_pie[] = $wTot->calc_tot("count", $search, "AND searchengine!='' AND spam=0", "DISTINCT");
196
+ $items_pie[] = $wTot->calc_tot("count", $search, "AND searchengine='' AND referrer NOT LIKE '%".$this->WpUrl."%' AND referrer!='' AND spam=0", "DISTINCT");
197
+ $items_pie[] = $wTot->calc_tot("count", $search, "AND searchengine='' AND (referrer LIKE '%".$this->WpUrl."%' OR referrer='') AND spam=0", "DISTINCT"); ?>
198
  <div style="text-align: center"><img src="http://chart.apis.google.com/chart?cht=p3&amp;chco=0000ff&amp;chs=600x300&amp;chl=Spam|Search%20Engine|Referrer|Direct&amp;chd=<?php Gchart_data($items_pie, null, null, null, 'pie'); ?>" /></div>
199
 
200
  <?php
201
  // ACTION: LINE CHART - TODO
202
  //} elseif ($_GET['action'] == "chart") {
203
+ // $chart = WassupItems::theChart($from_date,$to_date,$search);
204
 
205
  // ACTION: DISPLAY RAW RECORDS - no longer used (deprecated)
206
  //} elseif ($_GET['action'] == "displayraw") {
207
 
208
  // ACTION: SHOW TOP TEN
209
  } elseif ($_GET['action'] == "topten") {
210
+ $top_limit=0; //use default setting
211
+ if ($wdebug_mode) {
212
  $title='WassUp '.__('Top Stats for Period','wassup');
213
  $wdformat = get_option("date_format");
214
  if (($to_date - $from_date) > 24*60*60) {
224
  } else {
225
  echo '<span style="color:red;">Action.php '.__("ERROR: Missing or unknown parameters","wassup").', action='.attribute_escape($_GET["action"]).'</span>';
226
  }
227
+ if ($wdebug_mode) {
228
  if (function_exists('profiler_endSection')) {
229
  profiler_endSection('(Tot)Action.php');
230
  profiler_printResults();
lib/compat_functions.php CHANGED
@@ -31,6 +31,14 @@ if (!function_exists('json_decode')) {
31
  } //end function json_decode
32
  }
33
 
 
 
 
 
 
 
 
 
34
  if (!function_exists('admin_url')) {
35
  function admin_url($admin_file="") {
36
  $adminurl = get_bloginfo('wpurl')."/wp-admin/".$admin_file;
31
  } //end function json_decode
32
  }
33
 
34
+ //'microtime_float' replicates microtime(true) from PHP5
35
+ if (!function_exists('microtime_float')) {
36
+ function microtime_float() {
37
+ list($usec, $sec) = explode(" ", microtime());
38
+ return ((float)$usec + (float)$sec);
39
+ }
40
+ }
41
+
42
  if (!function_exists('admin_url')) {
43
  function admin_url($admin_file="") {
44
  $adminurl = get_bloginfo('wpurl')."/wp-admin/".$admin_file;
lib/main.php CHANGED
@@ -585,9 +585,9 @@ function wCleanURL($url="") {
585
  return $cleaned_url;
586
  } //end function
587
 
588
- //Output wassup records in Digg spy style...
589
  function wassup_spiaView ($from_date="",$rows=0,$spytype="",$spy_datasource="") {
590
- global $wpdb, $wp_version, $wassup_options, $debug_mode;
591
 
592
  if (!class_exists('wassupOptions') && file_exists(dirname(__FILE__). '/wassup.class.php')) {
593
  include_once(dirname(__FILE__). '/wassup.class.php');
@@ -806,25 +806,25 @@ function wGetLocationname($geoip_rec=array()) {
806
 
807
  // Geocoding location with Google Maps
808
  function geocodeWassUp($location, $key) {
809
- global $debug_mode;
810
  //Three parts to querystring: q= address, output= format, and key
811
  $address = urlencode($location);
812
  $api_url = "http://maps.google.com/maps/geo?q=".$address."&output=csv&key=".$key;
813
 
814
  /*
815
- $ch = curl_init();
816
- curl_setopt($ch, CURLOPT_URL, $api_url);
817
- curl_setopt($ch, CURLOPT_HEADER,0);
818
- curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
819
- curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
820
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
821
-
822
- $data = curl_exec($ch);
823
- curl_close($ch);
824
  */
825
  $apidata = wFetchAPIData($api_url);
826
  $data = explode(',',$apidata);
827
- if ($debug_mode) {
828
  echo "\n<!--geocodeWassup data: ";
829
  print_r($data);
830
  echo "-->" ;
@@ -839,7 +839,7 @@ function geocodeWassUp($location, $key) {
839
  * @return array (ip, location, latitude, longitude, country)
840
  */
841
  function wGeolocateIP($ip) {
842
- global $wpdb, $debug_mode;
843
 
844
  $wassup_settings=get_option('wassup_settings');
845
  $wassup_agent = apply_filters('http_headers_useragent',"WassUp/".$wassup_settings['wassup_version']." - www.wpwp.org");
@@ -921,14 +921,14 @@ function wGeolocateIP($ip) {
921
  * - Helene D. 2009-03-04
922
  */
923
  function wGetStats($stat_type, $stat_limit=10, $stat_condition="") {
924
- global $wpdb, $debug_mode;
925
 
926
  $wassup_settings = get_option('wassup_settings');
927
  $top_ten = unserialize(html_entity_decode($wassup_settings['wassup_top10']));
928
  $wpurl = get_bloginfo('wpurl');
929
  $blogurl = get_option('home');
930
- $table_name = (!empty($wassup_settings['wassup_table'])?$wassup_settings['wassup_table'] : $wpdb->prefix . "wassup");
931
- $table_tmp_name = $table_name . "_tmp";
932
 
933
  if (empty($stat_limit) || !(is_numeric($stat_limit))) {
934
  $stat_limit=10;
@@ -949,17 +949,17 @@ function wGetStats($stat_type, $stat_limit=10, $stat_condition="") {
949
  //get the stats data
950
  //top search phrases...
951
  if ($stat_type == "searches") {
952
- $stat_results = $wpdb->get_results("SELECT count(search) AS top_count, search AS top_item, referrer AS top_link FROM $table_name WHERE $stat_condition AND search!='' AND spider='' GROUP BY search ORDER BY top_count DESC LIMIT $stat_limit");
953
 
954
  //top external referrers...
955
  } elseif ($stat_type == "referrers") {
956
  //exclude internal referrals
957
- $url = parse_url($blogurl);
958
- $sitedomain = $url['host'];
959
  $exclude_list = $sitedomain;
960
  if ($wpurl != $blogurl) {
961
- $url = parse_url($wpurl);
962
- $wpdomain = $url['host'];
963
  $exclude_list .= ",".$wpdomain;
964
  }
965
  //exclude external referrers
@@ -979,34 +979,39 @@ function wGetStats($stat_type, $stat_limit=10, $stat_condition="") {
979
  }
980
  }
981
  }
982
- $stat_results = $wpdb->get_results("SELECT count(*) AS top_count, LOWER(referrer) AS top_item, referrer AS top_link FROM $table_name WHERE $stat_condition AND referrer!='' AND search='' AND spider='' $exclude_referrers GROUP BY top_item ORDER BY top_count DESC LIMIT $stat_limit");
983
- if ($debug_mode) {
984
  echo "\n<pre>exclude_referrers = $exclude_referrers </pre>\n";
985
  }
986
 
987
  //top url requests...
988
  } elseif ($stat_type == "urlrequested") {
989
- $stat_results = $wpdb->get_results("SELECT count(*) AS top_count, LOWER(REPLACE(urlrequested, '/', '')) AS top_group, LOWER(urlrequested) AS top_item, urlrequested AS top_link FROM $table_name WHERE $stat_condition GROUP BY top_group ORDER BY top_count DESC LIMIT $stat_limit");
990
 
991
  //top browser...
992
  } elseif ($stat_type == "browser") {
993
- $stat_results = $wpdb->get_results("SELECT count(*) AS top_count, SUBSTRING_INDEX(SUBSTRING_INDEX(browser, ' 0.', 1), '.', 1) AS top_item FROM $table_name WHERE $stat_condition AND `browser`!='' AND `browser` NOT LIKE 'N/A%' AND `spider`='' GROUP BY top_item ORDER BY top_count DESC LIMIT $stat_limit");
994
 
995
  //top os...
996
  } elseif ($stat_type == "os") {
997
- $stat_results = $wpdb->get_results("SELECT count(os) as top_count, `os` AS top_item FROM $table_name WHERE $stat_condition AND `os`!='' AND `os` NOT LIKE 'N/A%' AND spider='' GROUP BY top_item ORDER BY top_count DESC LIMIT $stat_limit");
998
 
999
  //top language/locale..
1000
  } elseif ($stat_type == "language" || $stat_type == "locale") {
1001
- $stat_results = $wpdb->get_results("SELECT count(LOWER(language)) as top_count, LOWER(language) as top_item FROM $table_name WHERE $stat_condition AND language!='' AND spider='' GROUP BY top_item ORDER BY top_count DESC LIMIT $stat_limit");
1002
 
1003
  //top visitors...
1004
  } elseif ($stat_type == "visitor" || $stat_type == "visitors") {
1005
- $stat_results = $wpdb->get_results("SELECT count(username) as top_count, username as top_item, '1loggedin_user' as visitor_type, `timestamp` as visit_timestamp FROM $table_name WHERE $stat_condition AND username!='' GROUP BY 2 UNION SELECT count(comment_author) as top_count, comment_author as top_item, '2comment_author' as visitor_type, `timestamp` as visit_timestamp FROM $table_name WHERE $stat_condition AND username='' AND comment_author!='' GROUP BY 2 UNION SELECT count(hostname) as top_count, hostname as top_item, '3hostname' as visitor_type, `timestamp` as visit_timestamp FROM $table_name WHERE $stat_condition AND username='' AND comment_author='' AND spider='' GROUP BY 2 ORDER BY 1 DESC, 3, 2 LIMIT $stat_limit");
 
 
 
 
 
1006
  } else {
1007
  //TODO: check that wp_wassup.$stat_type column exist and is char
1008
  if (!empty($stat_type)) {
1009
- $stat_results = $wpdb->get_results("SELECT count($stat_type) AS top_count, `$stat_type` AS top_item FROM $table_name WHERE $stat_condition AND `$stat_type`!='' AND `$stat_type` NOT LIKE 'N/A%' GROUP BY `$stat_type` ORDER BY top_count DESC LIMIT $stat_limit");
1010
  }
1011
  }
1012
 
@@ -1023,15 +1028,16 @@ function wGetStats($stat_type, $stat_limit=10, $stat_condition="") {
1023
  * @param string(4)
1024
  * @return none
1025
  */
1026
- function wassup_top10view ($from_date="",$to_date="",$max_char_len="",$top_limit=10,$title=false) {
1027
  global $wpdb, $wassup_options;
1028
  if (!class_exists('wassupOptions') && file_exists(dirname(__FILE__). '/wassup.class.php')) {
1029
  include_once(dirname(__FILE__). '/wassup.class.php');
1030
  }
1031
  $wassup_options = new wassupOptions;
1032
  $top_ten = unserialize(html_entity_decode($wassup_options->wassup_top10));
1033
- $table_name = (!empty($wassup_options->wassup_table)? $wassup_options->wassup_table: $wpdb->prefix . "wassup");
1034
- $table_tmp_name = $table_name . "_tmp";
 
1035
 
1036
  $blogurl = get_bloginfo('home');
1037
  $url = parse_url($blogurl);
@@ -1052,28 +1058,42 @@ function wassup_top10view ($from_date="",$to_date="",$max_char_len="",$top_limit
1052
  $max_char_len = $max_char_len-16;
1053
  }
1054
  }
1055
- //#add an extra width offset when columns count < 5
1056
  $col_count = array_sum($top_ten);
1057
- if ($col_count > 0 && $col_count < 5 ) {
1058
- $widthoffset = (($max_char_len*(5 - $col_count))/$col_count)*.4; //just a guess
1059
  } else {
1060
  $widthoffset = 0;
1061
  }
1062
  //extend page width to make room for more than 5 columns
1063
  $pagewidth = $wassup_options->wassup_screen_res;
1064
- if ($col_count > 5) {
1065
- $pagewidth = $pagewidth+17*($col_count-5);
 
 
 
 
 
 
 
 
1066
  }
1067
 
1068
  //mysql conditional query...
1069
  $top_condition = '`timestamp` BETWEEN '.$from_date.' AND '.$to_date;
 
 
 
1070
  echo "\n"; ?>
1071
  <div id="toptenchart" style="width:auto;">
1072
- <table width="100%" border="0" style="margin:0; padding:0;">
1073
  <tr valign="top"><?php
1074
  if (!empty($title)) { ?>
1075
  <th colspan="<?php echo $col_count; ?>"><span style="centered"><?php echo $title; ?></span></th></tr><tr><?php
1076
  }
 
 
 
1077
  //#output top 10 searches
1078
  if ($top_ten['topsearch'] == 1) {
1079
  $top_results = wGetStats("searches",$top_limit,$top_condition);
@@ -1082,12 +1102,14 @@ function wassup_top10view ($from_date="",$to_date="",$max_char_len="",$top_limit
1082
  <ul class="charts">
1083
  <li class="chartsT"><?php echo _e("TOP QUERY", "wassup"); ?></li> <?php
1084
  $i=0;
 
1085
  if (count($top_results) >0) {
1086
- foreach ($top_results as $top10) {
1087
- echo "\n"; ?>
1088
- <li class="charts"><?php echo $top10->top_count.': <a href="'.$top10->top_link.'" target="_BLANK" title="'.substr($top10->top_item,0,$wassup_options->wassup_screen_res-100).'">'.stringShortener(preg_replace('/'.preg_quote($blogurl,'/').'/i', '', $top10->top_item),$char_len).'</a>'; ?></li><?php
 
1089
  $i++;
1090
- }
1091
  }
1092
  //finish list with empty <li> for style consistency
1093
  wListFiller($i,$top_limit,"charts"); ?>
@@ -1104,19 +1126,21 @@ function wassup_top10view ($from_date="",$to_date="",$max_char_len="",$top_limit
1104
  <td style="min-width:<?php echo ($char_len-5); ?>px;">
1105
  <ul class="charts">
1106
  <li class="chartsT"><?php _e("TOP REFERRER", "wassup"); ?></li><?php
1107
- $i=0;
 
1108
  if (count($top_results) >0) {
 
1109
  foreach ($top_results as $top10) {
1110
- echo "\n"; ?>
1111
- <li class="charts"><?php echo $top10->top_count.': ';
1112
- print '<a href="'.clean_url($top10->top_link,'','url').'" title="'.attribute_escape($top10->top_link).'" target="_BLANK">';
1113
  //#cut http:// from displayed url and truncate
1114
  //# instead of using stringShortener
1115
- print substr(str_replace("http://", "", attribute_escape($top10->top_item)),0,$char_len);
1116
  if (strlen($top10->top_item) > ($char_len + 7)) {
1117
- print '...';
1118
  }
1119
- print '</a>'; ?></li><?php
1120
  $i++;
1121
  }
1122
  }
@@ -1135,17 +1159,19 @@ function wassup_top10view ($from_date="",$to_date="",$max_char_len="",$top_limit
1135
  <ul class="charts">
1136
  <li class="chartsT"><?php _e("TOP REQUEST", "wassup"); ?></li><?php
1137
  $i=0;
 
1138
  if (count($top_results) >0) {
1139
- foreach ($top_results as $top10) {
1140
- echo "\n"; ?>
1141
- <li class="charts"><?php echo $top10->top_count.': ';
 
1142
  if (strstr($top10->top_item,'[404]')) { //no link for 404 pages
1143
- echo '<span class="top10" title="'.substr($top10->top_item,0,$wassup_options->wassup_screen_res-100).'">'.stringShortener(preg_replace('/'.preg_quote($blogurl,'/').'/i', '', $top10->top_item),$char_len).'</span>';
1144
  } else {
1145
- echo '<a href="'.wAddSiteurl($top10->top_link).'" target="_BLANK" title="'.substr($top10->top_item,0,$wassup_options->wassup_screen_res-100).'">'.stringShortener(preg_replace('/'.preg_quote($blogurl,'/').'/i', '', $top10->top_item),$char_len).'</a>';
1146
- } ?></li><?php
1147
- $i++;
1148
- }
1149
  }
1150
  //finish list with empty <li> for styling consistency
1151
  wListFiller($i,$top_limit,"charts"); ?>
@@ -1162,13 +1188,15 @@ function wassup_top10view ($from_date="",$to_date="",$max_char_len="",$top_limit
1162
  <ul class="charts">
1163
  <li class="chartsT"><?php _e("TOP BROWSER", "wassup") ?></li><?php
1164
  $i=0;
 
1165
  if (count($top_results) >0) {
1166
- foreach ($top_results as $top10) {
1167
- echo "\n"; ?>
1168
- <li class="charts"><?php echo $top10->top_count.': ';
1169
- echo '<span class="top10" title="'.$top10->top_item.'">'.stringShortener($top10->top_item, $char_len).'</span>'; ?></li><?php
1170
- $i++;
1171
- }
 
1172
  }
1173
  //finish list with empty <li> for styling consistency
1174
  wListFiller($i,$top_limit,"charts"); ?>
@@ -1185,12 +1213,14 @@ function wassup_top10view ($from_date="",$to_date="",$max_char_len="",$top_limit
1185
  <ul class="charts">
1186
  <li class="chartsT"><?php _e("TOP OS", "wassup") ?></li><?php
1187
  $i=0;
 
1188
  if (count($top_results) >0) {
1189
- foreach ($top_results as $top10) {
1190
- echo "\n"; ?>
1191
- <li class="charts"><?php print $top10->top_count.': '; ?><span class="top10" title="<?php echo $top10->top_item; ?>"><?php echo stringShortener($top10->top_item, $char_len); ?></span></li><?php
1192
- $i++;
1193
- }
 
1194
  }
1195
  //finish list with empty <li> for styling consistency
1196
  wListFiller($i,$top_limit,"charts"); ?>
@@ -1207,14 +1237,16 @@ function wassup_top10view ($from_date="",$to_date="",$max_char_len="",$top_limit
1207
  <ul class="charts">
1208
  <li class="chartsT"><?php _e("TOP LOCALE", "wassup"); ?></li><?php
1209
  $i=0;
 
1210
  if (count($top_results) >0) {
1211
- foreach ($top_results as $top10) {
1212
- echo "\n"; ?>
1213
- <li class="charts"><?php echo $top10->top_count.': ';
1214
- echo '<img src="'.WASSUPURL.'/img/flags/'.strtolower($top10->top_item).'.png" alt="" />'; ?>
1215
- <span class="top10" title="<?php echo $top10->top_item; ?>"><?php echo $top10->top_item; ?></span></li><?php
1216
- $i++;
1217
- }
 
1218
  }
1219
  //finish list with empty <li> for styling consistency
1220
  wListFiller($i,$top_limit,"charts"); ?>
@@ -1231,29 +1263,67 @@ function wassup_top10view ($from_date="",$to_date="",$max_char_len="",$top_limit
1231
  <ul class="charts">
1232
  <li class="chartsT"><?php _e("TOP VISITOR", "wassup"); ?></li><?php
1233
  $i=0;
 
1234
  if (count($top_results)>0) {
1235
- foreach ($top_results as $top10) {
1236
- if ($top10->visitor_type == "1loggedin_user")
1237
- $uclass=" userslogged";
1238
- elseif ($top10->visitor_type == "2comment_author")
1239
- $uclass=" users";
1240
- else
1241
- $uclass="";
1242
- echo "\n"; ?>
1243
- <li class="charts"><?php echo $top10->top_count.': <span class="top10'.$uclass.'" title="'.$top10->top_item.'">'.stringShortener($top10->top_item, $char_len).'</span>'; ?></li><?php
1244
- $i++;
1245
- } //end loop
 
1246
  }
1247
  //finish list with empty <li> for styling consistency
1248
  wListFiller($i,$top_limit,"charts"); ?>
1249
  </ul>
1250
  </td>
1251
  <?php } // end if topvisitor
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1252
  ?></tr>
1253
- </table><?php
1254
- if ($wassup_options->wassup_spamcheck == 1) { ?>
1255
- <br/><span style="font-size:6pt;">* <?php _e("This report excludes Spam records","wassup"); ?></span><?php
1256
- } ?>
 
 
 
 
 
 
 
1257
  </div> <?php
1258
  } //end wassup_top10view
1259
 
@@ -1266,23 +1336,60 @@ function wListFiller($li_count=0,$li_limit=10,$li_class="charts") {
1266
  }
1267
  }
1268
  } //end wListFiller
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1269
 
1270
- // How many digits have an integer
1271
- function digit_count($n, $base=10) {
1272
- if($n == 0) return 1;
1273
- if($base == 10) {
1274
- # using the built-in log10(x)
1275
- # might be more accurate than log(x)/log(10).
1276
- return 1 + floor(log10(abs($n)));
1277
- }else{
1278
- # here logB(x) = log(x)/log(B) will have to do.
1279
- return 1 + floor(log(abs($n))/ log($base));
1280
- }
 
 
 
 
1281
  }
1282
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1283
  //Round the integer to the next near 10
1284
  function roundup($value) {
1285
- $dg = digit_count($value);
 
 
1286
  if ($dg <= 2) {
1287
  $dg = 1;
1288
  } else {
@@ -1292,7 +1399,7 @@ function roundup($value) {
1292
  }
1293
 
1294
  function Gchart_data($Wvisits, $pages=null, $atime=null, $type, $charttype=null, $axes=null, $chart_loc=null) {
1295
- global $debug_mode;
1296
  $chartAPIdata = false;
1297
  // Port of JavaScript from http://code.google.com/apis/chart/
1298
  // http://james.cridland.net/code
@@ -1373,7 +1480,7 @@ function Gchart_data($Wvisits, $pages=null, $atime=null, $type, $charttype=null,
1373
  } //end function
1374
 
1375
  // Used to show main visitors details query, to count items and to extract data for main chart
1376
- class MainItems {
1377
  // declare variables
1378
  var $tableName;
1379
  var $from_date;
@@ -1386,8 +1493,8 @@ class MainItems {
1386
  var $WpUrl;
1387
 
1388
  /* Constructor */
1389
- function mainitems($table_name,$date_from,$date_to,$whereis=null,$limit=null) {
1390
- global $wpdb, $wassup_options, $debug_mode;
1391
  if (empty($wassup_options->wassup_table)) {
1392
  $wassup_options = new wassupOptions;
1393
  }
@@ -1420,7 +1527,7 @@ class MainItems {
1420
  /* Methods */
1421
  // Function to show main query and count items
1422
  function calc_tot($Type, $Search="", $specific_where_clause=null, $distinct_type=null) {
1423
- global $wpdb, $wassup_options, $debug_mode;
1424
 
1425
  $this->ItemsType = $Type;
1426
  $this->searchString = $Search;
@@ -1443,7 +1550,7 @@ class MainItems {
1443
  //main query
1444
  // - retrieve one row per wassup_id with timestamp = max(timestamp) (ie. latest record)
1445
  // "sql_buffer_result" select option helps in cases where it takes a long time to retrieve results. -Helene D. 2/29/09
1446
- $qry = sprintf("SELECT SQL_BUFFER_RESULT *, max(`timestamp`) as max_timestamp, count(wassup_id) as page_hits FROM %s WHERE `timestamp` >= %s %s %s GROUP BY wassup_id ORDER BY max_timestamp DESC %s",
1447
  $this->tableName,
1448
  $this->from_date,
1449
  $ss,
@@ -1451,7 +1558,7 @@ class MainItems {
1451
  $this->Limit);
1452
  $results = $wpdb->get_results($qry);
1453
  if (empty($results) || !is_array($results)) { //try without buffer
1454
- $qry = sprintf("SELECT *, max(`timestamp`) as max_timestamp, count(wassup_id) as page_hits FROM %s WHERE `timestamp` >= %s %s %s GROUP BY wassup_id ORDER BY max_timestamp DESC %s",
1455
  $this->tableName,
1456
  $this->from_date,
1457
  $ss,
@@ -1475,7 +1582,7 @@ class MainItems {
1475
  break;
1476
  case "main-ip": //TODO
1477
  // These are the queries to count the hits/pages/spam by ip
1478
- $qry = sprintf("SELECT *, max(`timestamp`) as max_timestamp, count(`ip`) as page_hits FROM %s WHERE `timestamp` >= %s %s %s GROUP BY ip ORDER BY max_timestamp DESC %s",
1479
  $this->tableName,
1480
  $this->from_date,
1481
  $ss,
@@ -1505,7 +1612,7 @@ class MainItems {
1505
  // $Res = resolution
1506
  // $Search = string to add to where clause
1507
  function TheChart($Ctype, $Res, $chart_height, $Search="", $axes_type, $chart_bg, $chart_loc="page", $chart_group="") {
1508
- global $wpdb, $wassup_options, $debug_mode;
1509
 
1510
  $mysqlversion=substr(mysql_get_server_info(),0,3);
1511
  $cache_table = (!empty($wassup_options->wassup_table)?$wassup_options->wassup_table."_meta":$wpdb->prefix."wassup_meta");
@@ -1528,7 +1635,7 @@ class MainItems {
1528
  if (count($chart_cache)>0 && !empty($wassup_cache[0]->meta_value)) {
1529
  $chart_url = html_entity_decode($wassup_cache[0]->meta_value);
1530
  $cache_id = $wassup_cache[0]->meta_id;
1531
- if ($debug_mode) {
1532
  echo "\n<!-- Cached chart found. cache_id=$cache_id -->\n";
1533
  }
1534
  }
@@ -1704,7 +1811,7 @@ class MainItems {
1704
  $tlabel[] = gmdate($wp_timeformat,$x_timestamp);
1705
  }
1706
  }
1707
- if ($debug_mode) {
1708
  echo "\n<!-- \$x-points= ".implode("|",$tlabel)."\n";
1709
  echo " \$tgroup=".implode("|",$tgroup)."-->";
1710
  }
@@ -1730,7 +1837,7 @@ class MainItems {
1730
  $this->whereis,
1731
  $ss);
1732
  }
1733
- if ($debug_mode) {
1734
  echo "\n<!-- \$query= $qry-->\n";
1735
  }
1736
  $qry_result = $wpdb->get_results($qry,ARRAY_A);
@@ -1769,7 +1876,7 @@ class MainItems {
1769
  //prune overcrowded x-axis labels //TODO
1770
  //if (count($x_label) > 20 && $chart_width < 1000) {
1771
  //}
1772
- if ($debug_mode) {
1773
  echo "\n<!-- \$x-group= ".implode("|",$x_group);
1774
  echo "\n \$x-labels= ".implode("|",$x_label)."-->\n";
1775
  }
@@ -1843,7 +1950,7 @@ class MainItems {
1843
  return $ss;
1844
  } //end function buildSearch
1845
 
1846
- } //end class mainItems
1847
 
1848
  // Class to check if a previous comment with a specific IP was detected as SPAM by Akismet default plugin
1849
  class wassup_checkComment {
@@ -1945,7 +2052,7 @@ class wcURL {
1945
  * @since v1.8
1946
  */
1947
  function wFetchAPIData($api_url) {
1948
- global $debug_mode;
1949
 
1950
  $wassup_settings=get_option('wassup_settings');
1951
  $wassup_agent = apply_filters('http_headers_useragent',"WassUp/".$wassup_settings['wassup_version']." - www.wpwp.org");
@@ -1985,7 +2092,7 @@ function wFetchAPIData($api_url) {
1985
  }
1986
  $api_method='file_get_contents'; //debug
1987
  }
1988
- if ($debug_mode) {
1989
  echo "\n<!-- <br>API Fetch using $api_method data: "; //debug
1990
  print_r($apidata);
1991
  echo "-->\n";
585
  return $cleaned_url;
586
  } //end function
587
 
588
+ //Output wassup records in the old Digg spy style...
589
  function wassup_spiaView ($from_date="",$rows=0,$spytype="",$spy_datasource="") {
590
+ global $wpdb, $wp_version, $wassup_options, $wdebug_mode;
591
 
592
  if (!class_exists('wassupOptions') && file_exists(dirname(__FILE__). '/wassup.class.php')) {
593
  include_once(dirname(__FILE__). '/wassup.class.php');
806
 
807
  // Geocoding location with Google Maps
808
  function geocodeWassUp($location, $key) {
809
+ global $wdebug_mode;
810
  //Three parts to querystring: q= address, output= format, and key
811
  $address = urlencode($location);
812
  $api_url = "http://maps.google.com/maps/geo?q=".$address."&output=csv&key=".$key;
813
 
814
  /*
815
+ //$ch = curl_init();
816
+ //curl_setopt($ch, CURLOPT_URL, $api_url);
817
+ //curl_setopt($ch, CURLOPT_HEADER,0);
818
+ //curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
819
+ //curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
820
+ //curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
821
+
822
+ //$data = curl_exec($ch);
823
+ //curl_close($ch);
824
  */
825
  $apidata = wFetchAPIData($api_url);
826
  $data = explode(',',$apidata);
827
+ if ($wdebug_mode) {
828
  echo "\n<!--geocodeWassup data: ";
829
  print_r($data);
830
  echo "-->" ;
839
  * @return array (ip, location, latitude, longitude, country)
840
  */
841
  function wGeolocateIP($ip) {
842
+ global $wpdb, $wdebug_mode;
843
 
844
  $wassup_settings=get_option('wassup_settings');
845
  $wassup_agent = apply_filters('http_headers_useragent',"WassUp/".$wassup_settings['wassup_version']." - www.wpwp.org");
921
  * - Helene D. 2009-03-04
922
  */
923
  function wGetStats($stat_type, $stat_limit=10, $stat_condition="") {
924
+ global $wpdb, $wdebug_mode;
925
 
926
  $wassup_settings = get_option('wassup_settings');
927
  $top_ten = unserialize(html_entity_decode($wassup_settings['wassup_top10']));
928
  $wpurl = get_bloginfo('wpurl');
929
  $blogurl = get_option('home');
930
+ $wtable_name = (!empty($wassup_settings['wassup_table'])?$wassup_settings['wassup_table'] : $wpdb->prefix . "wassup");
931
+ $wtable_tmp_name = $wtable_name . "_tmp";
932
 
933
  if (empty($stat_limit) || !(is_numeric($stat_limit))) {
934
  $stat_limit=10;
949
  //get the stats data
950
  //top search phrases...
951
  if ($stat_type == "searches") {
952
+ $stat_results = $wpdb->get_results("SELECT count(search) AS top_count, search AS top_item, referrer AS top_link, max(`timestamp`) AS visit_timestamp FROM $wtable_name WHERE $stat_condition AND search!='' AND spider='' GROUP BY search ORDER BY top_count DESC, visit_timestamp DESC LIMIT $stat_limit");
953
 
954
  //top external referrers...
955
  } elseif ($stat_type == "referrers") {
956
  //exclude internal referrals
957
+ $wurl = parse_url($blogurl);
958
+ $sitedomain = $wurl['host'];
959
  $exclude_list = $sitedomain;
960
  if ($wpurl != $blogurl) {
961
+ $wurl = parse_url($wpurl);
962
+ $wpdomain = $wurl['host'];
963
  $exclude_list .= ",".$wpdomain;
964
  }
965
  //exclude external referrers
979
  }
980
  }
981
  }
982
+ $stat_results = $wpdb->get_results("SELECT count(*) AS top_count, LOWER(referrer) AS top_item, referrer AS top_link, max(`timestamp`) AS visit_timestamp FROM $wtable_name WHERE $stat_condition AND referrer!='' AND search='' AND spider='' $exclude_referrers GROUP BY top_item ORDER BY top_count DESC, visit_timestamp DESC LIMIT $stat_limit");
983
+ if ($wdebug_mode) {
984
  echo "\n<pre>exclude_referrers = $exclude_referrers </pre>\n";
985
  }
986
 
987
  //top url requests...
988
  } elseif ($stat_type == "urlrequested") {
989
+ $stat_results = $wpdb->get_results("SELECT count(*) AS top_count, LOWER(REPLACE(urlrequested, '/', '')) AS top_group, LOWER(urlrequested) AS top_item, urlrequested AS top_link, max(`timestamp`) AS visit_timestamp FROM $wtable_name WHERE $stat_condition GROUP BY top_group ORDER BY top_count DESC, visit_timestamp DESC LIMIT $stat_limit");
990
 
991
  //top browser...
992
  } elseif ($stat_type == "browser") {
993
+ $stat_results = $wpdb->get_results("SELECT count(*) AS top_count, SUBSTRING_INDEX(SUBSTRING_INDEX(browser, ' 0.', 1), '.', 1) AS top_item FROM $wtable_name WHERE $stat_condition AND `browser`!='' AND `browser` NOT LIKE 'N/A%' AND `spider`='' GROUP BY top_item ORDER BY top_count DESC LIMIT $stat_limit");
994
 
995
  //top os...
996
  } elseif ($stat_type == "os") {
997
+ $stat_results = $wpdb->get_results("SELECT count(os) as top_count, `os` AS top_item FROM $wtable_name WHERE $stat_condition AND `os`!='' AND `os` NOT LIKE 'N/A%' AND spider='' GROUP BY top_item ORDER BY top_count DESC LIMIT $stat_limit");
998
 
999
  //top language/locale..
1000
  } elseif ($stat_type == "language" || $stat_type == "locale") {
1001
+ $stat_results = $wpdb->get_results("SELECT count(LOWER(language)) as top_count, LOWER(language) as top_item FROM $wtable_name WHERE $stat_condition AND language!='' AND spider='' GROUP BY top_item ORDER BY top_count DESC LIMIT $stat_limit");
1002
 
1003
  //top visitors...
1004
  } elseif ($stat_type == "visitor" || $stat_type == "visitors") {
1005
+ $stat_results = $wpdb->get_results("SELECT count(username) as top_count, username as top_item, '1loggedin_user' as visitor_type, max(`timestamp`) as visit_timestamp FROM $wtable_name WHERE $stat_condition AND username!='' GROUP BY 2 UNION SELECT count(comment_author) as top_count, comment_author as top_item, '2comment_author' as visitor_type, max(`timestamp`) as visit_timestamp FROM $wtable_name WHERE $stat_condition AND username='' AND comment_author!='' GROUP BY 2 UNION SELECT count(hostname) as top_count, hostname as top_item, '3hostname' as visitor_type, max(`timestamp`) as visit_timestamp FROM $wtable_name WHERE $stat_condition AND username='' AND comment_author='' AND spider='' GROUP BY 2 ORDER BY 1 DESC, 3, 2 LIMIT $stat_limit");
1006
+
1007
+ //top postid (post|page)
1008
+ } elseif ($stat_type == "postid" || $stat_type == "article") {
1009
+ $stat_results = $wpdb->get_results("SELECT count(*) AS top_count, url_wpid AS top_group, post_title AS top_item, urlrequested AS top_link, max(`timestamp`) as visit_timestamp FROM $wtable_name, {$wpdb->prefix}posts WHERE $stat_condition AND url_wpid!='' AND url_wpid!='0' AND url_wpid = {$wpdb->prefix}posts.ID GROUP BY top_group ORDER BY top_count DESC, visit_timestamp DESC LIMIT $stat_limit");
1010
+
1011
  } else {
1012
  //TODO: check that wp_wassup.$stat_type column exist and is char
1013
  if (!empty($stat_type)) {
1014
+ $stat_results = $wpdb->get_results("SELECT count($stat_type) AS top_count, `$stat_type` AS top_item FROM $wtable_name WHERE $stat_condition AND `$stat_type`!='' AND `$stat_type` NOT LIKE 'N/A%' GROUP BY `$stat_type` ORDER BY top_count DESC LIMIT $stat_limit");
1015
  }
1016
  }
1017
 
1028
  * @param string(4)
1029
  * @return none
1030
  */
1031
+ function wassup_top10view ($from_date="",$to_date="",$max_char_len="",$top_limit=0,$title=false) {
1032
  global $wpdb, $wassup_options;
1033
  if (!class_exists('wassupOptions') && file_exists(dirname(__FILE__). '/wassup.class.php')) {
1034
  include_once(dirname(__FILE__). '/wassup.class.php');
1035
  }
1036
  $wassup_options = new wassupOptions;
1037
  $top_ten = unserialize(html_entity_decode($wassup_options->wassup_top10));
1038
+ if (!is_array($top_ten)) $top_ten = $wassup_options->defaultSettings("top10");
1039
+ //$table_name = (!empty($wassup_options->wassup_table)? $wassup_options->wassup_table: $wpdb->prefix . "wassup");
1040
+ //$table_tmp_name = $table_name . "_tmp";
1041
 
1042
  $blogurl = get_bloginfo('home');
1043
  $url = parse_url($blogurl);
1058
  $max_char_len = $max_char_len-16;
1059
  }
1060
  }
1061
+ //#add an extra width offset when columns count < 6
1062
  $col_count = array_sum($top_ten);
1063
+ if ($col_count > 0 && $col_count < 6 ) {
1064
+ $widthoffset = (($max_char_len*(6 - $col_count))/$col_count)*.4; //just a guess
1065
  } else {
1066
  $widthoffset = 0;
1067
  }
1068
  //extend page width to make room for more than 5 columns
1069
  $pagewidth = $wassup_options->wassup_screen_res;
1070
+ if ($col_count > 6) {
1071
+ $pagewidth = $pagewidth+17*($col_count-6);
1072
+ }
1073
+ //New in v1.8.3: top_limit in top10 array
1074
+ if (empty($top_limit) || !is_numeric($top_limit)) {
1075
+ if (!empty($top_ten['toplimit'])) {
1076
+ $top_limit = (int) $top_ten['toplimit'];
1077
+ } else {
1078
+ $top_limit = 10; //default
1079
+ }
1080
  }
1081
 
1082
  //mysql conditional query...
1083
  $top_condition = '`timestamp` BETWEEN '.$from_date.' AND '.$to_date;
1084
+ if (!empty($top_ten['top_nospider'])) {
1085
+ $top_condition .= " AND spider=''";
1086
+ }
1087
  echo "\n"; ?>
1088
  <div id="toptenchart" style="width:auto;">
1089
+ <table width="100%">
1090
  <tr valign="top"><?php
1091
  if (!empty($title)) { ?>
1092
  <th colspan="<?php echo $col_count; ?>"><span style="centered"><?php echo $title; ?></span></th></tr><tr><?php
1093
  }
1094
+ //show a line# column for long data columns
1095
+ if ($top_limit > 10) wPrintRowNums($top_limit);
1096
+
1097
  //#output top 10 searches
1098
  if ($top_ten['topsearch'] == 1) {
1099
  $top_results = wGetStats("searches",$top_limit,$top_condition);
1102
  <ul class="charts">
1103
  <li class="chartsT"><?php echo _e("TOP QUERY", "wassup"); ?></li> <?php
1104
  $i=0;
1105
+ $ndigits=1;
1106
  if (count($top_results) >0) {
1107
+ $ndigits = strlen("{$top_results[0]->top_count}");
1108
+ foreach ($top_results as $top10) {
1109
+ echo "\n"; ?>
1110
+ <li class="charts"><nobr><?php echo wPadNum($top10->top_count, $ndigits).' <a href="'.$top10->top_link.'" target="_BLANK" title="'.substr($top10->top_item,0,$wassup_options->wassup_screen_res-100).'">'.stringShortener(preg_replace('/'.preg_quote($blogurl,'/').'/i', '', $top10->top_item),$char_len).'</a>'; ?></nobr></li><?php
1111
  $i++;
1112
+ }
1113
  }
1114
  //finish list with empty <li> for style consistency
1115
  wListFiller($i,$top_limit,"charts"); ?>
1126
  <td style="min-width:<?php echo ($char_len-5); ?>px;">
1127
  <ul class="charts">
1128
  <li class="chartsT"><?php _e("TOP REFERRER", "wassup"); ?></li><?php
1129
+ $i=0;
1130
+ $ndigits=1;
1131
  if (count($top_results) >0) {
1132
+ $ndigits = strlen("{$top_results[0]->top_count}");
1133
  foreach ($top_results as $top10) {
1134
+ echo "\n"; ?>
1135
+ <li class="charts"><nobr><?php echo wPadNum($top10->top_count,$ndigits);
1136
+ echo ' <a href="'.clean_url($top10->top_link,'','url').'" title="'.attribute_escape($top10->top_link).'" target="_BLANK">';
1137
  //#cut http:// from displayed url and truncate
1138
  //# instead of using stringShortener
1139
+ echo substr(str_replace("http://", "", attribute_escape($top10->top_item)),0,$char_len);
1140
  if (strlen($top10->top_item) > ($char_len + 7)) {
1141
+ echo '...';
1142
  }
1143
+ echo '</a>'; ?></nobr></li><?php
1144
  $i++;
1145
  }
1146
  }
1159
  <ul class="charts">
1160
  <li class="chartsT"><?php _e("TOP REQUEST", "wassup"); ?></li><?php
1161
  $i=0;
1162
+ $ndigits=1;
1163
  if (count($top_results) >0) {
1164
+ $ndigits = strlen("{$top_results[0]->top_count}");
1165
+ foreach ($top_results as $top10) {
1166
+ echo "\n"; ?>
1167
+ <li class="charts"><nobr><?php echo wPadNum($top10->top_count,$ndigits);
1168
  if (strstr($top10->top_item,'[404]')) { //no link for 404 pages
1169
+ echo ' <span class="top10" title="'.substr($top10->top_item,0,$wassup_options->wassup_screen_res-100).'">'.stringShortener(preg_replace('/'.preg_quote($blogurl,'/').'/i', '', $top10->top_item),$char_len).'</span>';
1170
  } else {
1171
+ echo ' <a href="'.wAddSiteurl($top10->top_link).'" target="_BLANK" title="'.substr($top10->top_item,0,$wassup_options->wassup_screen_res-100).'">'.stringShortener(preg_replace('/'.preg_quote($blogurl,'/').'/i', '', $top10->top_item),$char_len).'</a>';
1172
+ } ?></nobr></li><?php
1173
+ $i++;
1174
+ }
1175
  }
1176
  //finish list with empty <li> for styling consistency
1177
  wListFiller($i,$top_limit,"charts"); ?>
1188
  <ul class="charts">
1189
  <li class="chartsT"><?php _e("TOP BROWSER", "wassup") ?></li><?php
1190
  $i=0;
1191
+ $ndigits=1;
1192
  if (count($top_results) >0) {
1193
+ $ndigits = strlen("{$top_results[0]->top_count}");
1194
+ foreach ($top_results as $top10) {
1195
+ echo "\n"; ?>
1196
+ <li class="charts"><nobr><?php echo wPadNum($top10->top_count,$ndigits);
1197
+ echo ' <span class="top10" title="'.$top10->top_item.'">'.stringShortener($top10->top_item, $char_len).'</span>'; ?></nobr></li><?php
1198
+ $i++;
1199
+ }
1200
  }
1201
  //finish list with empty <li> for styling consistency
1202
  wListFiller($i,$top_limit,"charts"); ?>
1213
  <ul class="charts">
1214
  <li class="chartsT"><?php _e("TOP OS", "wassup") ?></li><?php
1215
  $i=0;
1216
+ $ndigits=1;
1217
  if (count($top_results) >0) {
1218
+ $ndigits = strlen("{$top_results[0]->top_count}");
1219
+ foreach ($top_results as $top10) {
1220
+ echo "\n"; ?>
1221
+ <li class="charts"><nobr><?php echo wPadNum($top10->top_count,$ndigits); ?> <span class="top10" title="<?php echo $top10->top_item; ?>"><?php echo stringShortener($top10->top_item, $char_len); ?></span></nobr></li><?php
1222
+ $i++;
1223
+ }
1224
  }
1225
  //finish list with empty <li> for styling consistency
1226
  wListFiller($i,$top_limit,"charts"); ?>
1237
  <ul class="charts">
1238
  <li class="chartsT"><?php _e("TOP LOCALE", "wassup"); ?></li><?php
1239
  $i=0;
1240
+ $ndigits=1;
1241
  if (count($top_results) >0) {
1242
+ $ndigits = strlen("{$top_results[0]->top_count}");
1243
+ foreach ($top_results as $top10) {
1244
+ echo "\n"; ?>
1245
+ <li class="charts"><nobr><?php echo wPadNum($top10->top_count,$ndigits);
1246
+ echo ' <img src="'.WASSUPURL.'/img/flags/'.strtolower($top10->top_item).'.png" alt="" />'; ?>
1247
+ <span class="top10" title="<?php echo $top10->top_item; ?>"><?php echo $top10->top_item; ?></span></nobr></li><?php
1248
+ $i++;
1249
+ }
1250
  }
1251
  //finish list with empty <li> for styling consistency
1252
  wListFiller($i,$top_limit,"charts"); ?>
1263
  <ul class="charts">
1264
  <li class="chartsT"><?php _e("TOP VISITOR", "wassup"); ?></li><?php
1265
  $i=0;
1266
+ $ndigits=1;
1267
  if (count($top_results)>0) {
1268
+ $ndigits = strlen("{$top_results[0]->top_count}");
1269
+ foreach ($top_results as $top10) {
1270
+ if ($top10->visitor_type == "1loggedin_user")
1271
+ $uclass=" userslogged";
1272
+ elseif ($top10->visitor_type == "2comment_author")
1273
+ $uclass=" users";
1274
+ else
1275
+ $uclass="";
1276
+ echo "\n"; ?>
1277
+ <li class="charts"><nobr><?php echo wPadNum($top10->top_count,$ndigits).' <span class="top10'.$uclass.'" title="'.$top10->top_item.'">'.stringShortener($top10->top_item, $char_len).'</span>'; ?></nobr></li><?php
1278
+ $i++;
1279
+ } //end loop
1280
  }
1281
  //finish list with empty <li> for styling consistency
1282
  wListFiller($i,$top_limit,"charts"); ?>
1283
  </ul>
1284
  </td>
1285
  <?php } // end if topvisitor
1286
+
1287
+ //#output top article (post|page by id)
1288
+ if ($top_ten['toppostid'] == 1) {
1289
+ echo "\n<!--heartbeat-->";
1290
+ $top_results = wGetStats("postid",$top_limit,$top_condition);
1291
+ $char_len = round(($max_char_len*.28)+$widthoffset,0); ?>
1292
+ <td style="min-width:<?php echo ($char_len-5); ?>px;">
1293
+ <ul class="charts">
1294
+ <li class="chartsT"><?php _e("TOP ARTICLE", "wassup"); ?></li><?php
1295
+ $i=0;
1296
+ $ndigits=1;
1297
+ if (count($top_results) >0) {
1298
+ $ndigits = strlen("{$top_results[0]->top_count}");
1299
+ foreach ($top_results as $top10) {
1300
+ echo "\n"; ?>
1301
+ <li class="charts"><nobr><?php echo wPadNum($top10->top_count,$ndigits);
1302
+ echo ' <a href="'.wAddSiteurl($top10->top_link).'" target="_BLANK" title="'.$top10->top_item.'">'.stringShortener($top10->top_item,$char_len).'</a>'; ?> </nobr></li><?php
1303
+ $i++;
1304
+ }
1305
+ }
1306
+ //finish list with empty <li> for styling consistency
1307
+ wListFiller($i,$top_limit,"charts"); ?>
1308
+ </ul>
1309
+ </td><?php
1310
+ } // end if toppost
1311
+ //show a line# column for long data columns
1312
+ if ($top_limit > 10 && $col_count > 6) {
1313
+ wPrintRowNums($top_limit);
1314
+ }
1315
  ?></tr>
1316
+ </table>
1317
+ <span style="font-size:7pt;"> <?php
1318
+ if ($wassup_options->wassup_spamcheck == 1 || !empty($top_ten['top_nospider'])) { ?><br/>*<?php
1319
+ if ($wassup_options->wassup_spamcheck == 1 && !empty($top_ten['top_nospider'])) {
1320
+ _e("This report excludes spam and spider records","wassup");
1321
+ } elseif (!empty($top_ten['top_nospider'])) {
1322
+ _e("This report excludes spider records","wassup");
1323
+ } else {
1324
+ _e("This report excludes spam records","wassup");
1325
+ }
1326
+ } ?> </span>
1327
  </div> <?php
1328
  } //end wassup_top10view
1329
 
1336
  }
1337
  }
1338
  } //end wListFiller
1339
+ /*
1340
+ * print a table column with line number rows from 1 to "$top_limit"
1341
+ * @param integer
1342
+ * @output html
1343
+ * @return none
1344
+ */
1345
+ function wPrintRowNums($top_limit=10) {
1346
+ $ndigits = strlen("{$top_limit}");
1347
+ echo "\n"; ?>
1348
+ <td style="min-width:8px;">
1349
+ <ul class="charts rownums">
1350
+ <li class="chartsT">&nbsp;</li><?php
1351
+ for ($i=1; $i<= $top_limit; $i++) {
1352
+ echo "\n"; ?>
1353
+ <li class="charts"><nobr><?php echo wPadNum($i, $ndigits); ?></nobr></li><?php
1354
+ } ?>
1355
+ </td><?php
1356
+ } //end function
1357
 
1358
+ /**
1359
+ * return html code to pad an integer ($li_number) with spaces to match a
1360
+ * width of $li_width
1361
+ * @param integer (2)
1362
+ * @return string (html)
1363
+ */
1364
+ function wPadNum($li_number, $li_width=1) {
1365
+ $numstr = (int)$li_number;
1366
+ $ndigits = strlen("$numstr");
1367
+ $padding = '';
1368
+ if ($ndigits < $li_width) {
1369
+ for ($i=$ndigits; $i < $li_width; $i++) $padding .= '&nbsp;';
1370
+ }
1371
+ $padhtml = '<span class="fixed">'."$padding{$numstr}</span>";
1372
+ return ($padhtml);
1373
  }
1374
 
1375
+ // How many digits have an integer -- quicker to use 'strlen' function
1376
+ // function digit_count($n, $base=10) {
1377
+ // if($n == 0) return 1;
1378
+ // if($base == 10) {
1379
+ // # using the built-in log10(x)
1380
+ // # might be more accurate than log(x)/log(10).
1381
+ // return 1 + floor(log10(abs($n)));
1382
+ // }else{
1383
+ // # here logB(x) = log(x)/log(B) will have to do.
1384
+ // return 1 + floor(log(abs($n))/ log($base));
1385
+ // }
1386
+ //}
1387
+
1388
  //Round the integer to the next near 10
1389
  function roundup($value) {
1390
+ //$dg = digit_count($value);
1391
+ $numstr = (int)$value;
1392
+ $dg = strlen("$numstr");
1393
  if ($dg <= 2) {
1394
  $dg = 1;
1395
  } else {
1399
  }
1400
 
1401
  function Gchart_data($Wvisits, $pages=null, $atime=null, $type, $charttype=null, $axes=null, $chart_loc=null) {
1402
+ global $wdebug_mode;
1403
  $chartAPIdata = false;
1404
  // Port of JavaScript from http://code.google.com/apis/chart/
1405
  // http://james.cridland.net/code
1480
  } //end function
1481
 
1482
  // Used to show main visitors details query, to count items and to extract data for main chart
1483
+ class WassupItems {
1484
  // declare variables
1485
  var $tableName;
1486
  var $from_date;
1493
  var $WpUrl;
1494
 
1495
  /* Constructor */
1496
+ function wassupitems($table_name,$date_from,$date_to,$whereis=null,$limit=null) {
1497
+ global $wpdb, $wassup_options, $wdebug_mode;
1498
  if (empty($wassup_options->wassup_table)) {
1499
  $wassup_options = new wassupOptions;
1500
  }
1527
  /* Methods */
1528
  // Function to show main query and count items
1529
  function calc_tot($Type, $Search="", $specific_where_clause=null, $distinct_type=null) {
1530
+ global $wpdb, $wassup_options, $wdebug_mode;
1531
 
1532
  $this->ItemsType = $Type;
1533
  $this->searchString = $Search;
1550
  //main query
1551
  // - retrieve one row per wassup_id with timestamp = max(timestamp) (ie. latest record)
1552
  // "sql_buffer_result" select option helps in cases where it takes a long time to retrieve results. -Helene D. 2/29/09
1553
+ $qry = sprintf("SELECT SQL_BUFFER_RESULT *, max(`timestamp`) as max_timestamp, min(`timestamp`) as min_timestamp, count(wassup_id) as page_hits FROM %s WHERE `timestamp` >= %s %s %s GROUP BY wassup_id ORDER BY max_timestamp DESC %s",
1554
  $this->tableName,
1555
  $this->from_date,
1556
  $ss,
1558
  $this->Limit);
1559
  $results = $wpdb->get_results($qry);
1560
  if (empty($results) || !is_array($results)) { //try without buffer
1561
+ $qry = sprintf("SELECT *, max(`timestamp`) as max_timestamp, min(`timestamp`) as min_timestamp, count(wassup_id) as page_hits FROM %s WHERE `timestamp` >= %s %s %s GROUP BY wassup_id ORDER BY max_timestamp DESC %s",
1562
  $this->tableName,
1563
  $this->from_date,
1564
  $ss,
1582
  break;
1583
  case "main-ip": //TODO
1584
  // These are the queries to count the hits/pages/spam by ip
1585
+ $qry = sprintf("SELECT *, max(`timestamp`) as max_timestamp, min(`timestamp`) as min_timestamp, count(`ip`) as page_hits FROM %s WHERE `timestamp` >= %s %s %s GROUP BY ip ORDER BY max_timestamp DESC %s",
1586
  $this->tableName,
1587
  $this->from_date,
1588
  $ss,
1612
  // $Res = resolution
1613
  // $Search = string to add to where clause
1614
  function TheChart($Ctype, $Res, $chart_height, $Search="", $axes_type, $chart_bg, $chart_loc="page", $chart_group="") {
1615
+ global $wpdb, $wassup_options, $wdebug_mode;
1616
 
1617
  $mysqlversion=substr(mysql_get_server_info(),0,3);
1618
  $cache_table = (!empty($wassup_options->wassup_table)?$wassup_options->wassup_table."_meta":$wpdb->prefix."wassup_meta");
1635
  if (count($chart_cache)>0 && !empty($wassup_cache[0]->meta_value)) {
1636
  $chart_url = html_entity_decode($wassup_cache[0]->meta_value);
1637
  $cache_id = $wassup_cache[0]->meta_id;
1638
+ if ($wdebug_mode) {
1639
  echo "\n<!-- Cached chart found. cache_id=$cache_id -->\n";
1640
  }
1641
  }
1811
  $tlabel[] = gmdate($wp_timeformat,$x_timestamp);
1812
  }
1813
  }
1814
+ if ($wdebug_mode) {
1815
  echo "\n<!-- \$x-points= ".implode("|",$tlabel)."\n";
1816
  echo " \$tgroup=".implode("|",$tgroup)."-->";
1817
  }
1837
  $this->whereis,
1838
  $ss);
1839
  }
1840
+ if ($wdebug_mode) {
1841
  echo "\n<!-- \$query= $qry-->\n";
1842
  }
1843
  $qry_result = $wpdb->get_results($qry,ARRAY_A);
1876
  //prune overcrowded x-axis labels //TODO
1877
  //if (count($x_label) > 20 && $chart_width < 1000) {
1878
  //}
1879
+ if ($wdebug_mode) {
1880
  echo "\n<!-- \$x-group= ".implode("|",$x_group);
1881
  echo "\n \$x-labels= ".implode("|",$x_label)."-->\n";
1882
  }
1950
  return $ss;
1951
  } //end function buildSearch
1952
 
1953
+ } //end class WassupItems
1954
 
1955
  // Class to check if a previous comment with a specific IP was detected as SPAM by Akismet default plugin
1956
  class wassup_checkComment {
2052
  * @since v1.8
2053
  */
2054
  function wFetchAPIData($api_url) {
2055
+ global $wdebug_mode;
2056
 
2057
  $wassup_settings=get_option('wassup_settings');
2058
  $wassup_agent = apply_filters('http_headers_useragent',"WassUp/".$wassup_settings['wassup_version']." - www.wpwp.org");
2092
  }
2093
  $api_method='file_get_contents'; //debug
2094
  }
2095
+ if ($wdebug_mode) {
2096
  echo "\n<!-- <br>API Fetch using $api_method data: "; //debug
2097
  print_r($apidata);
2098
  echo "-->\n";
lib/settings.php CHANGED
@@ -8,7 +8,7 @@
8
  * and perform some maintenance operations.
9
  */
10
  function wassup_optionsView() {
11
- global $wpdb, $wp_version, $user_level, $wassupversion, $wassup_options, $debug_mode;
12
 
13
  $GMapsAPI="http://code.google.com/intl/en/apis/maps";
14
 
@@ -19,6 +19,7 @@ function wassup_optionsView() {
19
  $alert_msg = "";
20
  $alertstyle = 'color:red; background-color:#ffd;';
21
  $wassup_table = (!empty($wassup_options->wassup_table))? $wassup_options->wassup_table: $wpdb->prefix . "wassup";
 
22
  $table_engine = "";
23
  $table_collation = "";
24
 
@@ -76,18 +77,21 @@ function wassup_optionsView() {
76
  <select name='wassup_screen_res' style="width:90px;">
77
  <?php $wassup_options->showFormOptions("wassup_screen_res"); ?>
78
  </select>
79
- </p>
80
- <h3><?php _e('Set minimum users level which can view and manage WassUp plugin (default Administrators)','wassup'); ?></h3>
81
- <p><select name="wassup_userlevel">
 
82
  <?php $wassup_options->showFormOptions("wassup_userlevel"); ?>
83
- </select></p>
 
 
84
 
85
  <h3><?php _e('Dashboard Settings','wassup'); ?></h3>
86
  <p><input type="checkbox" name="wassup_dashboard_chart" value="1" <?php if($wassup_options->wassup_dashboard_chart == 1) print "CHECKED"; ?> /> <strong><?php _e('Display small chart in the dashboard','wassup'); ?></strong>
87
- </p>
88
 
89
- <h3><?php _e('GEO IP Map (Spy view)','wassup'); ?></h3>
90
- <p><input type="checkbox" name="wassup_geoip_map" value="1" <?php
91
  //if (!function_exists('curl_init')) { print "DISABLED"; }
92
  if ($wassup_options->wassup_geoip_map == 1) print "CHECKED"; ?> />
93
  <strong><?php _e('Display a GEO IP Map in the spy visitors view','wassup'); ?></strong></p><?php
@@ -104,54 +108,66 @@ function wassup_optionsView() {
104
  echo "$code_error\n";
105
  }
106
  } ?>
107
- <p><strong>Google Maps API <?php _e("key","wassup"); ?>:</strong> <input type="text" name="wassup_googlemaps_key" size="40" value="<?php print $wassup_options->wassup_googlemaps_key; ?>" /> - <a href="<?php echo $GMapsAPI.'/signup.html?url='.get_bloginfo('wpurl'); ?>"><?php _e("signup for your key","wassup"); ?></a></p></br /> <?php
108
  //no curl - now works without cUrl using 'wp_remote_get'
109
  //} else {
110
  //echo '<p class="small">'.__("Geo IP Map requires","wassup")." PHP <strong>Curl</strong>. ".__("Please install it to be able to activate this feature","wassup").".</p>";
111
- //} ?><br/>
 
 
 
 
 
112
 
113
  <h3><?php _e('Visitor Detail Settings','wassup'); ?></h3>
114
- <p><strong><?php _e('Time format 12/24 Hour','wassup'); ?></strong>:
115
  &nbsp; 12h <input type="radio" name="wassup_time_format" value="12" <?php if($wassup_options->wassup_time_format == 12) print "CHECKED"; ?> />
116
  &nbsp; &nbsp; 24h <input type="radio" name="wassup_time_format" value="24" <?php if($wassup_options->wassup_time_format == 24) print "CHECKED"; ?> />
117
  </p>
118
-
119
- <p><strong><?php _e('Show chart type - How many axes','wassup'); ?></strong>:
120
- <select name='wassup_chart_type'><?php
121
- $wassup_options->showFormOptions("wassup_chart_type");
122
- ?></select>
123
  </p>
124
-
125
- <p><strong><?php echo __('Set how many minutes wait for automatic page refresh','wassup'); ?></strong>:
126
  <input type="text" name="wassup_refresh" size="2" value="<?php print $wassup_options->wassup_refresh; ?>" /> <?php _e('minutes (default 3)','wassup'); ?>
127
  </p>
128
-
129
- <p><strong><?php _e('Show visitor details for the last','wassup');
130
- ?></strong>: <select name='wassup_time_period'> <?php
131
- $wassup_options->showFormOptions("wassup_time_period");
132
- ?></select>
133
  </p>
134
- <p><strong><?php _e('Filter visitor details for','wassup');
135
- ?></strong>: <select name='wassup_default_type'> <?php
136
- $wassup_options->showFormOptions("wassup_default_type");
137
- ?></select>
138
  </p>
139
-
140
- <p><strong><?php _e('Number of items per page','wassup'); ?></strong>:
141
  <select name='wassup_default_limit'>
142
  <?php $wassup_options->showFormOptions("wassup_default_limit"); ?>
143
  </select>
144
  </p><br />
145
- <?php
146
- //TODO: Make Top 10 Customizable with up to 10 choices
 
 
 
 
 
147
  $top_ten = unserialize(html_entity_decode($wassup_options->wassup_top10));
148
- ?>
149
- <h3><?php _e('Customize Top Ten List','wassup'); ?></h3>
150
- <p style="margin-top:5px;"> <strong> <?php _e("Choose one or more items for your Top Ten list", "wassup"); ?></strong> (<?php _e("over 5 selections may cause horizontal scrolling","wassup"); ?>):<br />
 
 
 
 
 
 
151
  <div style="padding-left:25px;padding-top:0;margin-top:0;display:block;clear:left;">
152
  <div style="display:block; vertical-align:top; float:left; width:225px;">
153
  <input type="checkbox" name="topsearch" value="1" <?php if($top_ten['topsearch'] == 1) print "CHECKED"; ?> /><?php _e("Top Searches", "wassup"); ?><br />
154
- <input type="checkbox" name="topreferrer" value="1" <?php if($top_ten['topreferrer'] == 1) print "CHECKED"; ?> /><?php _e("Top Referrers", "wassup"); ?><br />
155
  <input type="checkbox" name="toprequest" value="1" <?php if($top_ten['toprequest'] == 1) print "CHECKED"; ?> /><?php _e("Top Requests", "wassup"); ?><br />
156
  </div>
157
  <div style="display:block; vertical-align:top; float:left; width:225px;">
@@ -160,21 +176,25 @@ function wassup_optionsView() {
160
  <input type="checkbox" name="toplocale" value="1" <?php if($top_ten['toplocale'] == 1) print "CHECKED"; ?> /><?php _e("Top Locales", "wassup"); ?></span><br />
161
  </div>
162
  <div style="vertical-align:top; float:left; width:225px;">
163
- <input type="checkbox" name="topvisitor" value="1" <?php if($top_ten['topvisitor'] == 1) print "CHECKED"; ?> /><?php _e("Top Visitors", "wassup"); ?><br /><!--
 
164
  //TODO
165
  <input type="checkbox" name="topfeed" value="1" DISABLED /><?php _e("Top Feeds", "wassup"); ?><br />
166
  <input type="checkbox" name="topcrawler" value="1" DISABLED /><?php _e("Top Crawlers", "wassup"); ?> --><br />
167
  </div>
168
  </div>
169
- </p>
170
- <p style="margin-top:10px; clear:left;"> <strong><?php _e("Websites/domains to exclude from top referrers", "wassup"); ?></strong> :<br />
171
  <span style="padding-left:10px;display:block;clear:left;">
172
  <textarea name="topreferrer_exclude" rows="2" style="width:66%;"><?php echo $top_ten['topreferrer_exclude']; ?></textarea><br />
173
- <?php echo __("Comma separated value","wassup")."(ex: mydomain2.net, mydomain2.info). ". __("List whole domains only. Wildcards and partial domains will NOT be excluded.","wassup"). " ";
174
  _e("Don't list your website domain defined in WordPress","wassup"); ?>.</span>
175
  </p>
 
 
 
176
  <br /><br />
177
- <p style="clear:both;padding-left:0;padding-top:15px;"><input type="submit" name="submit-options" class="submit-opt wassup-button" value="<?php _e('Save Settings','wassup'); ?>" />&nbsp;<input type="reset" name="reset" class="reset-opt wassup-button" value="<?php _e('Reset','wassup'); ?>" /> - <input type="submit" name="reset-to-default" class="default-opt wassup-button" value="<?php _e("Reset to Default", "wassup"); ?>" /></p><br />
178
  </div>
179
 
180
  <div id="wassup_opt_frag-2" class="optionstab<?php if ($tab == "2") echo ' tabselected'; ?>">
@@ -205,45 +225,26 @@ function wassup_optionsView() {
205
  <br /><p><strong><?php echo __("Users","wassup")."\n<br /> &nbsp; ".__('Enter usernames to exclude from recording','wassup'); ?></strong>:
206
  <br /><span style="padding-left:10px;display:block;clear:left;">
207
  <textarea name="wassup_exclude_user" rows="2" style="width:60%;"><?php print $wassup_options->wassup_exclude_user; ?></textarea></span> &nbsp; <?php _e("comma separated value, enter a registered user's login name (ex: bobmarley, enyabrennan, etc.)", "wassup") ?></p>
208
- <br /><p><strong><?php echo __("Posts/pages","wassup")."\n<br /> &nbsp; ".__('enter requested URLs to exclude from recording','wassup'); ?></strong>:
209
  <br /><span style="padding-left:10px;display:block;clear:left;">
210
  <textarea name="wassup_exclude_url" rows="2" style="width:60%;"><?php print $wassup_options->wassup_exclude_url; ?></textarea></span> &nbsp; <?php _e("comma separated value, don't enter entire url, only the last path or some word to exclude (ex: /category/wordpress, 2007, etc...)", "wassup") ?></p>
211
- <p style="clear:both;padding-left:0;padding-top:15px;"><input type="submit" name="submit-options2" class="submit-opt wassup-button" value="<?php _e('Save Settings','wassup'); ?>" />&nbsp;<input type="reset" name="reset" class="reset-opt wassup-button" value="<?php _e('Reset','wassup'); ?>" /> - <input type="submit" name="reset-to-default" class="default-opt wassup-button" value="<?php _e("Reset to Default", "wassup"); ?>" /></p><br />
212
  </div>
213
 
214
  <div id="wassup_opt_frag-3" class="optionstab<?php if ($tab == "3") echo ' tabselected'; ?>">
215
- <?php /*
216
- // <h3>&lt;?php _e('Temporary files location folder','wassup'); ?&rt;</h3>
217
- // <p>&lt;?php echo '<strong>'.__('Current "Save path" directory for storing temporary files used to track visitor activity','wassup').'</strong>:<br />';
218
- // $sessionpath = $wassup_options->wassup_savepath;
219
- // if (empty($sessionpath)) {
220
- // $sessionpath = getSessionpath();
221
- // }
222
- // //$sessionpath = "/fakefolder/temp"; //#debug
223
- // $sessionstyle = '';
224
- // //# check that session_save_path exists and is writable...
225
- // if ($sessionpath == "" || $wassup_options->isWritableFolder($sessionpath) == false) {
226
- // $sessionwarn = '<span style="font-size:95%; padding-left:5px;'.$alertstyle.'"><span style="text-decoration:blink;">'.__('WARNING','wassup').'!</span> '.__('Directory does not exist or is not writable. Please enter a different path above or change "session.save_path" in "php.ini" to point to a valid, writable folder','wassup').'.</span>';
227
- // $sessionstyle = $alertstyle;
228
- // } else {
229
- // $sessionwarn ='<span style="font-size:95%; color:#555; padding-left:5px;">'.__('Note: To adjust, modify the directory shown in the box above or edit "sessions.save_path" in','wassup').' <i>php.ini</i>.</span>';
230
- // }
231
- // <textarea name="wassup_savepath" rows="1" style="width:550px;padding-left:25px;clear:left;&lt;?php echo $sessionstyle; ?&rt;">&lt;?php echo $sessionpath; ?&rt;</textarea>
232
- // <br />&nbsp;&nbsp;&lt;?php echo __('Use absolute directory paths only. This value is usually','wassup').' "/tmp".'."\n"; ?&rt;
233
- // <br />&nbsp; <span style="font-size:95%; color:#555;">System default for session.save_path="&lt;?php echo session_save_path(); //debug ?&rt;" from <i>php.ini</i> or from web server configuration.</span>
234
- // <br />&nbsp;&lt;?php echo $sessionwarn."\n"; ?&rt;
235
  // </p><br />
236
- */ ?>
237
- <?php //TODO ?>
238
- <!--
239
- <br /><h3><?php _e('Rescan Old Records','wassup'); ?></h3>
240
- <p><?php _e("Statistical records collected by earlier versions of WassUp may not have the latest spider, search engine, and spam data properly identified. Click the \"Rescan\" button to retroactively scan and update old records","wassup"); ?>.
241
- <br /><input type="button" name="rescan" value="<?php _e('Rescan Old Records','wassup'); ?>" />
242
- </p><br />
243
- -->
244
  <h3><?php _e('Select actions for table growth','wassup'); ?></h3>
245
  <p><?php _e("WassUp table grows very fast, especially if your site is frequently visited. I recommend you delete old records sometimes.","wassup");
246
- echo " ".__("You can select an option below to delete all Wassup records (empty table); or you can delete selected old records on either an automatic schedule (daily), or as manual task now (once). If you haven't database space problems, you can leave the table as is.","wassup"); ?></p>
 
247
  <p><?php _e('Current WassUp table usage is','wassup'); ?>:
248
  <strong><?php
249
  $tusage = number_format(($data_lenght/1024/1024), 2, ",", " ");
@@ -278,7 +279,12 @@ function wassup_optionsView() {
278
  <input type="button" name="delete_now" class="submit-opt wassup-hot-button" value="<?php _e('Delete NOW','wassup'); ?>" onclick="submit();" />
279
  </p><br/>
280
  <h3><?php _e('Cache storage option','wassup'); ?></h3>
281
- <p><input type="checkbox" name="wassup_cache" value="1" <?php if($wassup_options->wassup_cache == 1 ) print "CHECKED"; ?> /> <strong><?php echo __('Enable cache for storing some remote API services data locally in WassUp table','wassup'); ?></strong></p>
 
 
 
 
 
282
  <p style="color:#555; margin-top:0; padding-top:0;"><?php _e('Reduces the number of requests to remote API servers and may improve WassUp admin page load.','wassup'); ?></p><br/>
283
 
284
  <h3><?php _e("Server Settings and Memory Resources","wassup"); ?></h3>
@@ -484,7 +490,7 @@ function wassup_optionsView() {
484
  $sql_engine = $var->Value;
485
  }
486
  }
487
- if ($debug_mode) {
488
  print_r($sql_vars); //debug
489
  }
490
  } ?>
@@ -578,7 +584,7 @@ function wassup_optionsView() {
578
  ?></li>
579
  </ul></p>
580
  <br /><br />
581
- <p style="clear:both;padding-left:0;padding-top:15px;"><input type="submit" name="submit-options3" class="submit-opt wassup-button" value="<?php _e('Save Settings','wassup'); ?>" />&nbsp;<input type="reset" name="reset" class="reset-opt wassup-button" value="<?php _e('Reset','wassup'); ?>" /> - <input type="submit" name="reset-to-default" class="default-opt wassup-button" value="<?php _e("Reset to Default", "wassup"); ?>" /></p><br />
582
  </div>
583
 
584
  <div id="wassup_opt_frag-4" class="optionstab<?php if ($tab == "4") echo ' tabselected'; ?>">
@@ -595,7 +601,7 @@ function wassup_optionsView() {
595
 
596
  <br /><p><?php _e("To help improve this plugin, we would appreciate your feedback at","wassup"); ?> <a href="http://www.wpwp.org">www.wpwp.org</a>.</p>
597
  <br /><br />
598
- <p style="clear:both;padding-left:0;padding-top:15px;"><input type="submit" name="submit-options4" class="submit-opt wassup-button" value="<?php _e('Save Settings','wassup'); ?>" />&nbsp;<input type="reset" name="reset" value="<?php _e('Reset','wassup'); ?>" class="reset-opt wassup-button" /> - <input type="submit" name="reset-to-default" class="default-opt wassup-button" value="<?php _e("Reset to Default", "wassup"); ?>" /></p><br />
599
  </div>
600
  </form>
601
  </div> <!-- /#tabcontainer -->
8
  * and perform some maintenance operations.
9
  */
10
  function wassup_optionsView() {
11
+ global $wpdb, $wp_version, $user_level, $wassupversion, $wassup_options, $wdebug_mode;
12
 
13
  $GMapsAPI="http://code.google.com/intl/en/apis/maps";
14
 
19
  $alert_msg = "";
20
  $alertstyle = 'color:red; background-color:#ffd;';
21
  $wassup_table = (!empty($wassup_options->wassup_table))? $wassup_options->wassup_table: $wpdb->prefix . "wassup";
22
+ $wassup_meta_table = $wassup_table . "_meta";
23
  $table_engine = "";
24
  $table_collation = "";
25
 
77
  <select name='wassup_screen_res' style="width:90px;">
78
  <?php $wassup_options->showFormOptions("wassup_screen_res"); ?>
79
  </select>
80
+ </p><br/>
81
+ <h3><?php _e('User Permissions'); ?></h3>
82
+ <p><strong><?php _e('Set minimum users level which can view and manage WassUp plugin','wassup'); ?></strong>:
83
+ <select name="wassup_userlevel">
84
  <?php $wassup_options->showFormOptions("wassup_userlevel"); ?>
85
+ </select>
86
+ <?php echo "(".__('default Administrator','wassup').")"; ?>
87
+ </p><br/>
88
 
89
  <h3><?php _e('Dashboard Settings','wassup'); ?></h3>
90
  <p><input type="checkbox" name="wassup_dashboard_chart" value="1" <?php if($wassup_options->wassup_dashboard_chart == 1) print "CHECKED"; ?> /> <strong><?php _e('Display small chart in the dashboard','wassup'); ?></strong>
91
+ </p><br/>
92
 
93
+ <h3><?php _e('Spy Visitors Settings','wassup'); ?></h3>
94
+ <p> <input type="checkbox" name="wassup_geoip_map" value="1" <?php
95
  //if (!function_exists('curl_init')) { print "DISABLED"; }
96
  if ($wassup_options->wassup_geoip_map == 1) print "CHECKED"; ?> />
97
  <strong><?php _e('Display a GEO IP Map in the spy visitors view','wassup'); ?></strong></p><?php
108
  echo "$code_error\n";
109
  }
110
  } ?>
111
+ <p> <strong>Google Maps API <?php _e("key","wassup"); ?>:</strong> <input type="text" name="wassup_googlemaps_key" size="40" value="<?php print $wassup_options->wassup_googlemaps_key; ?>" /> - <a href="<?php echo $GMapsAPI.'/signup.html?url='.get_bloginfo('wpurl'); ?>"><?php _e("signup for your key","wassup"); ?></a></p> <?php
112
  //no curl - now works without cUrl using 'wp_remote_get'
113
  //} else {
114
  //echo '<p class="small">'.__("Geo IP Map requires","wassup")." PHP <strong>Curl</strong>. ".__("Please install it to be able to activate this feature","wassup").".</p>";
115
+ //} ?>
116
+ <p> <strong><?php echo _e('Set update speed of Spy data in microseconds','wassup'); ?></strong> :
117
+ <input type="text" name="wassup_spy_speed" size="5" value="<?php if (empty($wassup_options->wassup_spy_speed)) echo "5000"; else echo $wassup_options->wassup_spy_speed; ?>" />
118
+ <?php echo "<nobr>(".__('default 5000, minimum 1000','wassup').")</nobr>"; ?><br/>
119
+ <?php echo __('Decrease if some visitor records are missing from Spy view. Increase if multiple duplicate records are shown.','wassup'); ?>
120
+ </p><br/>
121
 
122
  <h3><?php _e('Visitor Detail Settings','wassup'); ?></h3>
123
+ <p> <strong><?php _e('Time format 12/24 Hour','wassup'); ?></strong>:
124
  &nbsp; 12h <input type="radio" name="wassup_time_format" value="12" <?php if($wassup_options->wassup_time_format == 12) print "CHECKED"; ?> />
125
  &nbsp; &nbsp; 24h <input type="radio" name="wassup_time_format" value="24" <?php if($wassup_options->wassup_time_format == 24) print "CHECKED"; ?> />
126
  </p>
127
+ <p> <strong><?php _e('Show chart type - How many axes','wassup'); ?></strong>:
128
+ <select name='wassup_chart_type'>
129
+ <?php $wassup_options->showFormOptions("wassup_chart_type"); ?>
130
+ </select>
 
131
  </p>
132
+ <p> <strong><?php echo __('Set how many minutes wait for automatic page refresh','wassup'); ?></strong>:
 
133
  <input type="text" name="wassup_refresh" size="2" value="<?php print $wassup_options->wassup_refresh; ?>" /> <?php _e('minutes (default 3)','wassup'); ?>
134
  </p>
135
+ <p> <strong><?php _e('Show visitor details for the last','wassup'); ?></strong>:
136
+ <select name='wassup_time_period'>
137
+ <?php $wassup_options->showFormOptions("wassup_time_period"); ?>
138
+ </select>
 
139
  </p>
140
+ <p> <strong><?php _e('Filter visitor details for','wassup'); ?></strong>:
141
+ <select name='wassup_default_type'>
142
+ <?php $wassup_options->showFormOptions("wassup_default_type"); ?>
143
+ </select>
144
  </p>
145
+ <p> <strong><?php _e('Number of items per page','wassup'); ?></strong>:
 
146
  <select name='wassup_default_limit'>
147
  <?php $wassup_options->showFormOptions("wassup_default_limit"); ?>
148
  </select>
149
  </p><br />
150
+
151
+ <h3><?php _e('Customize Top Stats Lists','wassup'); ?></h3><?php
152
+ //New in 1.8.3:
153
+ // 1) toplimit option to customize top stats list size
154
+ // 2) toppostid option to list top post-ID items (articles)
155
+ // 3) top_nospider option to exclude spider visits from all
156
+ // top stats lists
157
  $top_ten = unserialize(html_entity_decode($wassup_options->wassup_top10));
158
+ if (!is_array($top_ten)) { //in case corrupted
159
+ $top_ten = $wassup_options->defaultSettings("top10");
160
+ }
161
+ if (empty($top_ten["toplimit"])) $top_ten["toplimit"] = 10;
162
+ echo "\n"; ?>
163
+ <p> <strong> <?php _e("Set the list length size for Top Stats", "wassup"); ?></strong>:
164
+ <input type="text" name="toplimit" size="2" value="<?php echo (int)$top_ten['toplimit']; ?>" /> (<?php _e("default 10","wassup"); ?>)
165
+ </p>
166
+ <p style="margin-top:5px;"> <strong> <?php _e("Choose one or more items to list in Top Stats", "wassup"); ?></strong> (<?php _e("over 5 selections may cause horizontal scrolling","wassup"); ?>):<br />
167
  <div style="padding-left:25px;padding-top:0;margin-top:0;display:block;clear:left;">
168
  <div style="display:block; vertical-align:top; float:left; width:225px;">
169
  <input type="checkbox" name="topsearch" value="1" <?php if($top_ten['topsearch'] == 1) print "CHECKED"; ?> /><?php _e("Top Searches", "wassup"); ?><br />
170
+ <input type="checkbox" name="topreferrer" value="1" <?php if($top_ten['topreferrer'] == 1) print "CHECKED"; ?> /><?php _e("Top Referrers", "wassup"); ?>*<br />
171
  <input type="checkbox" name="toprequest" value="1" <?php if($top_ten['toprequest'] == 1) print "CHECKED"; ?> /><?php _e("Top Requests", "wassup"); ?><br />
172
  </div>
173
  <div style="display:block; vertical-align:top; float:left; width:225px;">
176
  <input type="checkbox" name="toplocale" value="1" <?php if($top_ten['toplocale'] == 1) print "CHECKED"; ?> /><?php _e("Top Locales", "wassup"); ?></span><br />
177
  </div>
178
  <div style="vertical-align:top; float:left; width:225px;">
179
+ <input type="checkbox" name="topvisitor" value="1" <?php if(!empty($top_ten['topvisitor'])) print "CHECKED"; ?> /><?php _e("Top Visitors", "wassup"); ?><br />
180
+ <input type="checkbox" name="toppostid" value="1" <?php if(!empty($top_ten['toppostid'])) print "CHECKED"; ?> /><?php _e("Top Articles", "wassup"); ?></span><br /><!--
181
  //TODO
182
  <input type="checkbox" name="topfeed" value="1" DISABLED /><?php _e("Top Feeds", "wassup"); ?><br />
183
  <input type="checkbox" name="topcrawler" value="1" DISABLED /><?php _e("Top Crawlers", "wassup"); ?> --><br />
184
  </div>
185
  </div>
186
+ </p><p style="clear:left;"></p>
187
+ <p style="margin-top:5px;"> *<strong><?php _e("Exclude the following website domains from Top Referrers", "wassup"); ?></strong> :<br />
188
  <span style="padding-left:10px;display:block;clear:left;">
189
  <textarea name="topreferrer_exclude" rows="2" style="width:66%;"><?php echo $top_ten['topreferrer_exclude']; ?></textarea><br />
190
+ <?php echo __("Comma separated value","wassup")." (ex: mydomain2.net, mydomain2.info). ". __("List whole domains only. Wildcards and partial domains will be ignored.","wassup"). " ";
191
  _e("Don't list your website domain defined in WordPress","wassup"); ?>.</span>
192
  </p>
193
+ <p> <input type="checkbox" name="top_nospider" value="1" <?php if($top_ten['top_nospider'] == 1) print "CHECKED"; ?> />
194
+ <strong> <?php _e("Exclude all spider records from Top Stats", "wassup"); ?></strong>
195
+ </p>
196
  <br /><br />
197
+ <p style="clear:both;padding-left:0;padding-top:15px;"><input type="submit" name="submit-options" class="submit-opt wassup-button button-primary" value="<?php _e('Save Settings','wassup'); ?>" />&nbsp;<input type="reset" name="reset" class="reset-opt wassup-button" value="<?php _e('Reset','wassup'); ?>" /> - <input type="submit" name="reset-to-default" class="default-opt wassup-button" value="<?php _e("Reset to Default", "wassup"); ?>" /></p><br />
198
  </div>
199
 
200
  <div id="wassup_opt_frag-2" class="optionstab<?php if ($tab == "2") echo ' tabselected'; ?>">
225
  <br /><p><strong><?php echo __("Users","wassup")."\n<br /> &nbsp; ".__('Enter usernames to exclude from recording','wassup'); ?></strong>:
226
  <br /><span style="padding-left:10px;display:block;clear:left;">
227
  <textarea name="wassup_exclude_user" rows="2" style="width:60%;"><?php print $wassup_options->wassup_exclude_user; ?></textarea></span> &nbsp; <?php _e("comma separated value, enter a registered user's login name (ex: bobmarley, enyabrennan, etc.)", "wassup") ?></p>
228
+ <br /><p><strong><?php echo __("Posts/pages","wassup")."\n<br /> &nbsp; ".__('Enter requested URLs to exclude from recording','wassup'); ?></strong>:
229
  <br /><span style="padding-left:10px;display:block;clear:left;">
230
  <textarea name="wassup_exclude_url" rows="2" style="width:60%;"><?php print $wassup_options->wassup_exclude_url; ?></textarea></span> &nbsp; <?php _e("comma separated value, don't enter entire url, only the last path or some word to exclude (ex: /category/wordpress, 2007, etc...)", "wassup") ?></p>
231
+ <p style="clear:both;padding-left:0;padding-top:15px;"><input type="submit" name="submit-options2" class="submit-opt wassup-button button-primary" value="<?php _e('Save Settings','wassup'); ?>" />&nbsp;<input type="reset" name="reset" class="reset-opt wassup-button" value="<?php _e('Reset','wassup'); ?>" /> - <input type="submit" name="reset-to-default" class="default-opt wassup-button" value="<?php _e("Reset to Default", "wassup"); ?>" /></p><br />
232
  </div>
233
 
234
  <div id="wassup_opt_frag-3" class="optionstab<?php if ($tab == "3") echo ' tabselected'; ?>">
235
+ <?php /*
236
+ //TODO ?
237
+ //<!--
238
+ //<br /><h3><?php _e('Rescan Old Records','wassup'); ?></h3>
239
+ // <p><?php _e("Statistical records collected by earlier versions of WassUp may not have the latest spider, search engine, and spam data properly identified. Click the \"Rescan\" button to retroactively scan and update old records","wassup"); ?>.
240
+ // <br /><input type="button" name="rescan" value="<?php _e('Rescan Old Records','wassup'); ?>" />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
  // </p><br />
242
+ // -->
243
+ */ ?>
 
 
 
 
 
 
244
  <h3><?php _e('Select actions for table growth','wassup'); ?></h3>
245
  <p><?php _e("WassUp table grows very fast, especially if your site is frequently visited. I recommend you delete old records sometimes.","wassup");
246
+ echo "<br/>".__('You can delete all Wassup records now (Empty Table), you can set an automatic delete option to delete selected old records daily, and you can manually delete selected old records once (Delete NOW).','wassup');
247
+ echo " ".__("If you haven't database space problems, you can leave the table as is.","wassup"); ?></p>
248
  <p><?php _e('Current WassUp table usage is','wassup'); ?>:
249
  <strong><?php
250
  $tusage = number_format(($data_lenght/1024/1024), 2, ",", " ");
279
  <input type="button" name="delete_now" class="submit-opt wassup-hot-button" value="<?php _e('Delete NOW','wassup'); ?>" onclick="submit();" />
280
  </p><br/>
281
  <h3><?php _e('Cache storage option','wassup'); ?></h3>
282
+ <p><input type="checkbox" name="wassup_cache" value="1" <?php
283
+ if ($wpdb->get_var("SHOW TABLES LIKE '$wassup_meta_table'") != $wassup_meta_table) {
284
+ echo "DISABLED"; //meta table required for cache
285
+ } elseif ($wassup_options->wassup_cache == 1 ) {
286
+ echo "CHECKED";
287
+ } ?> /> <strong><?php echo __('Enable cache for storing some remote API data locally in WassUp table','wassup'); ?></strong></p>
288
  <p style="color:#555; margin-top:0; padding-top:0;"><?php _e('Reduces the number of requests to remote API servers and may improve WassUp admin page load.','wassup'); ?></p><br/>
289
 
290
  <h3><?php _e("Server Settings and Memory Resources","wassup"); ?></h3>
490
  $sql_engine = $var->Value;
491
  }
492
  }
493
+ if ($wdebug_mode) {
494
  print_r($sql_vars); //debug
495
  }
496
  } ?>
584
  ?></li>
585
  </ul></p>
586
  <br /><br />
587
+ <p style="clear:both;padding-left:0;padding-top:15px;"><input type="submit" name="submit-options3" class="submit-opt wassup-button button-primary" value="<?php _e('Save Settings','wassup'); ?>" />&nbsp;<input type="reset" name="reset" class="reset-opt wassup-button" value="<?php _e('Reset','wassup'); ?>" /> - <input type="submit" name="reset-to-default" class="default-opt wassup-button" value="<?php _e("Reset to Default", "wassup"); ?>" /></p><br />
588
  </div>
589
 
590
  <div id="wassup_opt_frag-4" class="optionstab<?php if ($tab == "4") echo ' tabselected'; ?>">
601
 
602
  <br /><p><?php _e("To help improve this plugin, we would appreciate your feedback at","wassup"); ?> <a href="http://www.wpwp.org">www.wpwp.org</a>.</p>
603
  <br /><br />
604
+ <p style="clear:both;padding-left:0;padding-top:15px;"><input type="submit" name="submit-options4" class="submit-opt wassup-button button-primary" value="<?php _e('Save Settings','wassup'); ?>" />&nbsp;<input type="reset" name="reset" value="<?php _e('Reset','wassup'); ?>" class="reset-opt wassup-button" /> - <input type="submit" name="reset-to-default" class="default-opt wassup-button" value="<?php _e("Reset to Default", "wassup"); ?>" /></p><br />
605
  </div>
606
  </form>
607
  </div> <!-- /#tabcontainer -->
lib/uadetector.class.php CHANGED
@@ -1,13 +1,13 @@
1
  <?php
2
  /**
3
  * UADetector.class.php
4
- * Description: a PHP class for browser and spider identification
5
- * Updated: 2010-09-02
6
- * @version 0.9a3
7
- * @author Helene D. <techfromhel@gmail.com>
8
- * Author URI: http://www.techfromhel.com/
9
  *
10
- * @copyright Copyright (c) 2009,2010 Helene Duncker
11
  * @license http://www.gnu.org/licenses/gpl.txt GNU General Public License
12
  */
13
  /**
@@ -15,24 +15,25 @@
15
  * $useragent = new UADetector(); //returns object(16)
16
  *
17
  * Note: UADetector attempts to find the actual browser in use. This may
18
- * cause the browser "name" to differ from browser "emulation" field
19
- * when user-agent "spoofing" is detected. This means that:
20
- * a) "Name" field is best used for information and statistics only.
21
- * b) "Emulation" field is best used to format web page by browser type.
 
22
  *
23
  * Disclaimer: Use at your own risk. No warranty expressed or implied is provided.
24
  */
25
  class UADetector {
26
- var $name = ''; //name of browser or spider, not null
27
- var $version = ''; //version of browser|spider, if available
28
  var $os = ''; //operating system+version, if available
29
- var $platform = ''; //operating system|device platform
30
  var $emulation = ''; //emulated browser plus major version#
31
- var $language = ''; //language code, if available
32
- var $device = ''; //PC, PDA, Phone, TV, if known
33
- var $model = ''; //Manufacturer model, if known
34
  var $resolution = ''; //screen size (MMMxNNN), if in user-agent
35
- var $subscribers = ''; //feed subscribers, if in user-agent
36
  var $is_mobile = false;
37
  var $is_browser = false;
38
  var $is_robot = false;
@@ -63,12 +64,12 @@ class UADetector {
63
  * @constructor
64
  * @access public
65
  * @param string $ua (optional)
66
- * @return object(12)
67
  */
68
  function __construct($ua="") {
69
- global $debug_mode, $do_profile;
70
  $do_profile= false;
71
- if ($debug_mode && function_exists('profiler_beginSection')) {
72
  $do_profile = true;
73
  profiler_beginSection('(Subtot)uaDetector');
74
  }
@@ -138,7 +139,7 @@ class UADetector {
138
  //NOTE: Top agents are based on recent log data from
139
  // "WassUp", a web statistics plugin for WordPress 2.2+
140
  // available at http://www.wpwp.org
141
- global $debug_mode, $do_profile;
142
 
143
  // User agent parameter or class variable is required.
144
  $ua="";
@@ -173,7 +174,7 @@ class UADetector {
173
  if (!empty($match[3])) {
174
  $top_ua['device'] = $match[3];
175
  }
176
- // #3 Firefox or other Mozilla browsers on Windows
177
  } elseif (preg_match('#^Mozilla/\d\.\d\s\(Windows;\sU;\s(.+);\s([a-z]{2}(?:\-[A-Za-z]{2})?);\srv\:\d(?:\.\d+)+\)\sGecko/\d+\s([A-Za-z\-0-9]+)/(\d+(?:\.\d+)+)(?:\s\(.*\))?$#',$ua,$match)>0) {
178
  $top_ua['name'] = $match[3];
179
  $top_ua['version'] = $match[4];
@@ -192,9 +193,9 @@ class UADetector {
192
  $top_ua['language']=$match[2];
193
  }
194
  $top_ua['agenttype']= 'R';
195
- // #5 MSNBot, MSNbot-media
196
- } elseif (preg_match('#^(?:msnbot(\-media)?)/(\d\.\d)[^a-z0-9]+http\://search\.msn\.com/msnbot\.htm.$#',$ua,$match)>0) {
197
- $top_ua['name'] = 'MSNBot';
198
  if (!empty($match[1])) {
199
  $top_ua['name'].=$match[1];
200
  }
@@ -202,17 +203,12 @@ class UADetector {
202
  $top_ua['version']=$match[2];
203
  }
204
  $top_ua['agenttype']= 'R';
205
- // #6 Twiceler
206
- } elseif (preg_match('#^Mozilla/\d\.\d\s\(Twiceler\-(\d\.\d)\shttp://www\.cuill?\.com/twiceler/robot\.html\)$#',$ua,$match)>0) {
207
- $top_ua['name'] = 'Twiceler';
208
- $top_ua['version']=$match[1];
209
- $top_ua['agenttype']= 'R';
210
- // #7 FeedBurner
211
  } elseif (preg_match('#^FeedBurner/(\d\.\d)\s\(http\://www\.FeedBurner\.com\)$#',$ua,$match)>0) {
212
  $top_ua['name'] = 'FeedBurner';
213
  $top_ua['version']=$match[1];
214
  $top_ua['agenttype']= 'F';
215
- // #8 Wordpress
216
  } elseif (preg_match('#^WordPress/(?:wordpress(\-mu)\-)?(\d\.\d+)(?:\.\d+)*(?:\-[a-z]+)?(?:\;\shttp\://[a-z0-9_\.\:\/]+)?$#',$ua,$match)>0) {
217
  $top_ua['name'] = 'Wordpress';
218
  if (!empty($match[1])) {
@@ -220,7 +216,7 @@ class UADetector {
220
  }
221
  $top_ua['version']=$match[2];
222
  $top_ua['agenttype']= 'U';
223
- // #9 Firefox and Gecko browsers on Mac|*nix|OS/2 etc...
224
  } elseif (preg_match('#^Mozilla/\d\.\d\s\((Macintosh|X11|OS/2);\sU;\s(.+);\s([a-z]{2}(?:\-[A-Za-z]{2})?)(?:-mac)?;\srv\:\d(?:.\d+)+\)\sGecko/\d+\s([A-Za-z\-0-9]+)/(\d+(?:\.[0-9a-z\-\.]+))+(?:(\s\(.*\))(?:\s([A-Za-z\-0-9]+)/(\d+(?:\.\d+)+)))?$#',$ua,$match)>0) {
225
  $top_ua['name'] = $match[4];
226
  $top_ua['version'] = $match[5];
@@ -236,7 +232,7 @@ class UADetector {
236
  }
237
  list($top_ua['os']) = $this->OSversion($os,$top_ua['platform'],$ua);
238
  $top_ua['agenttype']= 'B';
239
- // #10 Safari and Webkit-based browsers on all platforms
240
  } elseif (preg_match('#^Mozilla/\d\.\d\s\(([A-Za-z0-9/\.]+);\sU;?\s?(.*);\s?([a-z]{2}(?:\-[A-Za-z]{2})?)?\)\sAppleWebKit/[0-9\.]+\+?\s\((?:KHTML,\s)?like\sGecko\)(?:\s([a-zA-Z0-9\./]+(?:\sMobile)?)/?[A-Z0-9]*)?\sSafari/([0-9\.]+)$#',$ua,$match)>0) {
241
  $top_ua['name'] = 'Safari';
242
  if (!empty($match[4])) { $vers = $match[4]; }
@@ -259,6 +255,26 @@ class UADetector {
259
  }
260
  $top_ua['language']=$match[3];
261
  $top_ua['agenttype']= 'B';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  }
263
  //check http header for user agent spoofing and for os and screen resolution
264
  if ($is_current_ua) {
@@ -279,7 +295,7 @@ class UADetector {
279
  } else {
280
  $top_ua=false;
281
  }
282
- if ($debug_mode) {
283
  echo "\n".'<br />uadetector: top_ua->name='.$top_ua['name']."&nbsp; ".'top_ua->os='.$top_ua['os']; //debug
284
  if ($do_profile) {
285
  profiler_endSection('____ua::isTopAgent');
@@ -295,7 +311,7 @@ class UADetector {
295
  * @return array (associative)
296
  */
297
  function isBrowserAgent($agent="") {
298
- global $debug_mode, $do_profile;
299
  $ua="";
300
  $is_current_ua = false;
301
  if (empty($agent)) {
@@ -310,7 +326,7 @@ class UADetector {
310
  $browser = array('name'=>"",'version'=>"",'os'=>"",'platform'=>"",'language'=>"",'agenttype'=>"B",'resolution'=>"",'device'=>"",'model'=>"", 'emulation'=>"");
311
 
312
  //spiders are not detected here, so exclude user agents that are likely spiders (ie. contains an email or URL, or spider-like keywords)
313
- if (isset($this->done_spiders) && !$this->done_spiders && preg_match('#(robot|bot[\s\-_\/\)]|bot$|blog|checker|crawl|feed|fetcher|libwww|[^\.e]link\s?|parser|reader|spider|verifier|href|https?\://|.+(?:\@|\s?at\s?)[a-z0-9_\-]+(?:\.|\s?dot\s?)|www[0-9]?\.[a-z0-9_\-]+\..+|\/.+\.(html?|aspx?|php5?|cgi))#i',$ua)>0) {
314
  //not spider if embedded browser or is a browser add-on such as spyware or translator
315
  if (preg_match('#(embedded\s?(WB|Web\sbrowser)|dynaweb|bsalsa\.com|muuk\.co|translat[eo]r?)#i',$ua)==0) {
316
  return false;
@@ -319,26 +335,23 @@ class UADetector {
319
  if ($do_profile) {
320
  profiler_beginSection('_____ua::isBrowser');
321
  }
322
- //Separate check for mobile browsers beforehand
323
  $ismobile = false;
324
- //check for mobile or embedded browser
325
  $wap = $this->isMobileAgent($ua);
326
  if (!empty($wap) && is_array($wap)) {
327
  $ismobile = true;
 
 
328
  $browser['device'] = $wap['device'];
329
  $browser['model'] = $wap['model'];
330
- $browser['platform'] = $wap['platform'];
331
- if (empty($browser['name'])) {
332
- $browser['name'] = $wap['name'];
333
- $browser['version'] = $wap['version'];
334
- }
335
- if (!empty($wap['os'])) $browser['os'] = $wap['os'];
336
  if (!empty($wap['language'])) $browser['language'] = $wap['language'];
337
  }
 
338
  if (!$ismobile || empty($browser['name'])) {
339
- //MSIE browsers
340
  if (preg_match('/compatible(?:\;|\,|\s)+MSIE\s(\d+)(\.\d+)+(.*)/',$ua,$pcs)>0) {
341
- if ($debug_mode) {
342
  echo "\nMatch for MSIE-based browser<br/>";
343
  }
344
  $browser['name'] = 'IE';
@@ -374,17 +387,15 @@ class UADetector {
374
  }
375
  }
376
 
 
377
  //Opera browsers
378
- } elseif (preg_match('#(Opera\s(?:Mini|Mobile))[/ ]([0-9\.]+)#',$ua,$pcs)>0) {
379
- $browser['name'] = $pcs[1];
380
- $browser['version'] = $pcs[2];
381
  } elseif (preg_match('#Opera[/ ]([0-9\.]+)#',$ua,$pcs)>0) {
382
  $browser['name'] = 'Opera';
383
  $browser['version'] = $pcs[1];
384
 
385
  //Firefox-based browsers (Camino, Flock) (find before FF)
386
  } elseif (preg_match('#[^a-z](Camino|Flock|Galeon|Orca)/(\d+[\.0-9a-z]*)#',$ua,$pcs)>0) {
387
- if ($debug_mode) {
388
  echo "\nMatch for Firefox-based browser<br/>";
389
  }
390
  $browser['name'] = $pcs[1];
@@ -392,7 +403,7 @@ class UADetector {
392
 
393
  //other Gecko-type browsers (incl. Firefox)
394
  } elseif (preg_match('#Gecko/\d+\s([a-z0-9_\- ]+)/(\d+[\.0-9a-z]*)(?:$|[^a-z0-9_\-]+([a-z0-9_\- ]+)/(\d+[\.0-9a-z]*)|[^a-z0-9_\-]*\(.*\))#i',$ua,$pcs)>0) {
395
- if ($debug_mode) {
396
  echo "\nMatch for Gecko-type browser<br/>";
397
  }
398
  $browser['name'] = $pcs[1];
@@ -403,7 +414,7 @@ class UADetector {
403
  }
404
  //Firefox browser
405
  } elseif (preg_match('#[^a-z](Fire(?:fox|bird))/?(\d+[\.0-9a-z]*)?#',$ua,$pcs)>0) {
406
- if ($debug_mode) {
407
  echo "\nMatch for Firefox browser<br/>";
408
  }
409
  $browser['name'] = $pcs[1];
@@ -412,7 +423,7 @@ class UADetector {
412
  }
413
  //Mozilla browser (like FF, but nothing after "rv:" or "Gecko")
414
  } elseif (preg_match('/^Mozilla\/\d\.\d.+\srv\:(\d[\.0-9a-z]+)[^a-z0-9]+(?:Gecko\/\d+)?$/i',$ua,$pcs)>0) {
415
- if ($debug_mode) {
416
  echo "\nMatch for Mozilla browser<br/>";
417
  }
418
  $browser['name'] = 'Mozilla';
@@ -422,7 +433,7 @@ class UADetector {
422
 
423
  //WebKit-based browsers
424
  } elseif (preg_match('#^Mozilla/\d\.\d\s\((?:([a-z]{3,}.*\s)?([a-z]{2}(?:\-[A-Za-z]{2})?)?)\)\sAppleWebKit/[0-9\.]+\+?\s\([a-z, ]*like\sGecko[a-z\; ]*\)\s([a-zA-Z0-9\./]+(?:\sMobile)?/?[A-Z0-9]*)?(\sSafari/([0-9\.]+))?$#',$ua,$pcs)>0) {
425
- if ($debug_mode) {
426
  echo "\nMatch for WebKit-based browser<br/>";
427
  }
428
  if (!empty($pcs[3])) { $vers = $pcs[3]; }
@@ -438,7 +449,7 @@ class UADetector {
438
 
439
  //Text-only browsers Lynx, ELinks...(yep, they still exist)
440
  } elseif (preg_match("#^(E?Links|Lynx|(?:Emacs\-)?w3m)[^a-z0-9]+([0-9\.]+)?#i",$ua,$pcs)) {
441
- if ($debug_mode) {
442
  echo "\nMatch for text browser<br/>";
443
  }
444
  $browser['name'] = $pcs[1];
@@ -478,7 +489,7 @@ class UADetector {
478
  }
479
  }
480
  }
481
- } //end if ($ismobile)
482
 
483
  //get operating system
484
  if (empty($browser['os']) && !empty($browser['name']) && $browser['agenttype']=="B") {
@@ -521,7 +532,7 @@ class UADetector {
521
  }
522
  $browser['agenttype']= "S";
523
  }
524
- if ($debug_mode) {
525
  echo "\n".'<br />uadetector: browser->name='.$browser['name']."&nbsp; ".'browser->os='.$browser['os']; //debug
526
  }
527
  if (!empty($browser['name'])) {
@@ -549,7 +560,7 @@ class UADetector {
549
  * @return array(browser, device, model, platform)
550
  */
551
  function isMobileAgent($agent="") {
552
- global $debug_mode, $do_profile;
553
  $ua="";
554
  $is_current_ua = false;
555
  if (empty($agent)) {
@@ -564,17 +575,14 @@ class UADetector {
564
  profiler_beginSection('____ua::isMobileUA');
565
  }
566
  $ismobile = false;
567
- $device = $ua;
568
- $wap = array('name'=>"",
569
- 'version'=>"",
570
- 'device'=>"",
571
- 'model'=>"",
572
- 'platform'=>"WAP");
573
  //detect known mobile browsers
574
 
575
  //Android-based devices
576
  if (preg_match("#^(?:([a-z0-9\-\s_]{3,})\s)?Mozilla/\d\.\d\s\([a-z\;\s]+Android\s([0-9\.]+)(?:\;\s([a-z]{2}(?:\-[A-Za-z]{2})?)\;)?.*Gecko\)\s([a-zA-Z0-9\./]+(?:\sMobile)?/?[A-Z0-9]*)?(\sSafari/([0-9\.]+))?#i",$ua,$pcs)) {
577
- $ismobile = true;
578
  if (!empty($pcs[4])) { $vers = $pcs[4]; }
579
  else { $vers = $pcs[6]; }
580
  $webkit = $this->webkitVersion($vers,$ua);
@@ -585,33 +593,40 @@ class UADetector {
585
  $wap['os'] = "Android";
586
  if (!empty($pcs[2])) $wap['os'] .= " ".$this->majorVersion($pcs[2]);
587
  if (!empty($pcs[3])) $wap['language'] = $pcs[3];
588
- if (!empty($pcs[1])) $device = $pcs[1];
 
 
 
 
 
 
 
 
 
 
589
 
590
  //NetFront and other mobile/embedded browsers
591
  } elseif (preg_match("#(NetFront|NF\-Browser)/([0-9\.]+)#i",$ua,$pcs)) {
592
- $ismobile = true;
593
  $wap['name'] = "NetFront";
594
  $wap['version'] = $pcs[2];
595
- } elseif (preg_match("#[^a-z0-9](Bolt|Iris|Minimo|Novarra\-Vision|Polaris)/([0-9\.]+)#i",$ua,$pcs)) {
596
- $ismobile = true;
597
  $wap['name'] = $pcs[1];
598
  $wap['version'] = $pcs[2];
599
  } elseif (preg_match("#(UP\.browser|SMIT\-Browser)/([0-9\.]+)#i",$ua,$pcs)) {
600
- $ismobile = true;
601
  $wap['name'] = $pcs[1];
602
  $wap['version'] = $pcs[2];
603
  } elseif (preg_match("#\((jig\sbrowser).*\s([0-9\.]+)[^a-z0-9]#i",$ua,$pcs)) {
604
- $ismobile = true;
605
  $wap['name'] = $pcs[1];
606
  $wap['version'] = $pcs[2];
607
  } elseif (preg_match("#[^a-z]Obigo#i",$ua,$pcs)) {
608
- $ismobile = true;
609
  $wap['name'] = 'Obigo';
610
  } elseif (preg_match("#openwave(\suntrusted)?/([0-9\.]+)#i",$ua,$pcs)) {
611
- $ismobile = true;
612
  $wap['name'] = 'OpenWave';
613
  $wap['version'] = $pcs[2];
614
  }
 
 
 
615
 
616
  //known mobile devices...
617
  if (preg_match('#(alcatel|amoi|blackberry|docomo\s|htc|ipaq|kindle|kwc|lge|lg\-|mobilephone|motorola|nexus\sone|nokia|PDA|Palm|Samsung|sanyo|smartphone|SonyEricsson|\st\-mobile|vodafone|zte)[/\-_\s]?((?:\d|[a-z])+\d+[a-z]*)*#i',$ua,$pcs)>0) {
@@ -648,18 +663,29 @@ class UADetector {
648
  $ismobile=true;
649
  }
650
  }
 
 
 
 
651
  }
652
- //TODO: check for wireless transcoder service user agents
653
- if (!$ismobile && preg_match('#wireless\stranscoder#i',$ua)>0) {
654
- $ismobile=true;
 
 
 
 
 
 
655
  }
656
- if ($debug_mode) {
657
  echo "\n".'<br />uadetector: wap->name='.$wap['name']."&nbsp; ".'wap->device='.$wap['device']; //debug
658
  }
659
  if ($do_profile) {
660
  profiler_endSection('____ua::isMobileUA');
661
  }
662
  if ($ismobile) {
 
663
  return $wap;
664
  } else {
665
  return false;
@@ -673,7 +699,7 @@ class UADetector {
673
  * @return array (associative)
674
  */
675
  function isSpiderAgent($agent="") {
676
- global $debug_mode, $do_profile;
677
  $ua="";
678
  $is_current_ua = false;
679
  list($ua,$is_current_ua) = $this->isCurrentAgent($agent);
@@ -691,7 +717,13 @@ class UADetector {
691
  $spider['version']=$match[1];
692
  $spider['agenttype']= 'F';
693
 
694
- // #12 FeedFetcher Google
 
 
 
 
 
 
695
  } elseif (preg_match('#^Feedfetcher\-Google[;\s\(\+]+http\://www\.google\.com/feedfetcher\.html[;\)\s]+(?:(\d)\ssubscriber)?#',$ua,$match)>0) {
696
  $spider['name'] = 'FeedFetcher-Google';
697
  if (!empty($match[1])) {
@@ -752,6 +784,9 @@ class UADetector {
752
  if (!empty($match[2])) {
753
  $spider['version']=$match[2];
754
  }
 
 
 
755
 
756
  //TODO: Libwww spiders
757
  //TODO: Trackback agents from blogs on MovableType, Drupal, DotNetNuke,...
@@ -762,6 +797,12 @@ class UADetector {
762
  if (!empty($match[3])) {
763
  $spider['version'] = $match[3];
764
  }
 
 
 
 
 
 
765
  // #Assume bot if user-agent 1st word and a contact domain are the same name, ex: Feedburner-feedburner.com, CazoodleBot,
766
  } elseif (preg_match('/([a-z\_\s\.]+)[\s\/\-_]?(v?[0-9\.]+)?.*(?:http\:\/\/|www\.)(\1)\.[a-z0-9_\-]+/i',$ua,$match)>0) {
767
  $spider['name'] = $match[1];
@@ -789,6 +830,11 @@ class UADetector {
789
  }
790
 
791
  // #Assume bot if user-agent includes contact email
 
 
 
 
 
792
  } elseif (preg_match('/^(([a-z]+)\s?(bot|crawler|robot|spider|\s[a-z]+)?)[\/\-\s_](v?[0-9\.]+)?.*[^a-z]+(?:\1|\2|\3)(?:\@|\s?at\s?)[a-z\-_]{2,}(?:\.|\s?dot\s)[a-z]{2,4}/i',$ua,$match)>0) {
793
  $spider['name'] = $match[1];
794
  if (!empty($match[4])) {
@@ -887,7 +933,7 @@ class UADetector {
887
  $spider['name'] = _e("Script Injection Bot");
888
  $spider['agenttype']= "S";
889
  }
890
- if ($debug_mode) {
891
  echo "\n".'<br />uadetector: spider->name='.$spider['name']."&nbsp; "; //debug
892
  }
893
  if (empty($spider['name'])) {
@@ -915,7 +961,7 @@ class UADetector {
915
  $ua = $this->agent;
916
  }
917
  }
918
- //distinguish feed readers from other spiders
919
  if (preg_match("/([0-9]+)\s?subscriber/i",$ua,$subscriber) >0) {
920
  // It's a feedreader with some subscribers
921
  $feed['subscribers'] = $subscriber[1];
@@ -967,7 +1013,7 @@ class UADetector {
967
  * @return none
968
  */
969
  function isWTF($ua="") {
970
- global $debug_mode, $do_profile;
971
  //recheck browsers or check PHP's browser capabilities file
972
  if (isset($this->done_browsers) && !$this->done_browsers) {
973
  return $this->isBrowserAgent($ua);
@@ -980,7 +1026,7 @@ class UADetector {
980
  if (!empty($unknown_agent['name'])) {
981
  $this->setClassVars($unknown_agent);
982
  }
983
- if ($debug_mode) {
984
  echo "\n".'<br />uadetector: unknown_agent->name='.$unknown_agent['name']."&nbsp; "; //debug
985
  }
986
  if ($do_profile) {
@@ -995,7 +1041,7 @@ class UADetector {
995
  * @return array(os_type, platform, device)
996
  */
997
  function OSversion($os="",$platform="",$ua="") {
998
- global $debug_mode, $do_profile;
999
  if ($do_profile) {
1000
  profiler_beginSection('_____ua::OSversion');
1001
  }
@@ -1226,7 +1272,7 @@ class UADetector {
1226
  * @return string
1227
  */
1228
  function linuxOSversion($os="") {
1229
- global $debug_mode, $do_profile;
1230
  if (empty($os)) { $os = $this->agent; }
1231
  if (empty($os)) { return false; }
1232
  if ($do_profile) {
@@ -1292,15 +1338,15 @@ class UADetector {
1292
  * @return associative array (browser, version)
1293
  */
1294
  function webkitVersion($webkit="",$ua="") {
1295
- global $debug_mode;
1296
  $browser = "Safari";
1297
  $vers = "";
1298
- if ($debug_mode) {
1299
  echo "<br />webkit=".$webkit."\n"; //debug
1300
  }
1301
  if (empty($webkit)) {
1302
  return false;
1303
- } elseif (preg_match("#^([a-zA-Z]+)/([0-9](?:[A-Za-z\.0-9]+))(\sMobile)?#",$webkit,$match)>0) {
1304
  if ($match[1] != "Version") { //Chrome,Iron,Shiira
1305
  $browser = $match[1];
1306
  }
@@ -1395,7 +1441,7 @@ class UADetector {
1395
  * @return array
1396
  */
1397
  function getBrowscap($ua="") {
1398
- global $debug_mode;
1399
  if (empty($ua)) $ua = $this->agent;
1400
  $browsercap = false;
1401
  $browser = array('name'=>"",'version'=>"",'os'=>"",'platform'=>"",'agenttype'=>"B");
@@ -1406,7 +1452,7 @@ class UADetector {
1406
  //}
1407
  if (ini_get("browscap")!="") {
1408
  $browsercap = get_browser($ua,true);
1409
- if ($debug_mode) {
1410
  echo "\n<br/>Browsercap=";
1411
  print_r($browsercap);
1412
  echo "\n<br />";
1
  <?php
2
  /**
3
  * UADetector.class.php
4
+ * Description: a PHP4 class for browser and spider identification
5
+ * Updated: 2011-07-13
6
+ * @version 0.9a5
7
+ * @author Helene Duncker <techfromhel@gmail.com>
8
+ * Author URI: http://techfromhel.webege.com/
9
  *
10
+ * @copyright Copyright (c) 2009-2011 Helene Duncker
11
  * @license http://www.gnu.org/licenses/gpl.txt GNU General Public License
12
  */
13
  /**
15
  * $useragent = new UADetector(); //returns object(16)
16
  *
17
  * Note: UADetector attempts to find the actual browser in use. This may
18
+ * cause the "name" field to differ from "emulation" field when
19
+ * user-agent "spoofing" is detected. Use the appropriate field
20
+ * for your application type:
21
+ * a) "Name" field is best for information and statistics only.
22
+ * b) "Emulation" field is best for UI and customizations by browser type.
23
  *
24
  * Disclaimer: Use at your own risk. No warranty expressed or implied is provided.
25
  */
26
  class UADetector {
27
+ var $name = ''; //browser or spider name, not null
28
+ var $version = ''; //browser or spider version, if available
29
  var $os = ''; //operating system+version, if available
30
+ var $platform = ''; //operating system or device platform
31
  var $emulation = ''; //emulated browser plus major version#
32
+ var $language = ''; //language code (not locale), if available
33
+ var $device = ''; //PC, PDA, Phone, TV, if available
34
+ var $model = ''; //Device manufacturer model, if available
35
  var $resolution = ''; //screen size (MMMxNNN), if in user-agent
36
+ var $subscribers = ''; //feed subscriber count, if in user-agent
37
  var $is_mobile = false;
38
  var $is_browser = false;
39
  var $is_robot = false;
64
  * @constructor
65
  * @access public
66
  * @param string $ua (optional)
67
+ * @return object(16)
68
  */
69
  function __construct($ua="") {
70
+ global $wdebug_mode, $do_profile;
71
  $do_profile= false;
72
+ if ($wdebug_mode && function_exists('profiler_beginSection')) {
73
  $do_profile = true;
74
  profiler_beginSection('(Subtot)uaDetector');
75
  }
139
  //NOTE: Top agents are based on recent log data from
140
  // "WassUp", a web statistics plugin for WordPress 2.2+
141
  // available at http://www.wpwp.org
142
+ global $wdebug_mode, $do_profile;
143
 
144
  // User agent parameter or class variable is required.
145
  $ua="";
174
  if (!empty($match[3])) {
175
  $top_ua['device'] = $match[3];
176
  }
177
+ // #3 Firefox and other Mozilla browsers on Windows
178
  } elseif (preg_match('#^Mozilla/\d\.\d\s\(Windows;\sU;\s(.+);\s([a-z]{2}(?:\-[A-Za-z]{2})?);\srv\:\d(?:\.\d+)+\)\sGecko/\d+\s([A-Za-z\-0-9]+)/(\d+(?:\.\d+)+)(?:\s\(.*\))?$#',$ua,$match)>0) {
179
  $top_ua['name'] = $match[3];
180
  $top_ua['version'] = $match[4];
193
  $top_ua['language']=$match[2];
194
  }
195
  $top_ua['agenttype']= 'R';
196
+ // #5 BingBot
197
+ } elseif (preg_match('#^Mozilla/\d\.\d\s\(compatible;\sbingbot/(\d\.\d)[^a-z0-9]+http\://www\.bing\.com/bingbot\.htm.$#',$ua,$match)>0) {
198
+ $top_ua['name'] = 'BingBot';
199
  if (!empty($match[1])) {
200
  $top_ua['name'].=$match[1];
201
  }
203
  $top_ua['version']=$match[2];
204
  }
205
  $top_ua['agenttype']= 'R';
206
+ // #6 FeedBurner
 
 
 
 
 
207
  } elseif (preg_match('#^FeedBurner/(\d\.\d)\s\(http\://www\.FeedBurner\.com\)$#',$ua,$match)>0) {
208
  $top_ua['name'] = 'FeedBurner';
209
  $top_ua['version']=$match[1];
210
  $top_ua['agenttype']= 'F';
211
+ // #7 Wordpress
212
  } elseif (preg_match('#^WordPress/(?:wordpress(\-mu)\-)?(\d\.\d+)(?:\.\d+)*(?:\-[a-z]+)?(?:\;\shttp\://[a-z0-9_\.\:\/]+)?$#',$ua,$match)>0) {
213
  $top_ua['name'] = 'Wordpress';
214
  if (!empty($match[1])) {
216
  }
217
  $top_ua['version']=$match[2];
218
  $top_ua['agenttype']= 'U';
219
+ // #8 Firefox and Gecko browsers on Mac|*nix|OS/2 etc...
220
  } elseif (preg_match('#^Mozilla/\d\.\d\s\((Macintosh|X11|OS/2);\sU;\s(.+);\s([a-z]{2}(?:\-[A-Za-z]{2})?)(?:-mac)?;\srv\:\d(?:.\d+)+\)\sGecko/\d+\s([A-Za-z\-0-9]+)/(\d+(?:\.[0-9a-z\-\.]+))+(?:(\s\(.*\))(?:\s([A-Za-z\-0-9]+)/(\d+(?:\.\d+)+)))?$#',$ua,$match)>0) {
221
  $top_ua['name'] = $match[4];
222
  $top_ua['version'] = $match[5];
232
  }
233
  list($top_ua['os']) = $this->OSversion($os,$top_ua['platform'],$ua);
234
  $top_ua['agenttype']= 'B';
235
+ // #9 Safari and Webkit-based browsers on all platforms
236
  } elseif (preg_match('#^Mozilla/\d\.\d\s\(([A-Za-z0-9/\.]+);\sU;?\s?(.*);\s?([a-z]{2}(?:\-[A-Za-z]{2})?)?\)\sAppleWebKit/[0-9\.]+\+?\s\((?:KHTML,\s)?like\sGecko\)(?:\s([a-zA-Z0-9\./]+(?:\sMobile)?)/?[A-Z0-9]*)?\sSafari/([0-9\.]+)$#',$ua,$match)>0) {
237
  $top_ua['name'] = 'Safari';
238
  if (!empty($match[4])) { $vers = $match[4]; }
255
  }
256
  $top_ua['language']=$match[3];
257
  $top_ua['agenttype']= 'B';
258
+
259
+ // #10 Google Chrome browser on all platforms with or without language string
260
+ } elseif (preg_match('#^Mozilla/\d+\.\d+\s(?:[A-Za-z0-9\./]+\s)?\((?:([A-Za-z0-9/\.]+);(?:\sU;)?\s?)?([^;]*)(?:;\s[A-Za-z]{3}64)?;?\s?([a-z]{2}(?:\-[A-Za-z]{2})?)?\)\sAppleWebKit/[0-9\.]+\+?\s\((?:KHTML,\s)?like\sGecko\)(?:\s([A-Za-z0-9_\-]+[^i])/([A-Za-z0-9\.]+)){1,3}(?:\sSafari/[0-9\.]+)?$#',$ua,$match)>0) {
261
+ $top_ua['name'] = $match[4];
262
+ $top_ua['version'] = $match[5];
263
+ if (empty($match[2])) {
264
+ $os = $match[1];
265
+ } else {
266
+ $top_ua['platform'] = $match[1];
267
+ $os = $match[2];
268
+ }
269
+ if ($top_ua['platform'] == 'Windows') {
270
+ $top_ua['os'] = $this->winOSversion($os);
271
+ } else {
272
+ list($top_ua['os']) = $this->OSversion($os,$top_ua['platform'],$ua);
273
+ }
274
+ if (!empty($match[3])) {
275
+ $top_ua['language']=$match[3];
276
+ }
277
+ $top_ua['agenttype']= 'B';
278
  }
279
  //check http header for user agent spoofing and for os and screen resolution
280
  if ($is_current_ua) {
295
  } else {
296
  $top_ua=false;
297
  }
298
+ if ($wdebug_mode) {
299
  echo "\n".'<br />uadetector: top_ua->name='.$top_ua['name']."&nbsp; ".'top_ua->os='.$top_ua['os']; //debug
300
  if ($do_profile) {
301
  profiler_endSection('____ua::isTopAgent');
311
  * @return array (associative)
312
  */
313
  function isBrowserAgent($agent="") {
314
+ global $wdebug_mode, $do_profile;
315
  $ua="";
316
  $is_current_ua = false;
317
  if (empty($agent)) {
326
  $browser = array('name'=>"",'version'=>"",'os'=>"",'platform'=>"",'language'=>"",'agenttype'=>"B",'resolution'=>"",'device'=>"",'model'=>"", 'emulation'=>"");
327
 
328
  //spiders are not detected here, so exclude user agents that are likely spiders (ie. contains an email or URL, or spider-like keywords)
329
+ if (isset($this->done_spiders) && !$this->done_spiders && preg_match('#(robot|bot[\s\-_\/\)]|bot$|blog|checker|crawl|feed|fetcher|libwww|[^\.e]link\s?|parser|reader|spider|verifier|href|https?\://|.+(?:\@|\s?at\s?)[a-z0-9_\-]+(?:\.|\s?dot\s?)|www[0-9]?\.[a-z0-9_\-]+\..+|\/.+\.(s?html?|aspx?|php5?|cgi))#i',$ua)>0) {
330
  //not spider if embedded browser or is a browser add-on such as spyware or translator
331
  if (preg_match('#(embedded\s?(WB|Web\sbrowser)|dynaweb|bsalsa\.com|muuk\.co|translat[eo]r?)#i',$ua)==0) {
332
  return false;
335
  if ($do_profile) {
336
  profiler_beginSection('_____ua::isBrowser');
337
  }
338
+ //### Step 1: check for mobile or embedded browsers
339
  $ismobile = false;
 
340
  $wap = $this->isMobileAgent($ua);
341
  if (!empty($wap) && is_array($wap)) {
342
  $ismobile = true;
343
+ $browser['name'] = $wap['name'];
344
+ $browser['version'] = $wap['version'];
345
  $browser['device'] = $wap['device'];
346
  $browser['model'] = $wap['model'];
347
+ $browser['os'] = $wap['os'];
348
+ $browser['platform'] = "WAP";
 
 
 
 
349
  if (!empty($wap['language'])) $browser['language'] = $wap['language'];
350
  }
351
+ //### Step 2: Check for MSIE-based browsers
352
  if (!$ismobile || empty($browser['name'])) {
 
353
  if (preg_match('/compatible(?:\;|\,|\s)+MSIE\s(\d+)(\.\d+)+(.*)/',$ua,$pcs)>0) {
354
+ if ($wdebug_mode) {
355
  echo "\nMatch for MSIE-based browser<br/>";
356
  }
357
  $browser['name'] = 'IE';
387
  }
388
  }
389
 
390
+ //### Step 3: Check for All Other browsers
391
  //Opera browsers
 
 
 
392
  } elseif (preg_match('#Opera[/ ]([0-9\.]+)#',$ua,$pcs)>0) {
393
  $browser['name'] = 'Opera';
394
  $browser['version'] = $pcs[1];
395
 
396
  //Firefox-based browsers (Camino, Flock) (find before FF)
397
  } elseif (preg_match('#[^a-z](Camino|Flock|Galeon|Orca)/(\d+[\.0-9a-z]*)#',$ua,$pcs)>0) {
398
+ if ($wdebug_mode) {
399
  echo "\nMatch for Firefox-based browser<br/>";
400
  }
401
  $browser['name'] = $pcs[1];
403
 
404
  //other Gecko-type browsers (incl. Firefox)
405
  } elseif (preg_match('#Gecko/\d+\s([a-z0-9_\- ]+)/(\d+[\.0-9a-z]*)(?:$|[^a-z0-9_\-]+([a-z0-9_\- ]+)/(\d+[\.0-9a-z]*)|[^a-z0-9_\-]*\(.*\))#i',$ua,$pcs)>0) {
406
+ if ($wdebug_mode) {
407
  echo "\nMatch for Gecko-type browser<br/>";
408
  }
409
  $browser['name'] = $pcs[1];
414
  }
415
  //Firefox browser
416
  } elseif (preg_match('#[^a-z](Fire(?:fox|bird))/?(\d+[\.0-9a-z]*)?#',$ua,$pcs)>0) {
417
+ if ($wdebug_mode) {
418
  echo "\nMatch for Firefox browser<br/>";
419
  }
420
  $browser['name'] = $pcs[1];
423
  }
424
  //Mozilla browser (like FF, but nothing after "rv:" or "Gecko")
425
  } elseif (preg_match('/^Mozilla\/\d\.\d.+\srv\:(\d[\.0-9a-z]+)[^a-z0-9]+(?:Gecko\/\d+)?$/i',$ua,$pcs)>0) {
426
+ if ($wdebug_mode) {
427
  echo "\nMatch for Mozilla browser<br/>";
428
  }
429
  $browser['name'] = 'Mozilla';
433
 
434
  //WebKit-based browsers
435
  } elseif (preg_match('#^Mozilla/\d\.\d\s\((?:([a-z]{3,}.*\s)?([a-z]{2}(?:\-[A-Za-z]{2})?)?)\)\sAppleWebKit/[0-9\.]+\+?\s\([a-z, ]*like\sGecko[a-z\; ]*\)\s([a-zA-Z0-9\./]+(?:\sMobile)?/?[A-Z0-9]*)?(\sSafari/([0-9\.]+))?$#',$ua,$pcs)>0) {
436
+ if ($wdebug_mode) {
437
  echo "\nMatch for WebKit-based browser<br/>";
438
  }
439
  if (!empty($pcs[3])) { $vers = $pcs[3]; }
449
 
450
  //Text-only browsers Lynx, ELinks...(yep, they still exist)
451
  } elseif (preg_match("#^(E?Links|Lynx|(?:Emacs\-)?w3m)[^a-z0-9]+([0-9\.]+)?#i",$ua,$pcs)) {
452
+ if ($wdebug_mode) {
453
  echo "\nMatch for text browser<br/>";
454
  }
455
  $browser['name'] = $pcs[1];
489
  }
490
  }
491
  }
492
+ } //end if (!$ismobile)
493
 
494
  //get operating system
495
  if (empty($browser['os']) && !empty($browser['name']) && $browser['agenttype']=="B") {
532
  }
533
  $browser['agenttype']= "S";
534
  }
535
+ if ($wdebug_mode) {
536
  echo "\n".'<br />uadetector: browser->name='.$browser['name']."&nbsp; ".'browser->os='.$browser['os']; //debug
537
  }
538
  if (!empty($browser['name'])) {
560
  * @return array(browser, device, model, platform)
561
  */
562
  function isMobileAgent($agent="") {
563
+ global $wdebug_mode, $do_profile;
564
  $ua="";
565
  $is_current_ua = false;
566
  if (empty($agent)) {
575
  profiler_beginSection('____ua::isMobileUA');
576
  }
577
  $ismobile = false;
578
+ //$device = $ua;
579
+ $wap = array('name'=>"", 'version'=>"",
580
+ 'device'=>"", 'model'=>"",
581
+ 'os'=>"", 'platform'=>"WAP");
 
 
582
  //detect known mobile browsers
583
 
584
  //Android-based devices
585
  if (preg_match("#^(?:([a-z0-9\-\s_]{3,})\s)?Mozilla/\d\.\d\s\([a-z\;\s]+Android\s([0-9\.]+)(?:\;\s([a-z]{2}(?:\-[A-Za-z]{2})?)\;)?.*Gecko\)\s([a-zA-Z0-9\./]+(?:\sMobile)?/?[A-Z0-9]*)?(\sSafari/([0-9\.]+))?#i",$ua,$pcs)) {
 
586
  if (!empty($pcs[4])) { $vers = $pcs[4]; }
587
  else { $vers = $pcs[6]; }
588
  $webkit = $this->webkitVersion($vers,$ua);
593
  $wap['os'] = "Android";
594
  if (!empty($pcs[2])) $wap['os'] .= " ".$this->majorVersion($pcs[2]);
595
  if (!empty($pcs[3])) $wap['language'] = $pcs[3];
596
+ if (!empty($pcs[1])) $wap['device'] = $pcs[1];
597
+
598
+ //Windows Mobile browsers
599
+ } elseif (preg_match('#Windows\sCE;\s?IEMobile\s(\d+)(\.\d+)*\)#i',$ua,$pcs)>0) {
600
+ $wap['name'] = 'IEMobile';
601
+ $wap['version'] = $pcs[1];
602
+ $wap['os'] = 'WinCE';
603
+ //Opera Mini/mobile browsers
604
+ } elseif (preg_match('#(Opera\s(?:Mini|Mobile))[/ ]([0-9\.]+)#',$ua,$pcs)>0) {
605
+ $wap['name'] = $pcs[1];
606
+ $wap['version'] = $pcs[2];
607
 
608
  //NetFront and other mobile/embedded browsers
609
  } elseif (preg_match("#(NetFront|NF\-Browser)/([0-9\.]+)#i",$ua,$pcs)) {
 
610
  $wap['name'] = "NetFront";
611
  $wap['version'] = $pcs[2];
612
+ } elseif (preg_match("#[^a-z0-9](Bolt|Iris|Jasmine|Minimo|Novarra\-Vision|Polaris)/([0-9\.]+)#i",$ua,$pcs)) {
 
613
  $wap['name'] = $pcs[1];
614
  $wap['version'] = $pcs[2];
615
  } elseif (preg_match("#(UP\.browser|SMIT\-Browser)/([0-9\.]+)#i",$ua,$pcs)) {
 
616
  $wap['name'] = $pcs[1];
617
  $wap['version'] = $pcs[2];
618
  } elseif (preg_match("#\((jig\sbrowser).*\s([0-9\.]+)[^a-z0-9]#i",$ua,$pcs)) {
 
619
  $wap['name'] = $pcs[1];
620
  $wap['version'] = $pcs[2];
621
  } elseif (preg_match("#[^a-z]Obigo#i",$ua,$pcs)) {
 
622
  $wap['name'] = 'Obigo';
623
  } elseif (preg_match("#openwave(\suntrusted)?/([0-9\.]+)#i",$ua,$pcs)) {
 
624
  $wap['name'] = 'OpenWave';
625
  $wap['version'] = $pcs[2];
626
  }
627
+ if (!empty($wap['name'])) {
628
+ $ismobile = true;
629
+ }
630
 
631
  //known mobile devices...
632
  if (preg_match('#(alcatel|amoi|blackberry|docomo\s|htc|ipaq|kindle|kwc|lge|lg\-|mobilephone|motorola|nexus\sone|nokia|PDA|Palm|Samsung|sanyo|smartphone|SonyEricsson|\st\-mobile|vodafone|zte)[/\-_\s]?((?:\d|[a-z])+\d+[a-z]*)*#i',$ua,$pcs)>0) {
663
  $ismobile=true;
664
  }
665
  }
666
+ //TODO: check for wireless transcoder service user agents
667
+ if (!$ismobile && preg_match('#wireless\stranscoder#i',$ua)>0) {
668
+ $ismobile=true;
669
+ }
670
  }
671
+ //set os = device, if missing
672
+ if ($ismobile) {
673
+ if (!empty($wap['device'])) {
674
+ if (empty($wap['name'])) {
675
+ $wap['name'] = $wap['device'];
676
+ } elseif (empty($wap['os'])) {
677
+ $wap['os'] = $wap['device'];
678
+ }
679
+ }
680
  }
681
+ if ($wdebug_mode) {
682
  echo "\n".'<br />uadetector: wap->name='.$wap['name']."&nbsp; ".'wap->device='.$wap['device']; //debug
683
  }
684
  if ($do_profile) {
685
  profiler_endSection('____ua::isMobileUA');
686
  }
687
  if ($ismobile) {
688
+ if (empty($wap['os'])) $wap['os'] = "WAP";
689
  return $wap;
690
  } else {
691
  return false;
699
  * @return array (associative)
700
  */
701
  function isSpiderAgent($agent="") {
702
+ global $wdebug_mode, $do_profile;
703
  $ua="";
704
  $is_current_ua = false;
705
  list($ua,$is_current_ua) = $this->isCurrentAgent($agent);
717
  $spider['version']=$match[1];
718
  $spider['agenttype']= 'F';
719
 
720
+ // #12 Twiceler
721
+ } elseif (preg_match('#^Mozilla/\d\.\d\s\(Twiceler\-(\d\.\d)\shttp://www\.cuill?\.com/twiceler/robot\.html\)$#',$ua,$match)>0) {
722
+ $spider['name'] = 'Twiceler';
723
+ $spider['version']=$match[1];
724
+ $spider['agenttype']= 'R';
725
+
726
+ // #13 FeedFetcher Google
727
  } elseif (preg_match('#^Feedfetcher\-Google[;\s\(\+]+http\://www\.google\.com/feedfetcher\.html[;\)\s]+(?:(\d)\ssubscriber)?#',$ua,$match)>0) {
728
  $spider['name'] = 'FeedFetcher-Google';
729
  if (!empty($match[1])) {
784
  if (!empty($match[2])) {
785
  $spider['version']=$match[2];
786
  }
787
+ if (strlen($match[1]) < 5) {
788
+ $spider['name'] = $match[1]. " Spider";
789
+ }
790
 
791
  //TODO: Libwww spiders
792
  //TODO: Trackback agents from blogs on MovableType, Drupal, DotNetNuke,...
797
  if (!empty($match[3])) {
798
  $spider['version'] = $match[3];
799
  }
800
+ } elseif (preg_match('#^Mozilla\/\d\.\d\s\(compatible;\s([a-z_ ]+)(?:[-/](\d+\.\d+))?;\s.?http://(?:www\.)?[a-z]+(?:[a-z\.]+)\.(?:[a-z]{2,4})/?[a-z/]*(?:\.s?html?|\.php|\.aspx?)?\)$#i',$ua,$match)>0) {
801
+ $spider['name'] = $match[1];
802
+ if (!empty($match[2])) {
803
+ $spider['version'] = $match[2];
804
+ }
805
+
806
  // #Assume bot if user-agent 1st word and a contact domain are the same name, ex: Feedburner-feedburner.com, CazoodleBot,
807
  } elseif (preg_match('/([a-z\_\s\.]+)[\s\/\-_]?(v?[0-9\.]+)?.*(?:http\:\/\/|www\.)(\1)\.[a-z0-9_\-]+/i',$ua,$match)>0) {
808
  $spider['name'] = $match[1];
830
  }
831
 
832
  // #Assume bot if user-agent includes contact email
833
+ } elseif (preg_match('#^Mozilla\/\d\.\d\s\(compatible;\s([a-z_ ]+)(?:[-/](\d+\.\d+))?;\s[^a-z0-9]?([a-z0-9\.]+@[a-z0-9]+\.[a-z]{2,4})\)$#i',$ua,$match)>0) {
834
+ $spider['name'] = $match[1];
835
+ if (!empty($match[2])) {
836
+ $spider['version'] = $match[2];
837
+ }
838
  } elseif (preg_match('/^(([a-z]+)\s?(bot|crawler|robot|spider|\s[a-z]+)?)[\/\-\s_](v?[0-9\.]+)?.*[^a-z]+(?:\1|\2|\3)(?:\@|\s?at\s?)[a-z\-_]{2,}(?:\.|\s?dot\s)[a-z]{2,4}/i',$ua,$match)>0) {
839
  $spider['name'] = $match[1];
840
  if (!empty($match[4])) {
933
  $spider['name'] = _e("Script Injection Bot");
934
  $spider['agenttype']= "S";
935
  }
936
+ if ($wdebug_mode) {
937
  echo "\n".'<br />uadetector: spider->name='.$spider['name']."&nbsp; "; //debug
938
  }
939
  if (empty($spider['name'])) {
961
  $ua = $this->agent;
962
  }
963
  }
964
+ //separate feed readers from spiders
965
  if (preg_match("/([0-9]+)\s?subscriber/i",$ua,$subscriber) >0) {
966
  // It's a feedreader with some subscribers
967
  $feed['subscribers'] = $subscriber[1];
1013
  * @return none
1014
  */
1015
  function isWTF($ua="") {
1016
+ global $wdebug_mode, $do_profile;
1017
  //recheck browsers or check PHP's browser capabilities file
1018
  if (isset($this->done_browsers) && !$this->done_browsers) {
1019
  return $this->isBrowserAgent($ua);
1026
  if (!empty($unknown_agent['name'])) {
1027
  $this->setClassVars($unknown_agent);
1028
  }
1029
+ if ($wdebug_mode) {
1030
  echo "\n".'<br />uadetector: unknown_agent->name='.$unknown_agent['name']."&nbsp; "; //debug
1031
  }
1032
  if ($do_profile) {
1041
  * @return array(os_type, platform, device)
1042
  */
1043
  function OSversion($os="",$platform="",$ua="") {
1044
+ global $wdebug_mode, $do_profile;
1045
  if ($do_profile) {
1046
  profiler_beginSection('_____ua::OSversion');
1047
  }
1272
  * @return string
1273
  */
1274
  function linuxOSversion($os="") {
1275
+ global $wdebug_mode, $do_profile;
1276
  if (empty($os)) { $os = $this->agent; }
1277
  if (empty($os)) { return false; }
1278
  if ($do_profile) {
1338
  * @return associative array (browser, version)
1339
  */
1340
  function webkitVersion($webkit="",$ua="") {
1341
+ global $wdebug_mode;
1342
  $browser = "Safari";
1343
  $vers = "";
1344
+ if ($wdebug_mode) {
1345
  echo "<br />webkit=".$webkit."\n"; //debug
1346
  }
1347
  if (empty($webkit)) {
1348
  return false;
1349
+ } elseif (preg_match("#^([a-zA-Z]+)/([0-9]+(?:[A-Za-z\.0-9]+))(\sMobile)?#",$webkit,$match)>0) {
1350
  if ($match[1] != "Version") { //Chrome,Iron,Shiira
1351
  $browser = $match[1];
1352
  }
1441
  * @return array
1442
  */
1443
  function getBrowscap($ua="") {
1444
+ global $wdebug_mode;
1445
  if (empty($ua)) $ua = $this->agent;
1446
  $browsercap = false;
1447
  $browser = array('name'=>"",'version'=>"",'os'=>"",'platform'=>"",'agenttype'=>"B");
1452
  //}
1453
  if (ini_get("browscap")!="") {
1454
  $browsercap = get_browser($ua,true);
1455
+ if ($wdebug_mode) {
1456
  echo "\n<br/>Browsercap=";
1457
  print_r($browsercap);
1458
  echo "\n<br />";
lib/upgrade.php CHANGED
@@ -6,14 +6,14 @@
6
  /**
7
  * Contains functions to create and update the tables required for WassUp
8
  * install and upgrade. These functions are loaded only when plugin is
9
- * activated via the 'wassup_install' hook function.
10
  * @since version 1.8
11
  * @author Helene D.
12
  */
13
 
14
  /**
15
  * Table install manager function that calls either 'wCreateTable' or
16
- * 'wUpdateTable' depending on whether this is a new install or upgrade.
17
  * @param none
18
  * @return boolean
19
  */
@@ -24,38 +24,39 @@ function wassup_tableInstaller() {
24
  $wassup_table = (!empty($wassup_options->wassup_table)? $wassup_options->wassup_table : $wpdb->prefix . "wassup");
25
  $wassup_tmp_table = $wassup_table."_tmp";
26
  $wassup_meta_table = $wassup_table."_meta";
27
- $charset=true;
28
- $success=false;
 
29
 
30
- //CREATE new table
31
- if ($wpdb->get_var("SHOW TABLES LIKE '$wassup_table'") != $wassup_table) {
 
 
 
32
  if (wCreateTable()) { //1st attempt
33
- $charset=true;
34
  }
35
  //2nd attempt: no character set in table
36
- if ($wpdb->get_var("SHOW TABLES LIKE '$wassup_table'") != $wassup_table) {
37
- $charset=false;
38
- wCreateTable("",$charset);
39
  }
40
 
41
- } else {
42
- //'wUpdateTable' now uses 'wCreateTable' and Wordpress' 'dbdelta' function to upgrade table structure
43
- $charset=false;
44
- wUpdateTable(); //<== wassup_tmp is added here, if missing
45
  }
46
 
47
  //check that install was successful, issue warnings, start tracker
48
- if ($wpdb->get_var("SHOW TABLES LIKE '$wassup_table'") == $wassup_table) {
49
- $success=true;
50
  //double-check that temp and meta were created
51
- if ($wpdb->get_var("SHOW TABLES LIKE '$wassup_tmp_table'") != $wassup_tmp_table) {
52
- wCreateTable($wassup_tmp_table,$charset);
53
  }
54
- if ($wpdb->get_var("SHOW TABLES LIKE '$wassup_meta_table'") != $wassup_meta_table) {
55
- wCreateTable($wassup_meta_table,$charset);
56
  }
57
  }
58
- return $success;
 
59
  } //#end function wassup_tableInstaller
60
 
61
  /**
@@ -64,14 +65,14 @@ function wassup_tableInstaller() {
64
  * @param (2) string,boolean
65
  * @return boolean
66
  */
67
- function wCreateTable($table="",$withcharset=true) {
68
- global $wpdb, $current_user, $wassupversion, $wassup_options;
69
 
70
  $wassup_table = (!empty($wassup_options->wassup_table))? $wassup_options->wassup_table: $wpdb->prefix . "wassup";
71
  $wassup_tmp_table = $wassup_table."_tmp";
72
  $wassup_meta_table = $wassup_table."_meta";
73
- if (empty($table)) $table_name = $wassup_table;
74
- else $table_name = $table;
75
  $is_new_table = false;
76
 
77
  //table builds should not be interrupted, so run in background in case of browser timeout
@@ -88,7 +89,7 @@ function wCreateTable($table="",$withcharset=true) {
88
  //...Set default character set and collation (on new table)
89
  $charset_collate = '';
90
  //Add charset on new table only
91
- if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") == $table_name) {
92
  $withcharset = false;
93
  } else {
94
  $is_new_table = true;
@@ -105,18 +106,18 @@ function wCreateTable($table="",$withcharset=true) {
105
  }
106
 
107
  //wassup table structure
108
- if ($table_name == $wassup_table || $table_name == $wassup_tmp_table) {
109
- $sql_createtable = "CREATE TABLE $table_name (
110
- `id` mediumint(9) NOT NULL auto_increment,
111
  `wassup_id` varchar(60) NOT NULL,
112
  `timestamp` varchar(20) NOT NULL,
113
- ip varchar(50) default NULL,
114
  `hostname` varchar(150) default NULL,
115
  `urlrequested` text,
116
  `agent` varchar(255) default NULL,
117
- `referrer` text default NULL,
118
  `search` varchar(255) default NULL,
119
- `searchpage` int(11) default 0,
120
  `os` varchar(15) default NULL,
121
  `browser` varchar(50) default NULL,
122
  `language` varchar(5) default NULL,
@@ -124,22 +125,22 @@ function wCreateTable($table="",$withcharset=true) {
124
  `searchengine` varchar(25) default NULL,
125
  `spider` varchar(50) default NULL,
126
  `feed` varchar(50) default NULL,
127
- `username` VARCHAR(50) default NULL,
128
- `comment_author` VARCHAR(50) default NULL,
129
- `spam` VARCHAR(5) default 0,
130
  `url_wpid` varchar(50) default NULL,
131
- UNIQUE KEY id (`id`),
132
- KEY idx_wassup (wassup_id(32),`timestamp`),
133
- INDEX (os),
134
- INDEX (browser),
135
- INDEX (`timestamp`)) {$charset_collate};";
136
  //Note: index (username,ip) was removed because of problems with
137
  // non-romanic language display
138
- //New in v.1.8: increased ip width to 50 for ipv6 support
139
 
140
  //...Include a first record if new table (not temp table)
141
  $sql_firstrecord = '';
142
- if ($table_name == $wassup_table && $is_new_table) {
143
  if (!class_exists('UADetector'))
144
  include_once (dirname(__FILE__) . '/lib/uadetector.class.php');
145
  $ua = new UADetector;
@@ -159,32 +160,39 @@ function wCreateTable($table="",$withcharset=true) {
159
  'http://www.wpwp.org', $ua->os,
160
  trim($ua->name.' '.$ua->majorVersion($ua->version)),
161
  $locale, $screen_res, $logged_user);
162
- }
163
 
164
  //...create/upgrade wassup table
165
- if (!empty($sql_firstrecord)) {
166
- $result = dbDelta(array($sql_createtable,$sql_firstrecord));
167
- } else {
 
 
 
168
  $result = dbDelta($sql_createtable);
 
 
169
  }
 
170
 
171
  //...return 'true' if table created successfully, false otherwise
172
  $retvalue=true;
173
- if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
174
 
175
  $retvalue=false;
176
  } else {
177
- if ($table == "" && version_compare(mysql_get_server_info(),'4.1.0','>')) {
178
  //'CREATE TABLE LIKE' syntax not supported in MySQL 4.1 or less
179
- $upgrade = dbDelta("CREATE TABLE $wassup_tmp_table LIKE {$wassup_table}");
 
180
  }
181
  }
182
  } //end if wassup_table
183
 
184
- //New in v1.8: "meta" table to extend wassup. Used as a temporary
185
  // data cache and can be used to capture additional visitor data
186
- if ($table == "") $table_name = $wassup_meta_table;
187
- if ($table_name == $wassup_meta_table) {
188
 
189
  // Wassup Meta Table Structure:
190
  // `wassup_key` can be either a foreign key for wp_wassup (contains
@@ -196,26 +204,27 @@ function wCreateTable($table="",$withcharset=true) {
196
  // serialized array.
197
  // `meta_expire` is a timestamp that is an expiration date in unix
198
  // timestamp format...for temporary/cache-only records.
199
- $sql_createtable_meta = "CREATE TABLE `$wassup_meta_table` (
200
  `meta_id` integer(15) unsigned auto_increment,
201
  `wassup_key` varchar(150) NOT NULL,
202
  `meta_key` varchar(80) NOT NULL,
203
  `meta_value` longtext,
204
  `meta_expire` integer(10) unsigned default '0',
205
- UNIQUE KEY (`meta_id`),
206
  INDEX (`wassup_key`),
207
- INDEX (`meta_key`)) {$charset_collate};";
208
 
209
  //create/upgrade wassup table
210
- $result = dbDelta($sql_createtable_meta);
 
211
 
212
  //...return 'false' if table was not created
213
- if ($table == $wassup_meta_table && $wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
214
  $retvalue=false;
215
  }
216
  } //end if wassup_meta_table
217
 
218
- return $retvalue;
219
  //#TODO:
220
  // 1. create stored procedure that selects records by timestamp
221
  // 2. create table views, 'wassup_hourly', 'wassup_weekly', 'wassup_monthly' as subsets of 'wp_wassup' for hourly hits, daily hits, weekly hits...
@@ -237,6 +246,7 @@ function wUpdateTable() {
237
  $wassup_table = (!empty($wassup_options->wassup_table))? $wassup_options->wassup_table: $wpdb->prefix . "wassup";
238
  $wassup_tmp_table = $wassup_table."_tmp";
239
  $wassup_meta_table = $wassup_table."_meta";
 
240
 
241
  //queue table content upgrades
242
  //For upgrade to v1.8: fix incorrect OS "win2008" (="win7")
@@ -250,87 +260,150 @@ function wUpdateTable() {
250
  //increase mysql session timeout to 3 minutes for upgrade
251
  $wpdb->query("SET wait_timeout = 180");
252
 
253
- //do table content upgrade
254
- if (!empty($upgrade_sql)) {
255
- wassup_scheduled_dbtask($upgrade_sql);
256
- }
257
 
258
- // For all upgrades: Drop and re-create all indices except 'id'
259
- //# get list of all wassup indices
260
- $qryresult = mysql_query("SHOW INDEX FROM {$wassup_table}");
261
- if ($qryresult) {
262
- $row_count = mysql_num_rows($qryresult);
263
- } else {
264
- $row_count = 0;
265
- }
266
- //# get the names of all indices
267
- $idx_names = array();
268
- $prev_key = ""; //names listed multiples times per columns in key
269
- if ($row_count > 1) {
270
- while ($row = mysql_fetch_array($qryresult,MYSQL_ASSOC)) {
271
- if ($row["Column_name"] != "id" && $row["Key_name"] != $prev_key) {
272
- $idx_names[] = $row["Key_name"];
 
 
 
273
  }
274
- $prev_key = $row["Key_name"];
275
  } //end while
276
- } //end if row_count
277
- mysql_free_result($qryresult);
278
- //# drop all the indices in $idx_names and drop temp table...
279
- //drop indices
280
- foreach ($idx_names AS $idx_drop) {
281
- mysql_query("DROP INDEX $idx_drop ON {$wassup_table}");
 
 
282
  }
283
 
284
  //NOTE: All column updates replaced by single call to 'wcreateTable' function which uses 'dbDelta' to update table structure
285
 
286
- //## For all upgrades
287
- //# Drop and re-create all indices except 'id'
288
- //Get list of all wp_wassup indices...
289
- //$idx_cols = $wpdb->get_col("SHOW INDEX FROM $wassup_table","Column_name"); //doesn't work
290
- $qryresult = mysql_query("SHOW INDEX FROM {$wassup_table}");
291
- if ($qryresult) {
292
- $row_count = mysql_num_rows($qryresult);
293
- } else {
294
- $row_count = 0;
295
- }
296
- //store names of all indices in an array...
297
- $idx_names = array();
298
- $prev_key = ""; //names listed multiples times per columns in key
299
- if ($row_count > 1) {
300
- while ($row = mysql_fetch_array($qryresult,MYSQL_ASSOC)) {
301
- if ($row["Column_name"] != "id" && $row["Key_name"] != $prev_key) {
302
- $idx_names[] = $row["Key_name"];
303
- }
304
- $prev_key = $row["Key_name"];
305
- } //end while
306
- } //end if row_count
307
- mysql_free_result($qryresult);
308
- //drop indices in array...
309
- foreach ($idx_names AS $idx_drop) {
310
- mysql_query("DROP INDEX $idx_drop ON {$wassup_table}");
311
- }
312
  // drop wp_wassup_tmp table...
313
  //$wpdb->query("DROP TABLE IF EXISTS $table_tmp_name"); //incorrectly causes an activation error in Wordpress
314
- mysql_query("DROP TABLE IF EXISTS $wassup_tmp_table");
315
 
316
  //call 'wCreateTable' to update tables structure and rebuild indices using wordpress' 'dbdelta' function...
317
- $success=wCreateTable();
 
318
 
319
- //build secondary tables, in case failed
320
- if ($wpdb->get_var("SHOW TABLES LIKE '$wassup_tmp_table'") != $wassup_tmp_table) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
  wCreateTable($wassup_tmp_table,false);
322
  }
323
- if ($wpdb->get_var("SHOW TABLES LIKE '$wassup_meta_table'") != $wassup_meta_table) {
324
  wCreateTable($wassup_meta_table,false);
325
  }
326
 
327
- if ($wpdb->get_var("SHOW TABLES LIKE '$wassup_table'") == $wassup_table) {
328
- //table upgrade warning error
329
- return true;
330
- } else {
331
- //table upgrade fatal error
332
- return false;
 
 
 
333
  }
 
334
  } //end function wUpdateTable
335
 
336
  /**
@@ -350,7 +423,7 @@ function wassup_compatCheck($item_to_check) {
350
  if (!file_exists($footer_file)) $footer_file = TEMPLATEPATH."/footer.php";
351
  if (file_exists($footer_file)) {
352
  $footer = file_get_contents($footer_file);
353
- //Note: Commented out 'wp_footer()' calls will match as true in test below...should be skipped
354
  if (stristr($footer,'wp_footer(')!==false || stristr($footer,'wp_footer (')!==false) $result=true;
355
  else $result=false;
356
  } else {
6
  /**
7
  * Contains functions to create and update the tables required for WassUp
8
  * install and upgrade. These functions are loaded only when plugin is
9
+ * activated through the 'wassup_install' hook function.
10
  * @since version 1.8
11
  * @author Helene D.
12
  */
13
 
14
  /**
15
  * Table install manager function that calls either 'wCreateTable' or
16
+ * 'wUpdateTable' depending on whether this is a new install or an upgrade.
17
  * @param none
18
  * @return boolean
19
  */
24
  $wassup_table = (!empty($wassup_options->wassup_table)? $wassup_options->wassup_table : $wpdb->prefix . "wassup");
25
  $wassup_tmp_table = $wassup_table."_tmp";
26
  $wassup_meta_table = $wassup_table."_meta";
27
+ $wcharset=true;
28
+ $wsuccess=false;
29
+ //$wpdb->show_errors = true;
30
 
31
+ //CREATE/UPGRADE table
32
+ if ($wpdb->get_var("SHOW TABLES LIKE '{$wassup_table}'") == $wassup_table) {
33
+ $wcharset=false;
34
+ $wsuccess=wUpdateTable(); //<== wassup_tmp is added here, if missing
35
+ } else {
36
  if (wCreateTable()) { //1st attempt
37
+ $wcharset=true;
38
  }
39
  //2nd attempt: no character set in table
40
+ if ($wpdb->get_var("SHOW TABLES LIKE '{$wassup_table}'") != $wassup_table) {
41
+ $wcharset=false;
42
+ wCreateTable("",$wcharset);
43
  }
44
 
 
 
 
 
45
  }
46
 
47
  //check that install was successful, issue warnings, start tracker
48
+ if ($wsuccess || $wpdb->get_var("SHOW TABLES LIKE '{$wassup_table}' ") == $wassup_table) {
49
+ $wsuccess=true;
50
  //double-check that temp and meta were created
51
+ if ($wpdb->get_var("SHOW TABLES LIKE '{$wassup_tmp_table}' ") != $wassup_tmp_table) {
52
+ wCreateTable($wassup_tmp_table,$wcharset);
53
  }
54
+ if ($wpdb->get_var("SHOW TABLES LIKE '{$wassup_meta_table}' ") != $wassup_meta_table) {
55
+ wCreateTable($wassup_meta_table,$wcharset);
56
  }
57
  }
58
+ //$wpdb->show_errors = false;
59
+ return($wsuccess);
60
  } //#end function wassup_tableInstaller
61
 
62
  /**
65
  * @param (2) string,boolean
66
  * @return boolean
67
  */
68
+ function wCreateTable($wtable="",$withcharset=true) {
69
+ global $wpdb, $current_user, $wp_version, $wassupversion, $wassup_options;
70
 
71
  $wassup_table = (!empty($wassup_options->wassup_table))? $wassup_options->wassup_table: $wpdb->prefix . "wassup";
72
  $wassup_tmp_table = $wassup_table."_tmp";
73
  $wassup_meta_table = $wassup_table."_meta";
74
+ if (empty($wtable)) $wtable_name = $wassup_table;
75
+ else $wtable_name = $wtable;
76
  $is_new_table = false;
77
 
78
  //table builds should not be interrupted, so run in background in case of browser timeout
89
  //...Set default character set and collation (on new table)
90
  $charset_collate = '';
91
  //Add charset on new table only
92
+ if ($wpdb->get_var("SHOW TABLES LIKE '{$wtable_name}'") == $wtable_name) {
93
  $withcharset = false;
94
  } else {
95
  $is_new_table = true;
106
  }
107
 
108
  //wassup table structure
109
+ if ($wtable_name == $wassup_table || $wtable_name == $wassup_tmp_table) {
110
+ $sql_createtable = "CREATE TABLE $wtable_name (
111
+ `id` mediumint(9) unsigned NOT NULL auto_increment,
112
  `wassup_id` varchar(60) NOT NULL,
113
  `timestamp` varchar(20) NOT NULL,
114
+ `ip` varchar(50) default NULL,
115
  `hostname` varchar(150) default NULL,
116
  `urlrequested` text,
117
  `agent` varchar(255) default NULL,
118
+ `referrer` text,
119
  `search` varchar(255) default NULL,
120
+ `searchpage` int(11) unsigned default '0',
121
  `os` varchar(15) default NULL,
122
  `browser` varchar(50) default NULL,
123
  `language` varchar(5) default NULL,
125
  `searchengine` varchar(25) default NULL,
126
  `spider` varchar(50) default NULL,
127
  `feed` varchar(50) default NULL,
128
+ `username` varchar(50) default NULL,
129
+ `comment_author` varchar(50) default NULL,
130
+ `spam` varchar(5) default '0',
131
  `url_wpid` varchar(50) default NULL,
132
+ UNIQUE KEY `id` (`id`),
133
+ KEY `idx_wassup` (`wassup_id`(32),`timestamp`),
134
+ INDEX (`os`),
135
+ INDEX (`browser`),
136
+ INDEX `timestamp` (`timestamp`)) {$charset_collate};";
137
  //Note: index (username,ip) was removed because of problems with
138
  // non-romanic language display
139
+ //Since v1.8: increased ip width to 50 for ipv6 support
140
 
141
  //...Include a first record if new table (not temp table)
142
  $sql_firstrecord = '';
143
+ if ($wtable_name == $wassup_table && $is_new_table) {
144
  if (!class_exists('UADetector'))
145
  include_once (dirname(__FILE__) . '/lib/uadetector.class.php');
146
  $ua = new UADetector;
160
  'http://www.wpwp.org', $ua->os,
161
  trim($ua->name.' '.$ua->majorVersion($ua->version)),
162
  $locale, $screen_res, $logged_user);
163
+ } // end if wassup && is_new_table
164
 
165
  //...create/upgrade wassup table
166
+
167
+ //New in 1.8.3: Don't use Wordpress' "dbdelta" function on
168
+ // pre-existing "wp_wassup" table because "dbDelta" fails to
169
+ // upgrade wp_wassup's large table structure in Wordpress 3.1+
170
+ // (throws MySQL ALTER TABLE error).
171
+ if ($wtable_name != $wassup_table) {
172
  $result = dbDelta($sql_createtable);
173
+ } elseif (!empty($sql_firstrecord)) {
174
+ $result = dbDelta(array($sql_createtable,$sql_firstrecord));
175
  }
176
+ //$wpdb->print_error(); //debug
177
 
178
  //...return 'true' if table created successfully, false otherwise
179
  $retvalue=true;
180
+ if ($wpdb->get_var("SHOW TABLES LIKE '{$wtable_name}'") != $wtable_name) {
181
 
182
  $retvalue=false;
183
  } else {
184
+ if ($wtable == "" && version_compare(mysql_get_server_info(),'4.1.0','>')) {
185
  //'CREATE TABLE LIKE' syntax not supported in MySQL 4.1 or less
186
+ $wupgrade = dbDelta("CREATE TABLE $wassup_tmp_table LIKE {$wassup_table}");
187
+ //$wpdb->print_error(); //debug
188
  }
189
  }
190
  } //end if wassup_table
191
 
192
+ //Since v1.8: "meta" table to extend wassup. Used as a temporary
193
  // data cache and can be used to capture additional visitor data
194
+ if ($wtable == "") $wtable_name = $wassup_meta_table;
195
+ if ($wtable_name == $wassup_meta_table) {
196
 
197
  // Wassup Meta Table Structure:
198
  // `wassup_key` can be either a foreign key for wp_wassup (contains
204
  // serialized array.
205
  // `meta_expire` is a timestamp that is an expiration date in unix
206
  // timestamp format...for temporary/cache-only records.
207
+ $sql_create_meta = "CREATE TABLE `$wassup_meta_table` (
208
  `meta_id` integer(15) unsigned auto_increment,
209
  `wassup_key` varchar(150) NOT NULL,
210
  `meta_key` varchar(80) NOT NULL,
211
  `meta_value` longtext,
212
  `meta_expire` integer(10) unsigned default '0',
213
+ UNIQUE KEY meta_id (`meta_id`),
214
  INDEX (`wassup_key`),
215
+ INDEX (`meta_key`)) {$charset_collate}; ";
216
 
217
  //create/upgrade wassup table
218
+ $result = dbDelta($sql_create_meta);
219
+ //$wpdb->print_error(); //debug
220
 
221
  //...return 'false' if table was not created
222
+ if ($wtable == $wassup_meta_table && $wpdb->get_var("SHOW TABLES LIKE '{$wtable_name}'") != $wtable_name) {
223
  $retvalue=false;
224
  }
225
  } //end if wassup_meta_table
226
 
227
+ return($retvalue);
228
  //#TODO:
229
  // 1. create stored procedure that selects records by timestamp
230
  // 2. create table views, 'wassup_hourly', 'wassup_weekly', 'wassup_monthly' as subsets of 'wp_wassup' for hourly hits, daily hits, weekly hits...
246
  $wassup_table = (!empty($wassup_options->wassup_table))? $wassup_options->wassup_table: $wpdb->prefix . "wassup";
247
  $wassup_tmp_table = $wassup_table."_tmp";
248
  $wassup_meta_table = $wassup_table."_meta";
249
+ $wsuccess=true;
250
 
251
  //queue table content upgrades
252
  //For upgrade to v1.8: fix incorrect OS "win2008" (="win7")
260
  //increase mysql session timeout to 3 minutes for upgrade
261
  $wpdb->query("SET wait_timeout = 180");
262
 
263
+ //do table content upgrade - after table upgrade to avoid lockouts
264
+ //if (!empty($upgrade_sql)) {
265
+ // wassup_scheduled_dbtask($upgrade_sql);
266
+ //}
267
 
268
+ // For all upgrades: Drop and re-create all indices except 'id' and
269
+ // 'meta_id' on 'wp_wassup' and 'wp_wassup_meta' tables
270
+ $wtables = array("$wassup_table", "$wassup_meta_table");
271
+ foreach ($wtables AS $wtbl) {
272
+ //# get list of all wassup indices
273
+ $wqryresult = mysql_query("SHOW INDEX FROM `{$wtbl}`");
274
+ if ($wqryresult) {
275
+ $wrow_count = mysql_num_rows($wqryresult);
276
+ } else {
277
+ $wrow_count = 0;
278
+ }
279
+ //# get the names of all indices
280
+ $idx_names = array();
281
+ $prev_key = ""; //names listed multiples times per columns in key
282
+ if ($wrow_count > 1) {
283
+ while ($wrow = mysql_fetch_array($wqryresult,MYSQL_ASSOC)) {
284
+ if ($wrow["Column_name"]!= "id" && $wrow["Column_name"]!= "meta_id" && $wrow["Key_name"]!= $prev_key) {
285
+ $idx_names[] = $wrow["Key_name"];
286
  }
287
+ $prev_key = $wrow["Key_name"];
288
  } //end while
289
+ } //end if wrow_count
290
+ mysql_free_result($wqryresult);
291
+ //# drop all the indices in $idx_names and drop temp table...
292
+ //drop indices
293
+ foreach ($idx_names AS $idx_drop) {
294
+ mysql_query("DROP INDEX $idx_drop ON `{$wtbl}`");
295
+ }
296
+ unset ($wrow, $wrow_count, $prev_key, $idx_names);
297
  }
298
 
299
  //NOTE: All column updates replaced by single call to 'wcreateTable' function which uses 'dbDelta' to update table structure
300
 
301
+ ////## For all upgrades - redundant code
302
+ ////# Drop and re-create all indices except 'id'
303
+ ////Get list of all wp_wassup indices...
304
+ ////$idx_cols = $wpdb->get_col("SHOW INDEX FROM $wassup_table","Column_name"); //doesn't work
305
+ //$qryresult = mysql_query("SHOW INDEX FROM {$wassup_table}");
306
+ //if ($qryresult) {
307
+ // $row_count = mysql_num_rows($qryresult);
308
+ //} else {
309
+ // $row_count = 0;
310
+ //}
311
+ ////store names of all indices in an array...
312
+ //$idx_names = array();
313
+ //$prev_key = ""; //names listed multiples times per columns in key
314
+ //if ($row_count > 1) {
315
+ // while ($row = mysql_fetch_array($qryresult,MYSQL_ASSOC)) {
316
+ // if ($row["Column_name"] != "id" && $row["Key_name"] != $prev_key) {
317
+ // $idx_names[] = $row["Key_name"];
318
+ // }
319
+ // $prev_key = $row["Key_name"];
320
+ // } //end while
321
+ //} //end if row_count
322
+ //mysql_free_result($qryresult);
323
+ ////drop indices in array...
324
+ //foreach ($idx_names AS $idx_drop) {
325
+ // mysql_query("DROP INDEX $idx_drop ON {$wassup_table}");
326
+ //}
327
  // drop wp_wassup_tmp table...
328
  //$wpdb->query("DROP TABLE IF EXISTS $table_tmp_name"); //incorrectly causes an activation error in Wordpress
329
+ mysql_query("DROP TABLE IF EXISTS `{$wassup_tmp_table}`");
330
 
331
  //call 'wCreateTable' to update tables structure and rebuild indices using wordpress' 'dbdelta' function...
332
+ //NOTE: 'wcreateTable' no longer upgrades "wp_wassup" table since v.1.8.3
333
+ $wsuccess=wCreateTable();
334
 
335
+ //New in 1.8.3: 'wCreateTable' and 'dbdelta' workaround code
336
+ // Since Wordpress 3.1, Wordpress' "dbDelta" function fails to
337
+ // upgrade "wp_wassup" table structure (throws MySQL ALTER TABLE
338
+ // error). To work around this problem, restored column-by-column
339
+ // upgrades from earlier versions of WassUp (pre 1.7) and restored
340
+ // manual index rebuilds.
341
+
342
+ //upgrades for version 1.7 or less
343
+ if (empty($wassup_options->wassup_version) OR version_compare($wassup_options->wassup_version,"1.7","<")) {
344
+ // Upgrade from version < 1.3.9 - add 'spam' field to wassup table
345
+ if ($wpdb->get_var("SHOW COLUMNS FROM $wassup_table LIKE 'spam'") == "") {
346
+ $wpdb->query("ALTER TABLE {$wassup_table} ADD COLUMN spam VARCHAR(5) DEFAULT '0'");
347
+ }
348
+
349
+ // Upgrade from version <= 1.5.1 - increase 'wassup_id' size
350
+ $wassup_col = $wpdb->get_results("SHOW COLUMNS FROM $wassup_table LIKE 'wassup_id'");
351
+ foreach ($wassup_col as $wID) {
352
+ if ($wID->Type != "varchar(60)") {
353
+ $wpdb->query("ALTER TABLE {$wassup_table} CHANGE COLUMN wassup_id wassup_id varchar(60) DEFAULT NULL");
354
+ }
355
+ }
356
+ // - increase size of 'searchengine' and 'spider' fields
357
+ $col_size = $wpdb->get_results("SHOW COLUMNS FROM $wassup_table LIKE 'searchengine'");
358
+ foreach ($col_size as $wCol) {
359
+ if ($wCol->Type != "varchar(25)") {
360
+ $wpdb->query("ALTER TABLE {$wassup_table} CHANGE COLUMN searchengine searchengine varchar(25) DEFAULT NULL");
361
+ }
362
+ }
363
+ $col_size = $wpdb->get_results("SHOW COLUMNS FROM $wassup_table LIKE 'spider'");
364
+ foreach ($col_size as $wCol) {
365
+ if ($wCol->Type != "varchar(50)") {
366
+ $wpdb->query("ALTER TABLE {$wassup_table} CHANGE COLUMN spider spider varchar(50) DEFAULT NULL");
367
+ }
368
+ }
369
+ } //end if wassup_version
370
+ //upgrades for versions 1.7 thru 1.8.2
371
+ if (empty($wassup_options->wassup_version) OR version_compare($wassup_options->wassup_version,"1.8.3","<")) {
372
+ //Since v1.8: add new field 'url_wpid' for post_id tracking
373
+ if ($wpdb->get_var("SHOW COLUMNS FROM $wassup_table LIKE 'url_wpid'") == "") {
374
+ $wpdb->query("ALTER TABLE {$wassup_table} ADD COLUMN url_wpid varchar(50) DEFAULT NULL");
375
+ }
376
+ //Since v1.8: increase size of 'ip' field for IPv6 addresses
377
+ $wpdb->query("ALTER TABLE {$wassup_table} CHANGE COLUMN ip `ip` varchar(50) DEFAULT NULL");
378
+ }
379
+ //TODO: show an upgrade warning error when table structure is not updated
380
+ //rebuild indices on 'wp_wassup' - this also optimizes
381
+ //...could take a long time, so run in background in case of timeout
382
+ ignore_user_abort(1);
383
+ $wpdb->query("ALTER TABLE {$wassup_table} ADD KEY idx_wassup (wassup_id(32),`timestamp`)");
384
+ $wpdb->query("ALTER TABLE {$wassup_table} ADD INDEX (os)");
385
+ $wpdb->query("ALTER TABLE {$wassup_table} ADD INDEX (browser)");
386
+ $wpdb->query("ALTER TABLE {$wassup_table} ADD INDEX (`timestamp`)");
387
+
388
+ //build secondary tables, in case upgrade failed in 'wCreateTable'
389
+ if ($wpdb->get_var("SHOW TABLES LIKE '{$wassup_tmp_table}'") != $wassup_tmp_table) {
390
  wCreateTable($wassup_tmp_table,false);
391
  }
392
+ if ($wpdb->get_var("SHOW TABLES LIKE '{$wassup_meta_table}'") != $wassup_meta_table) {
393
  wCreateTable($wassup_meta_table,false);
394
  }
395
 
396
+ if ($wsuccess || $wpdb->get_var("SHOW TABLES LIKE '{$wassup_table}'") == $wassup_table) {
397
+ $wsuccess=true;
398
+ }
399
+
400
+ //lastly do table content upgrade, if any
401
+ if ($wsuccess) {
402
+ if (!empty($upgrade_sql)) {
403
+ wassup_scheduled_dbtask($upgrade_sql);
404
+ }
405
  }
406
+ return($wsuccess);
407
  } //end function wUpdateTable
408
 
409
  /**
423
  if (!file_exists($footer_file)) $footer_file = TEMPLATEPATH."/footer.php";
424
  if (file_exists($footer_file)) {
425
  $footer = file_get_contents($footer_file);
426
+ //Note: if 'wp_footer()' is commented-out in template code, it will still match as true in test below
427
  if (stristr($footer,'wp_footer(')!==false || stristr($footer,'wp_footer (')!==false) $result=true;
428
  else $result=false;
429
  } else {
lib/wassup.class.php CHANGED
@@ -10,7 +10,7 @@ if (!class_exists('wassupOptions')) {
10
  * Contains variables and methods used to set or change wassup
11
  * settings in Wordpress' wp_options table and to output those
12
  * values for use in forms.
13
- * @author: Helene Duncker. 2/24/08, 6/21/09, 2009-11-15
14
  */
15
  class wassupOptions {
16
  /* general/detail settings */
@@ -21,12 +21,13 @@ class wassupOptions {
21
  var $wassup_default_type = "";
22
  var $wassup_default_spy_type = "";
23
  var $wassup_default_limit = "10";
24
- var $wassup_top10 ; //array containg top ten preferences
25
  var $wassup_dashboard_chart;
26
  var $wassup_geoip_map;
27
  var $wassup_googlemaps_key;
 
28
  var $wassup_time_format;
29
- var $wassup_time_period; //new in 1.8 - for visitor details default date/time range
30
 
31
  /* recording settings */
32
  var $wassup_active = "1";
@@ -45,9 +46,9 @@ class wassupOptions {
45
  var $wassup_refspam;
46
 
47
  /* table/file management settings */
48
- //var $wassup_savepath; //deprecated
49
  var $delete_auto;
50
- var $delete_filter; //new in 1.8 for deleting select records
51
  var $wassup_remind_mb;
52
  var $wassup_remind_flag;
53
  var $wassup_uninstall; //for complete uninstall of wassup
@@ -55,7 +56,7 @@ class wassupOptions {
55
  var $wassup_version; //since 1.7 - revision# for wassup updates
56
  var $wassup_table; //since 1.7.2 - WassUp table name
57
  var $wassup_dbengine; //since 1.7.2 - MySQL table engine type
58
- var $wassup_cache; //new in 1.8 for using wassup_meta table as cache
59
 
60
  /* chart display settings */
61
  var $wassup_chart;
@@ -77,7 +78,7 @@ class wassupOptions {
77
  var $wassup_widget_chars;
78
 
79
  /* temporary action settings */
80
- var $wassup_alert_message; //used to display alerts
81
  var $wmark;
82
  var $wip;
83
  var $whash = ""; //wp_hash value used by action.php
@@ -101,8 +102,19 @@ class wassupOptions {
101
  * @param none
102
  * @return array
103
  */
104
- function defaultSettings() {
105
  global $wpdb;
 
 
 
 
 
 
 
 
 
 
 
106
  $defaults = array(
107
  'wassup_active' =>"1",
108
  'wassup_loggedin' =>"1",
@@ -132,6 +144,7 @@ class wassupOptions {
132
  'wassup_dashboard_chart'=>"0",
133
  'wassup_geoip_map' =>"0",
134
  'wassup_googlemaps_key' =>"",
 
135
  'wassup_time_format' =>"24",
136
  'wassup_time_period' =>"1",
137
  'wassup_widget_title' =>"Visitors Online",
@@ -150,17 +163,17 @@ class wassupOptions {
150
  'wassup_alert_message' =>"",
151
  'wassup_uninstall' =>"0",
152
  'wassup_optimize' =>current_time('timestamp'),
153
- 'wassup_top10' =>attribute_escape(serialize(array(
154
- "topsearch"=>"1",
155
- "topreferrer"=>"1",
156
- "toprequest"=>"1",
157
- "topbrowser"=>"1",
158
- "topos"=>"1",
159
- "toplocale"=>"0",
160
- "topvisitor"=>"0",
161
- "topfeed"=>"0",
162
- "topcrawler"=>"0",
163
- "topreferrer_exclude"=>""))),
164
  'whash' =>$this->get_wp_hash(),
165
  'wassup_version'=>"",
166
  'wassup_table' =>$wpdb->prefix . "wassup",
@@ -177,7 +190,18 @@ class wassupOptions {
177
  if (!empty($this->wassup_table)) {
178
  $defaults['wassup_table']= $this->wassup_table;
179
  }
180
- return $defaults;
 
 
 
 
 
 
 
 
 
 
 
181
  } //end defaultSettings
182
 
183
  //#Load class variables with array parameter or current options
10
  * Contains variables and methods used to set or change wassup
11
  * settings in Wordpress' wp_options table and to output those
12
  * values for use in forms.
13
+ * @author: Helene Duncker. 2/24/08, 6/21/09, 2009-11-15, 2011-04-17
14
  */
15
  class wassupOptions {
16
  /* general/detail settings */
21
  var $wassup_default_type = "";
22
  var $wassup_default_spy_type = "";
23
  var $wassup_default_limit = "10";
24
+ var $wassup_top10 ; //array containg top stats preferences
25
  var $wassup_dashboard_chart;
26
  var $wassup_geoip_map;
27
  var $wassup_googlemaps_key;
28
+ var $wassup_spy_speed = "5000"; //New in 1.8.3
29
  var $wassup_time_format;
30
+ var $wassup_time_period; //since 1.8 - visitor details default range
31
 
32
  /* recording settings */
33
  var $wassup_active = "1";
46
  var $wassup_refspam;
47
 
48
  /* table/file management settings */
49
+ //var $wassup_savepath; //deprecated
50
  var $delete_auto;
51
+ var $delete_filter; //since 1.8 - auto delete select records
52
  var $wassup_remind_mb;
53
  var $wassup_remind_flag;
54
  var $wassup_uninstall; //for complete uninstall of wassup
56
  var $wassup_version; //since 1.7 - revision# for wassup updates
57
  var $wassup_table; //since 1.7.2 - WassUp table name
58
  var $wassup_dbengine; //since 1.7.2 - MySQL table engine type
59
+ var $wassup_cache; //since 1.8 - use wassup_meta table as cache
60
 
61
  /* chart display settings */
62
  var $wassup_chart;
78
  var $wassup_widget_chars;
79
 
80
  /* temporary action settings */
81
+ var $wassup_alert_message; //to display alerts
82
  var $wmark;
83
  var $wip;
84
  var $whash = ""; //wp_hash value used by action.php
102
  * @param none
103
  * @return array
104
  */
105
+ function defaultSettings($dsetting="") {
106
  global $wpdb;
107
+ $top10 = array( "toplimit"=>"10", //new in 1.8.3 - top stats list size
108
+ "topsearch"=>"1",
109
+ "topreferrer"=>"1",
110
+ "toprequest"=>"1",
111
+ "topbrowser"=>"1",
112
+ "topos"=>"1",
113
+ "toplocale"=>"0",
114
+ "topvisitor"=>"0",
115
+ "toppostid"=>"0", //new in v1.8.3 - top article by post-id
116
+ "topreferrer_exclude"=>"",
117
+ "top_nospider"=>"0"); //new in v1.8.3 - exclude spiders from top stats
118
  $defaults = array(
119
  'wassup_active' =>"1",
120
  'wassup_loggedin' =>"1",
144
  'wassup_dashboard_chart'=>"0",
145
  'wassup_geoip_map' =>"0",
146
  'wassup_googlemaps_key' =>"",
147
+ 'wassup_spy_speed' =>"5000",
148
  'wassup_time_format' =>"24",
149
  'wassup_time_period' =>"1",
150
  'wassup_widget_title' =>"Visitors Online",
163
  'wassup_alert_message' =>"",
164
  'wassup_uninstall' =>"0",
165
  'wassup_optimize' =>current_time('timestamp'),
166
+ 'wassup_top10' =>attribute_escape(serialize($top10)),
167
+ // "topsearch"=>"1", - moved
168
+ // "topreferrer"=>"1", - moved
169
+ // "toprequest"=>"1", - moved
170
+ // "topbrowser"=>"1", - moved
171
+ // "topos"=>"1", - moved
172
+ // "toplocale"=>"0", - moved
173
+ // "topvisitor"=>"0", - moved
174
+ // "topfeed"=>"0", - moved
175
+ // "topcrawler"=>"0", - moved
176
+ // "topreferrer_exclude"=>""))), - moved
177
  'whash' =>$this->get_wp_hash(),
178
  'wassup_version'=>"",
179
  'wassup_table' =>$wpdb->prefix . "wassup",
190
  if (!empty($this->wassup_table)) {
191
  $defaults['wassup_table']= $this->wassup_table;
192
  }
193
+ //New in 1.8.3: return a single default value when function argument given
194
+ if (!empty($dsetting)) {
195
+ if ($dsetting == "top10" || $dsetting == "wassup_top10" || $dsetting == "top_stats") {
196
+ return ($top10);
197
+ } elseif (!empty($defaults[$dsetting])) {
198
+ return ($defaults[$dsetting]);
199
+ } else {
200
+ return (null);
201
+ }
202
+ } else {
203
+ return($defaults);
204
+ };
205
  } //end defaultSettings
206
 
207
  //#Load class variables with array parameter or current options
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=michele%
4
  Tags: tracker, tracking, statistics, analyze, web, realtime, stats, ajax, visitors, visits, online users, details, seo, admin, spy, visitors, widgets, widget, sidebar, monitor, stalker, detector, webmaster, tool, geolocation, chart, google!charts, spammers, exploits, injection, security, useragent, browser, spider, detection, pageviews
5
  Requires at least: 2.2
6
  Tested up to: 3.2.1
7
- Stable tag: 1.8.2
8
 
9
  Analyze your visitors traffic with real-time statistics, a lot of chronological information, charts, a sidebar widget.
10
 
@@ -72,16 +72,19 @@ IMPORTANT: WassUp is incompatible with page-based caching plugins such as "WP Su
72
  == Frequently Asked Questions ==
73
 
74
  = How do I add WassUp's chart to my admin dashboard? =
75
- Go to Wassup >> Options submenu, select [General Setup] tab and check "Display small chart in dashboard", then click [Save Settings] button.
76
 
77
  = My Wordpress theme is not widget ready. Is it possible to add WassUp Widget to my site? =
78
  Yes. Simply insert the template tag, "wassup_sidebar()", into your theme's "sidebar.php" file.
79
 
80
  = How do I exclude a visitor from being recorded? =
81
- Go to Wassup >> Options, select [Statistics Recording] tab and enter the IP address or username to be excluded in the appropriate text area.
82
 
83
  = How do I stop (temporarily) WassUp from recording new visits on my site? =
84
- Go to Wassup >> Options, select [Statistics Recording] tab and uncheck "Enable/disable recording", then click [Save Settings] button.
 
 
 
85
 
86
  = Can Wassup record visits on a web site that is not Wordpress? =
87
  No. Wassup is a Wordpress-only plugin and requires at least Wordpress 2.2 to work.
@@ -92,11 +95,11 @@ WassUp is incompatible with WP Supercache, WP Cache, Hyper Cache, or any page-ba
92
  = Is there any caching plugin that works with WassUp? =
93
  [WP Widget Cache](http://wordpress.org/extend/plugins/wp-widget-cache/) is the only caching plugin verified to work with WassUp. However, some WassUp users have reported success using [DB Cache Reloaded](http://wordpress.org/extend/plugins/db-cache-reloaded/) and [Quick Cache](http://wordpress.org/extend/plugins/quick-cache/) plugins with WassUp.
94
 
95
- = Why does WassUp stats show more page views than actual pages clicked by a user? =
96
  "Phantom" page views can occur when a user's browser does automatic feed retrieval, link pre-fetching, or a page refresh. WassUp tracks these because they are valid requests from that user's browser and are indistinguishable from user link clicks.
97
 
98
  = How do I uninstall WassUp? =
99
- To completely remove WassUp's settings and tables from Wordpress, go to Wassup >> Wassup-Options, select [Uninstall] tab, check the "Uninstall" box, click the "[Save Settings]" button, then deactivate WassUp in "Plugins".
100
 
101
  Visit [http://www.wpwp.org](http://trac.wpwp.org/wiki/Documentation) for more FAQs.
102
 
@@ -141,23 +144,37 @@ IMPORTANT: WassUp is incompatible with page-based caching plugins such as "WP Su
141
 
142
  == Changelog ==
143
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  = 1.8.2 =
145
  = Urgent bugfix, compatibility and feature improvement upgrade =
146
- * fixed regex bug that caused a `preg.match` compilation warning error to display in some configurations.
147
- * fixed a typo in `wassup_install` function and updated code to suppress warning errors when 1st table install attempt fails.
148
- * added a javascript cookie to footer function for better screen resolution tracking in IE.
149
- * added 'Google Web Preview' snapshot bot to list of known spiders.
150
- * added code to detect faked referrer strings.
151
- * added new referrer spammers and removed obsolete domains from spammer lists.
152
- * added validity check to refresh timer to limit user input range to between 0 and 180 minutes (3 hours). An input value of 0 disables the timer.
153
- * improved search engine/search phrase detection.
154
- * improved namespace compatibility with other plugins.
155
  * miscellaneous minor code and style changes.
156
 
157
  = 1.8.1 =
158
  = Urgent bugfix and code improvement upgrade =
159
  * fixed bug that caused `set_time_limit` and other warning errors to display to visitors.
160
- * improved upgrade instructions in `readme.txt`.
161
  * miscellaneous minor code changes.
162
 
163
  = 1.8 =
@@ -188,12 +205,12 @@ IMPORTANT: WassUp is incompatible with page-based caching plugins such as "WP Su
188
  ...
189
  == Upgrade Notice ==
190
 
191
- = 1.8.2 =
192
- * Urgent bug fix and feature improvement upgrade. Required for WassUp 1.8+ users. Read plugin install instructions for important upgrade information.
193
 
194
  == Infos ==
195
 
196
  You could find every informations and much more at [http://www.wpwp.org](http://www.wpwp.org) - [http://trac.wpwp.org](http://trac.wpwp.org/wiki/Documentation) - [http://www.wpwp.org/forums](http://www.wpwp.org/forums/)
197
 
198
- Credits to: [Jquery](http://www.jquery.com) for the amazing Ajax framework, [FAMFAMFAM](http://www.famfamfam.com/) for the flags icons and a big thanks to [Helene D.](http://www.techfromhel.com/) for her help to improve WassUp!
199
 
4
  Tags: tracker, tracking, statistics, analyze, web, realtime, stats, ajax, visitors, visits, online users, details, seo, admin, spy, visitors, widgets, widget, sidebar, monitor, stalker, detector, webmaster, tool, geolocation, chart, google!charts, spammers, exploits, injection, security, useragent, browser, spider, detection, pageviews
5
  Requires at least: 2.2
6
  Tested up to: 3.2.1
7
+ Stable tag: 1.8.3
8
 
9
  Analyze your visitors traffic with real-time statistics, a lot of chronological information, charts, a sidebar widget.
10
 
72
  == Frequently Asked Questions ==
73
 
74
  = How do I add WassUp's chart to my admin dashboard? =
75
+ Enable the dashboard chart in WassUp's settings. Go to Wassup >> Options >> [General Setup] tab and check "Display small chart in dashboard", then click [Save Settings] button.
76
 
77
  = My Wordpress theme is not widget ready. Is it possible to add WassUp Widget to my site? =
78
  Yes. Simply insert the template tag, "wassup_sidebar()", into your theme's "sidebar.php" file.
79
 
80
  = How do I exclude a visitor from being recorded? =
81
+ Add a username or IP to WassUp's recording exclusion settings. Go to Wassup >> Options >> [Statistics Recording] tab and enter the IP address or username to be excluded in the appropriate text area.
82
 
83
  = How do I stop (temporarily) WassUp from recording new visits on my site? =
84
+ Disable recording in WassUp's settings. Go to Wassup >> Options >> [Statistics Recording] tab and uncheck "Enable/disable recording", then click [Save Settings] button.
85
+
86
+ = My popular web site is hosted on a shared server that has database size limits. How do I make sure that WassUp's table size never goes over my allotted quota? =
87
+ Change WassUp's settings to enable "auto delete" of old records and to set a warning notice to be emailed to you when WassUp's table growth exceeds a preset size limit. Go to Wassup >> Options >> [Manage Files & Database] tab to enable these settings.
88
 
89
  = Can Wassup record visits on a web site that is not Wordpress? =
90
  No. Wassup is a Wordpress-only plugin and requires at least Wordpress 2.2 to work.
95
  = Is there any caching plugin that works with WassUp? =
96
  [WP Widget Cache](http://wordpress.org/extend/plugins/wp-widget-cache/) is the only caching plugin verified to work with WassUp. However, some WassUp users have reported success using [DB Cache Reloaded](http://wordpress.org/extend/plugins/db-cache-reloaded/) and [Quick Cache](http://wordpress.org/extend/plugins/quick-cache/) plugins with WassUp.
97
 
98
+ = Why does WassUp stats sometimes show more page views than actual pages clicked by a user? =
99
  "Phantom" page views can occur when a user's browser does automatic feed retrieval, link pre-fetching, or a page refresh. WassUp tracks these because they are valid requests from that user's browser and are indistinguishable from user link clicks.
100
 
101
  = How do I uninstall WassUp? =
102
+ To completely remove WassUp's settings and tables from Wordpress, go to Wassup >> Options >> [Uninstall] tab, check the "Uninstall" box, click the "[Save Settings]" button, then deactivate WassUp in "Plugins".
103
 
104
  Visit [http://www.wpwp.org](http://trac.wpwp.org/wiki/Documentation) for more FAQs.
105
 
144
 
145
  == Changelog ==
146
 
147
+ = 1.8.3 =
148
+ = Urgent bugfix, compatibility, and feature improvement upgrade =
149
+ * fixed typo that caused a php "foreach" error in v.1.8.2.
150
+ * fixed table upgrade function to prevent errors that can cause activation failure.
151
+ * new "Top Stats" settings for improved statistics:
152
+ * 1. list length - an input field to customize "top stats" list length size
153
+ * 1. "Top Articles" - a top stats selection to display the most popular articles (posts and pages) by post title, and
154
+ * 1. "exclude spiders" - a checkbox option to exclude all spiders from top stats.
155
+ * new option for manual adjust of SPY data speed.
156
+ * improved tracking of logged-in users.
157
+ * improved detection of referrer spammers and faked referrer strings.
158
+ * improved detection of spiders, mobile browsers and google chrome.
159
+ * improved search engine and search phrase detection.
160
+ * improved namespace compatibility with other Wordpress plugins.
161
+ * updated jQuery library to v.1.6.4 and jqueryUI library to v.1.8.16
162
+ * miscellaneous minor code and style changes.
163
+
164
  = 1.8.2 =
165
  = Urgent bugfix, compatibility and feature improvement upgrade =
166
+ * fixed a regex bug that caused a `preg.match` compilation warning in some configurations.
167
+ * fixed a typo in `wassup_install` function that caused plugin activation to fail in some configurations.
168
+ * updated refresh timer to have a range limit (0-180 min.) with a value of 0 disabling the timer.
169
+ * improved spider detection.
170
+ * improved referrer spam detection.
171
+ * improved screen resolution detection for IE.
 
 
 
172
  * miscellaneous minor code and style changes.
173
 
174
  = 1.8.1 =
175
  = Urgent bugfix and code improvement upgrade =
176
  * fixed bug that caused `set_time_limit` and other warning errors to display to visitors.
177
+ * new upgrade instructions in `readme.txt`.
178
  * miscellaneous minor code changes.
179
 
180
  = 1.8 =
205
  ...
206
  == Upgrade Notice ==
207
 
208
+ = 1.8.3 =
209
+ * Urgent bug fix, compatibility, and feature improvement upgrade. Required for WassUp 1.8+ users. Read plugin install instructions for important upgrade information.
210
 
211
  == Infos ==
212
 
213
  You could find every informations and much more at [http://www.wpwp.org](http://www.wpwp.org) - [http://trac.wpwp.org](http://trac.wpwp.org/wiki/Documentation) - [http://www.wpwp.org/forums](http://www.wpwp.org/forums/)
214
 
215
+ Credits to: [Jquery](http://www.jquery.com) for the amazing Ajax framework, [FAMFAMFAM](http://www.famfamfam.com/) for the flags icons and a big thanks to [Helene D.](http://techfromhel.webege.com/) for her help to improve WassUp!
216
 
wassup.php CHANGED
@@ -3,12 +3,12 @@
3
  Plugin Name: WassUp
4
  Plugin URI: http://www.wpwp.org
5
  Description: Analyze your visitors traffic with real-time stats, charts, and a lot of chronological information. Includes a sidebar widget of current online visitors and other statistics and an admin dashboard widget with chart. For Wordpress 2.2 or higher. Caution: don't upgrade when your site is busy!
6
- Version: 1.8.2
7
  Author: Michele Marcucci, Helene Duncker
8
  Author URI: http://www.michelem.org/
9
  Disclaimer: Use at your own risk. No warranty expressed or implied is provided.
10
 
11
- Copyright (c) 2007-2010 Michele Marcucci
12
  Released under the GNU General Public License (GPL)
13
  http://www.gnu.org/licenses/gpl.txt
14
  */
@@ -23,9 +23,9 @@ if (!defined('ABSPATH')) {
23
  }
24
  //wassup globals & constants
25
  global $wp_version, $current_user, $user_level, $wassup_options;
26
- $wassupversion="1.8.2";
27
  $wassup_cookie_value="";
28
- $debug_mode=false; //turn on debugging (global)...Use cautiously! Will display errors from all plugins, not just WassUp
29
  define('WASSUPDIR', dirname(__FILE__)); //new constant in v1.8
30
  define('WASSUPFOLDER', plugin_basename(dirname(__FILE__)));
31
  require_once(WASSUPDIR.'/lib/wassup.class.php');
@@ -66,6 +66,7 @@ function wassup_install() {
66
  //#Add/update wassup settings in Wordpress options table
67
  $wassup_options = new wassupOptions; //#settings initialized here
68
  $wassup_table = (!empty($wassup_options->wassup_table))? $wassup_options->wassup_table : $wpdb->prefix . "wassup";
 
69
 
70
  //# wassup should not be active during install
71
  $wassup_options->wassup_active = 0;
@@ -107,36 +108,36 @@ function wassup_install() {
107
  require_once(WASSUPDIR.'/lib/upgrade.php');
108
  } else {
109
  echo "file: ".WASSUPDIR.'/lib/upgrade.php does not exist!';
110
- exit (1);
111
  }
112
- $success = @wassup_tableInstaller();
113
  //double-check that main table was installed
114
- $wassup_table = (!empty($wassup_options->wassup_table))? $wassup_options->wassup_table : $wpdb->prefix . "wassup";
115
- if ($wpdb->get_var("SHOW TABLES LIKE '$wassup_table'") == $wassup_table){
 
 
 
 
116
  //Reset 'dbengine' MySQL setting with each upgrade...because host server settings can change
117
  if (!empty($wassup_options->wassup_version)) { //upgrade only
118
  $wassup_options->wassup_dbengine = $wassup_options->getMySQLsetting('engine');
119
  }
120
  //turn off wassup_cache if meta table does not exist
121
- $wassup_meta_table = $wassup_table . "_meta";
122
  if ($wassup_options->wassup_cache == 1) {
123
- if ($wpdb->get_var("SHOW TABLES LIKE '$wassup_meta_table'") != $wassup_meta_table) {
124
  $wassup_options->wassup_cache = 0;
125
  }
126
  }
127
 
128
  //show warning when 'WP_CACHE' constant is set
129
  if (wassup_compatCheck("WP_CACHE") == true) {
130
- $wassup_options->wassup_alert_message = '<strong style="color:#c00;padding:5px;">'.__("Page caching affect WassUp's ability to generate accurate statistics. If your cache plugin does whole page caching, WassUp won't run properly. Please deactivate that plugin and remove \"WP_CACHE\" from \"wp_config.php\".","wassup").'</strong>';
131
  }
132
  //TODO: Show warning when 'wp_footer()' does not exist in active theme template (non-cache setups only)
133
 
134
  //#Since v1.7: put current version# in options after update
135
  $wassup_options->wassup_version = $wassupversion;
136
 
137
- if (empty($wassup_options->wassup_alert_message)) {
138
- $wassup_options->wassup_alert_message = "Wassup $wassupversion: ".__("database created/upgraded successfully","wassup"); //debug
139
- }
140
  $wassup_options->wassup_active = 1; //start recording
141
  $wassup_options->saveSettings();
142
 
@@ -146,7 +147,7 @@ function wassup_install() {
146
  if (function_exists('deactivate_plugins')) {
147
  deactivate_plugins(__FILE__);
148
  }
149
- echo '<strong style="color:#c00;padding:5px;">'.__("Error installing WassUp tables","wassup").'.</strong>';
150
  exit(1); //exit with error
151
  }
152
  } //end function
@@ -194,36 +195,37 @@ function wassup_uninstall() {
194
 
195
  /**
196
  * Output javascript in page head for wassup tracking
197
- * @param string (optional);
198
  * @return none;
199
  */
200
- function wassup_head($screen_res="") {
201
- global $wassup_options, $wassupversion, $current_user;
202
-
203
- if ($wassup_options->wassup_active == "1") {
204
- //Since v.1.8: removed meta tag to reduce plugin bloat
205
- //print '<meta name="wassup-version" content="'.$wassupversion.'" />'."\n";
206
- //add screen resolution javascript to blog header
207
- if ($screen_res == "" && isset($_COOKIE['wassup_screen_res'])) {
208
- $screen_res = attribute_escape(trim($_COOKIE['wassup_screen_res']));
209
- if ($screen_res == "x") $screen_res = "";
210
- }
211
- if (empty($screen_res) && isset($_SERVER['HTTP_UA_PIXELS'])) {
212
- //resolution in IE/IEMobile header sometimes
213
- $screen_res = str_replace('X',' x ',$_SERVER['HTTP_UA_PIXELS']);
214
- }
215
- if (empty($screen_res) && isset($_COOKIE['wassup'])) {
216
- $cookie_data = explode('::',attribute_escape(base64_decode(urldecode($_COOKIE['wassup']))));
217
- $screen_res=(!empty($cookie_data[2]))?$cookie_data[2]:"";
218
- }
219
  //Get visitor's screen resolution using javascript and a cookie.
220
  // - Added here so javascript code is placed in document <head>
221
  // to store this client-side only variable in a cookie that PHP
222
  // can read. -Helene D. 2009-01-19 ?>
223
  <script type="text/javascript">
224
  //<![CDATA[
225
- var screen_res = "<?php echo $screen_res; ?>";
226
- <?php if (empty($screen_res) && !isset($_COOKIE['wassup_screen_res'])) { ?>
 
227
  function writeCookie(name,value,hours) {
228
  var the_cookie = name+"="+escape(value)+"; expires=";
229
  var expires = "";
@@ -255,9 +257,9 @@ function wassup_head($screen_res="") {
255
  } //end if !isset('wassup_screen_res')
256
  ?>
257
  //]]>
258
- </script>
259
- <?php
260
- } // end if wassup_active == "1"
261
  } //end function wassup_head
262
 
263
  //# Wassup init hook actions performed before headers are sent:
@@ -268,8 +270,10 @@ function wassup_init() {
268
  global $wp_version, $wassup_options;
269
 
270
  //block any obvious sql injection attempts involving WassUp -Helene D. 2009-06-16
271
- if (stristr($_SERVER['REQUEST_URI'],'wassup') !==FALSE || (isset($_SERVER['HTTP_REFERER']) && stristr($_SERVER['HTTP_REFERER'],'wassup') !==FALSE)) {
272
- if (preg_match('/[&?].+\=(\-(1|9)+|.*(select|update|delete|alter|drop|union|create)[ %&].*(?:from)?.*wp_\w+)/i',str_replace(array('\\','&#92;','"','%22','&#34;','&quot','&#39;','\'','`','&#96;'),'',$_SERVER['REQUEST_URI']))>0) {
 
 
273
  header("HTTP/1.1 403 Forbidden");
274
  wp_die('Illegal request - Permission Denied!');
275
  } elseif (preg_match('/(<|&lt;|&#60;|%3C)script[^a-z0-9]/i',$_SERVER['REQUEST_URI'])>0) {
@@ -290,14 +294,14 @@ function wassup_init() {
290
  wp_deregister_script('jquery');
291
  }
292
  // the safe way to load jquery into WP
293
- wp_register_script('jquery', WASSUPURL.'/js/jquery.js',FALSE,'1.4.2');
294
  }
295
  if ($_GET['page'] == "wassup-spia") {
296
  //the safe way to load a jquery dependent script
297
  wp_enqueue_script('spia', WASSUPURL.'/js/spia.js', array('jquery'), '1.4');
298
  } elseif($_GET['page'] == "wassup-options") {
299
  //if (version_compare($wp_version, '2.7', '<')) {
300
- wp_enqueue_script('jqueryui', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js', array('jquery'), '1.8');
301
  //} else {
302
  // wp_enqueue_script('ui.core', array('jquery'));
303
  // wp_enqueue_script('ui.tabs', array('jquery'));
@@ -330,7 +334,7 @@ if (is_admin()) {
330
 
331
  //Add the wassup stylesheet and other javascripts...
332
  function add_wassup_css() {
333
- global $wassup_options, $debug_mode;
334
 
335
  $plugin_page = $_GET['page'];
336
  if (stristr($plugin_page,'wassup') !== FALSE) { $plugin_page="wassup"; }
@@ -343,7 +347,7 @@ function add_wassup_css() {
343
  }
344
  //preassign "GET" parameters for "action.php" in "action_param"
345
  $action_param='&whash='.$wassup_options->whash;
346
- if ($debug_mode) {
347
  $action_param .= '&debug_mode=true';
348
  }
349
  //Important Note: In WordPress 2.6+ "/wp-content/" can be
@@ -366,14 +370,14 @@ function add_wassup_css() {
366
  ?>
367
  <script type='text/javascript'>
368
  //<![CDATA[
369
- // var selftimerID = 0;
370
  function selfRefresh(){
371
  location.href='?<?php print $_SERVER['QUERY_STRING']; ?>';
372
  }
373
- // selftimerID = setTimeout('selfRefresh()', <?php print ($wassup_options->wassup_refresh * 60000)+2000; ?>);
374
  //]]>
375
- </script>
376
- <?php //New in 1.8.2: restrict refresh to range 0-180 minutes (3 hrs)
377
  $wrefresh = 0;
378
  if (!is_numeric($wassup_options->wassup_refresh) || $wassup_options->wassup_refresh < 0 || $wassup_options->wassup_refresh > 180) {
379
  $wrefresh = 3; //3 minutes default;
@@ -450,14 +454,14 @@ jQuery(document).ready(function($){
450
 
451
  //show larger icons on mouse-over
452
  $("img.delete-icon").mouseover(function() {
453
- $(this).attr("src","<?php echo WASSUPURL.'/img/cross2.png'; ?>");
454
  }).mouseout(function() {
455
- $(this).attr("src","<?php echo WASSUPURL.'/img/cross.png'; ?>");
456
  });
457
  $("img.table-icon").mouseover(function() {
458
- $(this).attr("src","<?php echo WASSUPURL.'/img/database_table2.png'; ?>");
459
  }).mouseout(function() {
460
- $(this).attr("src","<?php echo WASSUPURL.'/img/database_table.png'; ?>");
461
  });
462
 
463
  $("a.deleteID").click(function(){
@@ -472,10 +476,10 @@ jQuery(document).ready(function($){
472
  if (html == "")
473
  $("div#delID" + id).fadeOut("slow");
474
  else
475
- $("div#delID" + id).find('p.delbut').append("<br/><br/><small style='color:#404;font-weight:bold;text-align:right;float:right;'> <nobr>Sorry, delete failed!</nobr> " + html + "</small>");
476
  },
477
  error: function (XMLHttpReq, txtStatus, errThrown) {
478
- $("div#delID" + id).find('p.delbut').append("<br/><br/><small style='color:#404;font-weight:bold;text-align:right;float:right;'> <nobr>Sorry, delete failed!</nobr> " + txtStatus + ": " + errThrown + "</small>");
479
  }
480
  });
481
  return false;
@@ -485,49 +489,45 @@ jQuery(document).ready(function($){
485
  if (empty($_GET['search'])) {
486
  echo "\n"; ?>
487
  $("div.search-ip").slideDown("slow");
488
- $("a.show-search").html("<a href='#' class='show-search'><?php _e("Hide Search", "wassup") ?></a>");
489
  },function() {
490
  $("div.search-ip").slideUp("slow");
491
- $("a.show-search").html("<a href='#' class='show-search'><?php _e("Search", "wassup") ?></a>");
492
  return false; <?php
493
  } else {
494
  echo "\n"; ?>
495
  $("div.search-ip").slideUp("slow");
496
- $("a.show-search").html("<a href='#' class='show-search'><?php _e("Search", "wassup") ?></a>");
497
  },function() {
498
  $("div.search-ip").slideDown("slow");
499
- $("a.show-search").html("<a href='#' class='show-search'><?php _e("Hide Search", "wassup") ?></a>");
500
  return false; <?php
501
  }
502
  echo "\n"; ?>
503
  });
504
- $("a.show-topten").toggle(function(){
505
- $("div.topten").slideDown("slow");
506
- $("a.show-topten").html("<a href='#' class='show-topten'><?php _e("Hide TopTen", "wassup") ?></a>");
507
- },function() {
508
- $("div.topten").slideUp("slow");
509
- $("a.show-topten").html("<a href='#' class='show-topten'><?php _e("Show TopTen", "wassup") ?></a>");
510
- return false;
511
- });
512
 
 
513
  $("a.toggle-all").toggle(function() {
514
  $("div.togglenavi").slideDown("slow");
515
- $("a.toggle-all").html("<a href='#' class='toggle-all boxed'><?php _e("Collapse All", "wassup") ?></a>");
516
  },function() {
517
  $("div.togglenavi").slideUp("slow");
518
- $("a.toggle-all").html("<a href='#' class='toggle-all boxed'><?php _e("Expand All", "wassup") ?></a>");
519
  return false;
520
  });
521
  $("a.toggle-allcrono").toggle(function() {
522
  $("div.togglecrono").slideUp("slow");
523
- $("a.toggle-allcrono").html("<a href='#' class='toggle-allcrono boxed'><?php _e("Expand Chronology", "wassup") ?></a>");
524
  },function() {
525
  $("div.togglecrono").slideDown("slow");
526
- $("a.toggle-allcrono").html("<a href='#' class='toggle-allcrono boxed'><?php _e("Collapse Chronology", "wassup") ?></a>");
527
  return false;
528
  });
529
  <?php
530
- //don't add refresh timer click function if refresh==0
531
  if ($wrefresh > 0) { ?>
532
  $("#CountDownPanel").click(function(){ //Pause|Resume countdown
533
  var timeleft = _currentSeconds*1000;
@@ -550,8 +550,6 @@ jQuery(document).ready(function($){
550
  </script>
551
  <?php } //end if page != wassup-options
552
 
553
- // Since v1.8: go and go2 javascripts deleted because they are not used
554
-
555
  if ($_GET['page'] == "wassup-options") {
556
  //#Current active tabs are indentified after page reload with
557
  //# either $_GET['tab']=N or $_POST['submit-optionsN'] where
@@ -559,12 +557,11 @@ if ($_GET['page'] == "wassup-options") {
559
  //# "settings.php" with <li class="ui-tabs-selected">
560
  //<link rel="stylesheet" href="WASSUPURL.'/css/ui.tabs.css'" type="text/css" />
561
  echo "\n"; ?>
562
- <link href='http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css' rel='stylesheet' type='text/css'/>
563
  <script type="text/javascript">
564
  //<![CDATA[
565
  jQuery(document).ready(function($) {
566
  var $tabs = $('#tabcontainer').tabs();
567
- //$('#tabcontainer > ul').tabs({ fx: { opacity: 'toggle' } });
568
  $('.submit-opt').click(function(){
569
  $(this).css("background-color", "#d71");
570
  });
@@ -594,8 +591,12 @@ echo "\n"; ?>
594
  $('#spyContainer').spy({
595
  limit: 12,
596
  fadeLast: 5,
597
- ajax: '<?php echo WASSUPURL."/lib/action.php?action=spia&spiatype=".$spytype.$action_param; ?>',
598
- timeout: 5000,
 
 
 
 
599
  'timestamp': myTimestamp,
600
  fadeInSpeed: 1100 });
601
 
@@ -604,7 +605,7 @@ echo "\n"; ?>
604
  $("#spy-play").css("background-color", "#eae9e9"); <?php
605
  if (!empty($wassup_options->wassup_geoip_map)) {
606
  echo "\n"; ?>
607
- $("div#map").css({"opacity": "0.5", "background": "none"}); <?php
608
  } ?>
609
  });
610
  $('#spy-play').click(function(){
@@ -682,13 +683,13 @@ function wassupPluginLinks($links, $file) {
682
  * Wassup's admin page manager - displays WassUp admin pages
683
  */
684
  function WassUp() {
685
- global $wpdb, $wp_version, $current_user, $user_level, $wassupversion, $wassup_options, $debug_mode;
686
 
687
  // Start getting time of execution to debug SQL query
688
  $starttime = microtime_float();
689
 
690
  //#debug...
691
- if ($debug_mode) {
692
  $mode_reset=ini_get('display_errors');
693
  //error_reporting(E_ALL | E_STRICT); //debug, E_STRICT=php5 only
694
  error_reporting(E_ALL); //debug
@@ -707,7 +708,7 @@ function WassUp() {
707
 
708
  //"action_param" are preassigned "GET" parameters used for "action.php" external/ajax calls like "top ten"
709
  $action_param='&whash='.$wassup_options->whash;
710
- if ($debug_mode) {
711
  $action_param .= '&debug_mode=true';
712
  }
713
  //wpabspath param required for non-standard wp-content directory location
@@ -822,7 +823,7 @@ function WassUp() {
822
  $wassup_options->delete_filter = $_POST['delete_filter'];
823
  }
824
  $wassup_options->wassup_screen_res = $_POST['wassup_screen_res'];
825
- //validate wassup_refresh option input
826
  if (is_numeric($_POST['wassup_refresh']) && $_POST['wassup_refresh']>=0 && $_POST['wassup_refresh']<=180) {
827
  $wassup_options->wassup_refresh = (int)$_POST['wassup_refresh'];
828
  }
@@ -833,20 +834,27 @@ function WassUp() {
833
  if (!empty($_POST['wassup_googlemaps_key'])) { //don't clear geoip key
834
  $wassup_options->wassup_googlemaps_key = $_POST['wassup_googlemaps_key'];
835
  }
 
 
 
836
  $wassup_options->wassup_time_format = $_POST['wassup_time_format'];
837
  $wassup_options->wassup_time_period = $_POST['wassup_time_period'];
838
  $wassup_options->wassup_default_type = $_POST['wassup_default_type'];
839
  $wassup_options->wassup_default_limit = $_POST['wassup_default_limit'];
840
- $top_ten = array("topsearch" => $_POST['topsearch'],
 
 
 
 
841
  "topreferrer" => $_POST['topreferrer'],
842
  "toprequest" => $_POST['toprequest'],
843
  "topbrowser" => $_POST['topbrowser'],
844
  "topos" => $_POST['topos'],
845
  "toplocale" => (isset($_POST['toplocale'])?$_POST['toplocale']:"0"),
846
  "topvisitor" => (isset($_POST['topvisitor'])?$_POST['topvisitor']:"0"),
847
- "topfeed" => "0",
848
- "topcrawler" => "0",
849
- "topreferrer_exclude" => $_POST['topreferrer_exclude']);
850
  $wassup_options->wassup_top10 = attribute_escape(serialize($top_ten));
851
  $wassup_options->wassup_cache = (!empty($_POST['wassup_cache'])?"1":"0");
852
  if ($wassup_options->saveSettings()) {
@@ -1192,23 +1200,23 @@ function WassUp() {
1192
  //## Filter detail list by date range...
1193
  $to_date = current_time("timestamp"); //wordpress time function
1194
  if (isset($_GET['last']) && is_numeric($_GET['last'])) {
1195
- $last = $_GET['last'];
1196
- $stickyFilters.='&last='.$last;
1197
  } else {
1198
- $last = $wassup_options->wassup_time_period;
1199
  }
1200
- if ($last == 0) {
1201
  $from_date = "0"; //all time
1202
  } else {
1203
- $from_date = $to_date - (int)(($last*24)*3600);
1204
  //extend start date to within a rounded time
1205
- if ($last < .25) { //start on 1 minute
1206
  $from_date = ((int)($from_date/60))*60;
1207
- } elseif ($last < 7) {
1208
  $from_date = ((int)($from_date/300))*300;
1209
- } elseif ($last < 30) {
1210
  $from_date = ((int)($from_date/1800))*1800;
1211
- } elseif ($last < 365) {
1212
  $from_date = ((int)($from_date/86400))*86400;
1213
  } else {
1214
  $from_date = ((int)($from_date/604800))*604800;
@@ -1217,45 +1225,45 @@ function WassUp() {
1217
 
1218
  //## Filter detail lists by visitor type...
1219
  if (isset($_GET['type'])) {
1220
- $type = attribute_escape($_GET['type']);
1221
- $stickyFilters.='&type='.$type;
1222
  } else {
1223
- $type = $wassup_options->wassup_default_type;
1224
  }
1225
- if (!empty($type) && $type != 'everything') {
1226
- $whereis=$wassup_options->getKeyOptions("wassup_default_type","sql",$type);
1227
  } else {
1228
- $type="";
1229
- $whereis="";
1230
  }
1231
  //## Filter detail lists by a specific page and number
1232
  //# of items per page...
1233
- $items = 10; //default
1234
  if (isset($_GET['limit']) && is_numeric($_GET['limit'])) {
1235
- //$items = htmlentities(attribute_escape($_GET['limit']));
1236
- $items = (int)$_GET['limit'];
1237
  } elseif ($wassup_options->wassup_default_limit != '') {
1238
- $items = $wassup_options->wassup_default_limit;
1239
  }
1240
- if ((int)$items < 1 ) { $items = 10; }
1241
  //# current page selections
1242
  if (isset($_GET['pages']) && is_numeric($_GET['pages'])) {
1243
- $pages = (int)$_GET['pages'];
1244
  } else {
1245
- $pages = 1;
1246
  }
1247
- if ( $pages > 1 ) {
1248
- $limit = " LIMIT ".(($pages-1)*$items).",$items";
1249
  } else {
1250
- $limit = " LIMIT $items";
1251
  }
1252
 
1253
  //## Filter detail lists by a searched item
1254
  if (!empty($_GET['search'])) {
1255
- $search = attribute_escape(strip_tags(html_entity_decode($_GET['search'])));
1256
- $stickyFilters.='&search='.$search;
1257
  } else {
1258
- $search = "";
1259
  }
1260
 
1261
  // DELETE EVERY RECORD MARKED BY IP
@@ -1280,28 +1288,28 @@ function WassUp() {
1280
  echo "<!--heartbeat-->\n";
1281
 
1282
  // Instantiate class to count items
1283
- $Tot = New MainItems($wassup_table,$from_date,$to_date,$whereis,$limit);
1284
- $Tot->whereis = $whereis;
1285
- $Tot->Limit = $limit;
1286
- $Tot->WpUrl = $wpurl;
1287
  echo "<!--heartbeat-->\n";
1288
 
1289
  // MAIN QUERY
1290
- $main = $Tot->calc_tot("main", $search);
1291
  echo "<!--heartbeat-->\n";
1292
- $itemstot = $Tot->calc_tot("count", $search, null, "DISTINCT");
1293
  echo "<!--heartbeat-->\n";
1294
- $pagestot = $Tot->calc_tot("count", $search);
1295
  echo "<!--heartbeat-->\n";
1296
- $spamtot = $Tot->calc_tot("count", $search, "AND spam>0");
1297
  // Check if some records was marked
1298
  if ($wassup_options->wmark == "1") {
1299
- $markedtot = $Tot->calc_tot("count", $search, "AND ip = '".$wassup_options->wip."'", "DISTINCT");
1300
  }
1301
  echo "<!--heartbeat-->\n";
1302
  // Check if some records were searched
1303
- if (!empty($search)) {
1304
- $searchtot = $Tot->calc_tot("count", $search, null, "DISTINCT");
1305
  }
1306
  //# remove any delete request from $_SERVER['QUERY_STRING']
1307
  //# clear non-sticky filter parameters before applying new filters
@@ -1343,7 +1351,7 @@ function WassUp() {
1343
  _e('Details for the last','wassup'); ?>:
1344
  <select style="font-size: 11px;" name="last" onChange="window.location.href=this.options[this.selectedIndex].value;"><?php
1345
  $optionargs="?".attribute_escape($new_last."&last=");
1346
- $wassup_options->showFormOptions("wassup_time_period","$last","$optionargs"); ?>
1347
  </select></td>
1348
  <td class="legend" align="right"><?php _e('Items per page','wassup'); ?>: <select name="navi" style="font-size: 11px;" onChange="window.location.href=this.options[this.selectedIndex].value;"><?php
1349
  //selectable filter by number of items on page (default_limit)
@@ -1352,15 +1360,15 @@ function WassUp() {
1352
  } else {
1353
  $new_limit = $URLQuery;
1354
  }
1355
- $selected=$items;
1356
  $optionargs="?".$new_limit."&limit=";
1357
  $wassup_options->showFormOptions("wassup_default_limit","$selected","$optionargs"); ?>
1358
  </select><span class="separator">|</span>
1359
  <?php _e('Filter items by','wassup'); ?>: <select style="font-size: 11px;" name="type" onChange="window.location.href=this.options[this.selectedIndex].value;">
1360
  <?php
1361
  //selectable filter by type of record (wassup_default_type)
1362
- $selected=$type;
1363
- $filter_args=str_replace("&type=$type","",$stickyFilters);
1364
  $optionargs="?page=".WASSUPFOLDER.$filter_args."&type=";
1365
  $wassup_options->showFormOptions("wassup_default_type","$selected","$optionargs"); ?>
1366
  </select></td>
@@ -1370,12 +1378,12 @@ function WassUp() {
1370
  <div class='centered'>
1371
  <div id='usage'>
1372
  <ul>
1373
- <li><span style="border-bottom:2px solid #0077CC;"><?php echo $itemstot; ?></span> <?php _e('Visits','wassup'); ?></li>
1374
- <li><span style="border-bottom:2px dashed #FF6D06;"><?php echo $pagestot; ?></span> <?php _e('Pageviews','wassup'); ?></li>
1375
- <li><span><?php echo @number_format(($pagestot/$itemstot), 2); ?></span> <?php _e('Pages/Visits','wassup'); ?></li><?php
1376
  // Print spam usage only if enabled
1377
  if ($wassup_options->wassup_spamcheck == 1) { ?>
1378
- <li><span> <a href="#TB_inline?width=400&inlineId=hiddenspam" class="thickbox"><?php echo $spamtot; ?><span class="plaintext">(<?php echo @number_format(($spamtot*100/$pagestot), 1); ?>%)</span></a></span> <?php _e('Spams','wassup'); ?></li><?php
1379
  } ?>
1380
  </ul><br/>
1381
  <div id="placeholder" align="center"></div>
@@ -1383,12 +1391,12 @@ function WassUp() {
1383
  </div><?php
1384
  // Page breakdown
1385
  // paginate only when total records > items per page
1386
- if ($itemstot > $items) {
1387
  $p=new wassup_pagination();
1388
- $p->items($itemstot);
1389
- $p->limit($items);
1390
- $p->currentPage($pages);
1391
- $p->target("admin.php?page=".WASSUPFOLDER."&limit=$items&type=$type&last=$last&search=$search");
1392
  echo "<!--heartbeat-->\n";
1393
  $p->calculate();
1394
  $p->adjacents(5);
@@ -1417,9 +1425,9 @@ function WassUp() {
1417
  } ?></td>
1418
  <td align="right" class="legend">
1419
  <a href="<?php echo wCleanURL(WASSUPURL.'/lib/action.php?action=topten&from_date='.$from_date.'&to_date='.$to_date.$action_param.'&width='.($res+250).'&height=440','','url');
1420
- if ($debug_mode) echo '" target="_blank';
1421
  else echo '" class="thickbox';
1422
- ?>" title="Wassup <?php _e('Top Stats for Period','wassup');
1423
  $wdformat = get_option("date_format");
1424
  if (($to_date - $from_date) > 24*60*60) {
1425
  echo ": ".gmdate("$wdformat",$from_date)." - ".gmdate("$wdformat",$to_date);
@@ -1428,34 +1436,37 @@ function WassUp() {
1428
  } ?>"><?php _e('Show Top Stats','wassup'); ?></a>
1429
  <span class="separator">|</span>
1430
  <a href="#" class='show-search'><?php
1431
- if (!empty($search)) {
1432
  _e('Hide Search','wassup');
1433
  } else {
1434
  _e('Search','wassup');
1435
  } ?></a></td>
1436
  </tr>
1437
  <tr><td align="left" class="legend" colspan="2"><?php
1438
- if (!empty($search)) {
1439
- echo " &nbsp; <strong>".(int)$searchtot."</strong> ".__('Matches found for search','wassup').": <strong>$search</strong>";
1440
  } else {
1441
  echo "<br/>";
1442
  } ?>
1443
  </td>
1444
  <td align="right" class="legend">
1445
- <div class="search-ip" <?php if (empty($search)) echo 'style="display: none;"'; ?>>
1446
  <form action="" method="get">
1447
  <input type="hidden" name="page" value="<?php echo WASSUPFOLDER; ?>" /><?php
1448
  if (!empty($stickyFilters)) {
1449
  $wfilterargs=wGetQueryPairs($stickyFilters);
1450
- if (!empty($wfilterargs)) {
1451
- foreach ($w_filterargs AS $wfilter) {
1452
- $wfilterval=explode('=',$wfilter);
1453
- if (!empty($wfilterval[0]) && $wfilterval[0]!= 'type') { ?>
1454
- <input type="hidden" name="<?php echo $wfilterval[0].'" value="'.$wfilterval[1]; ?>" /><?php
 
 
1455
  }
1456
  }
1457
- } } ?>
1458
- <input type="text" size="25" name="search" value="<?php if ($search != "") print attribute_escape($search); ?>" /><input type="submit" name="submit-search" value="search" />
 
1459
  </form>
1460
  </div> <!-- /search-ip -->
1461
  </td>
@@ -1463,12 +1474,12 @@ function WassUp() {
1463
  <div class='main-tabs'><?php
1464
  print $expcol;
1465
  //# Show Page numbers/Links...
1466
- if ($itemstot > $items) {
1467
  echo '<div id="pag" align="center">'.$p->show()."</div>\n";
1468
  }
1469
  //# Detailed List of Wassup Records...
1470
- if ($itemstot >0 && count($main) >0) {
1471
- foreach ($main as $rk) {
1472
  $timestampF = $rk->max_timestamp;
1473
  $dateF = gmdate("d M Y", $timestampF);
1474
  if ($wassup_options->wassup_time_format == 24) {
@@ -1559,7 +1570,10 @@ function WassUp() {
1559
  <li><?php echo __("Screen Resolution","wassup").': <span class="raw">'.$rk->screen_res.'</span>'; ?></li><?php
1560
  } ?>
1561
  <li><?php echo 'Wassup ID'.': <span class="raw">'.$rk->wassup_id.'</span>'; ?></li>
1562
- <li><?php echo __("End timestamp","wassup").': <span class="raw">'.$datetimeF.' ( '.$rk->max_timestamp.' )</span>'; ?></li>
 
 
 
1563
  </ul>
1564
  </div> <!-- raw-wassup_id -->
1565
 
@@ -1585,10 +1599,10 @@ function WassUp() {
1585
  <a href="?<?php echo attribute_escape($URLQuery.'&deleteMARKED=1&dip='.$ip); ?>" style="text-decoration:none;" class="deleteIP"><img class="delete-icon" src="<?php echo WASSUPURL.'/img/cross.png" alt="'.__('delete','wassup').'" title="'.__('Delete ALL marked records with this IP','wassup'); ?>" /></a>
1586
  <a href="?<?php echo attribute_escape($URLQuery.'&wmark=0'); ?>" style="text-decoration:none;"><img class="unmark-icon" src="<?php echo WASSUPURL.'/img/error_delete.png" alt="'.__('unmark','wassup').'" title="'.__('UnMark IP','wassup'); ?>" /></a><?php
1587
  } else { ?>
1588
- <a href="#" class="deleteID" id="<?php echo $rk->wassup_id ?>" style="text-decoration:none;"><img class="delete-icon" src="<?php echo WASSUPURL.'/img/cross.png" alt="'.__('delete','wassup').'" title="'.__('Delete this record','wassup'); ?>" /></a>
1589
  <a href="?<?php echo attribute_escape($URLQuery.'&wmark=1&wip='.$ip); ?>" style="text-decoration:none;"><img class="mark-icon" src="<?php echo WASSUPURL.'/img/error_add.png" alt="'.__('mark','wassup').'" title="'.__('Mark IP','wassup'); ?>" /></a><?php
1590
  } ?>
1591
- <a href="#TB_inline?height=400&width=<?php echo $res.'&inlineId='.$raw_div; ?>" class="thickbox"><img class="table-icon" src="<?php echo WASSUPURL.'/img/database_table.png" alt="'.__('show raw table','wassup').'" title="'.__('Show the items as raw table','wassup'); ?>" /></a>
1592
  </p>
1593
  <div class="sum-box">
1594
  <span class="sum-box-ip <?php echo $unclass ?>"><?php
@@ -1745,8 +1759,8 @@ function WassUp() {
1745
  <?php
1746
  } //end foreach qry
1747
  print $expcol; //moved
1748
- } //end if itemstot > 0
1749
- if ($itemstot > $items) {
1750
  print '<div align="center">'.$p->show().'</div><br />'."\n";
1751
  } ?>
1752
  </div><!-- /main-tabs --><?php
@@ -1754,13 +1768,13 @@ function WassUp() {
1754
  if (!empty($wassup_options->wassup_chart) || (!empty($_GET['chart']) && "1" == attribute_escape($_GET['chart']))) {
1755
  $chart_type = ($wassup_options->wassup_chart_type >0)? $wassup_options->wassup_chart_type: "2";
1756
  //show Google!Charts image
1757
- if ($pagestot > 12) {
1758
  $chartwidth=$res;
1759
  //let browser resize chart for small screens
1760
  if ((int)$wassup_options->wassup_screen_res <800){
1761
  $chartwidth=640;
1762
  }
1763
- $chart_url = $Tot->TheChart($last, $chartwidth, "180", $search, $chart_type, "bg,s,dedade|c,lg,90,edffff,0,dedade,0.8", "page", $type);
1764
  $html='<img src="'.$chart_url.'" alt="'.__("Graph of visitor hits","wassup").'" class="chart" width="'.$res.'" />';
1765
  } else {
1766
  $html='<p style="padding-top:10px;">'.__("Too few records to print chart","wassup").'...</p>';
@@ -1783,7 +1797,7 @@ function WassUp() {
1783
  <p><small>WassUp ver: <?php echo $wassupversion.' <span class="separator">|</span> '.__("Check the official","wassup").' <a href="http://www.wpwp.org" target="_BLANK">WassUp</a> '.__("page for updates, bug reports and your hints to improve it","wassup").' <span class="separator">|</span> <a href="http://trac.wpwp.org/wiki/Documentation" title="Wassup '.__("User Guide documentation","wassup").'">Wassup '.__("User Guide documentation","wassup").'</a>'; ?>
1784
  <nobr><span class="separator">|</span> <?php echo __('Exec time','wassup').": $totaltime"; ?></nobr></small></p>
1785
  <?php
1786
- if ($debug_mode) {
1787
  //display MySQL errors/warnings in admin menus - for debug
1788
  $wpdb->print_error(); //debug
1789
 
@@ -1795,15 +1809,14 @@ function WassUp() {
1795
  <?php
1796
  } //end function Wassup
1797
 
1798
- //Since v.1.8: createTable/upgradeTable functions were moved to
1799
- // 'upgrade.php' module where they are loaded only when needed to keep
1800
- // WassUp fast
1801
  } //end if is_admin
1802
 
1803
  //### Wassup Tracking functions
1804
  //Set Wassup_id and cookie (before headers sent)
1805
  function wassupPrepend() {
1806
- global $wassup_options, $current_user, $user_level, $screen_res, $wassup_cookie_value, $debug_mode;
1807
 
1808
  //reload wassup_options in case changed elsewhere (by admin)
1809
  $wassup_options = new wassupOptions;
@@ -1814,9 +1827,10 @@ function wassupPrepend() {
1814
  }
1815
  $wassup_id = "";
1816
  $session_timeout = 1;
1817
- $screen_res = "";
1818
  $cookieIP = "";
1819
  $cookieHost = "";
 
1820
  $wassup_cookie_value="";
1821
  $wassup_dbtask=array();
1822
 
@@ -1830,26 +1844,30 @@ function wassupPrepend() {
1830
  $wassup_timer = $cookie_data[1];
1831
  $session_timeout = ((int)$wassup_timer - (int)time());
1832
  }
1833
- if (!empty($cookie_data[2])) $screen_res = $cookie_data[2];
1834
  if (!empty($cookie_data[3])) {
1835
  $cookieIP = $cookie_data[3];
1836
  if (!empty($cookie_data[4])) {
1837
  $cookieHost = $cookie_data[4];
1838
  }
1839
  }
 
 
 
 
1840
  }
1841
  //set screen resolution value from cookie or browser header data, if any
1842
- if (empty($screen_res)) {
1843
  if (isset($_COOKIE['wassup_screen_res'])) {
1844
- $screen_res = attribute_escape(trim($_COOKIE['wassup_screen_res']));
1845
- if ($screen_res == "x") $screen_res="";
1846
  }
1847
- if (empty($screen_res) && isset($_SERVER['HTTP_UA_PIXELS'])) {
1848
  //resolution in IE/IEMobile header sometimes
1849
- $screen_res = str_replace('X',' x ',$_SERVER['HTTP_UA_PIXELS']);
1850
  }
1851
- //if (empty($screen_res) && isset($_GET['wscr'])) {
1852
- // $screen_res = $_GET['wscr'];
1853
  //}
1854
  }
1855
 
@@ -1857,12 +1875,13 @@ function wassupPrepend() {
1857
  //if (empty($current_user->user_login)) {
1858
  get_currentuserinfo(); //sets $current_user, $user_xx
1859
  //}
1860
- $logged_user = (!empty($current_user->user_login)? $current_user->user_login: "");
 
1861
  //exclude valid wordpress admin page visits and admin hits
1862
  if (($wassup_options->wassup_admin == "1" || $user_level < 8) && (!is_admin() || empty($logged_user))) {
1863
 
1864
  //write wassup cookie for new visits, visit timeout (45 mins) or empty screen_res
1865
- if (empty($wassup_id) || $session_timeout < 1 || (empty($cookie_data[2]) && !empty($screen_res))) {
1866
  $ipAddress = "";
1867
  $proxy = "";
1868
  $hostname = "";
@@ -1970,14 +1989,14 @@ function wassupPrepend() {
1970
  $cookiepath = $cookieurl['path'];
1971
  }
1972
  $expire = time()+3000; //expire based on utc timestamp, not on Wordpress time
1973
- $cookie_data = implode('::',array("$wassup_id","$wassup_timer","$screen_res","$IP","$hostname"));
1974
  $wassup_cookie_value = urlencode(base64_encode($cookie_data));
1975
  setcookie("wassup", "$wassup_cookie_value", $expire, $cookiepath, $cookiedomain);
1976
  unset($temp_id, $tempUA, $templen);
1977
  } //end if empty(wassup_id)
1978
 
1979
  //place wassup tag and javascript in document head
1980
- add_action('wp_head', 'wassup_head', 10, "$screen_res");
1981
  //track visitor hits:
1982
  // use 'send_headers' hook to track media, downloads, and feed hits
1983
  if (preg_match("/(\.(gif|ico|jpe?g|png|svg|tiff|asp|cgi|css|doc|html?|js|jar|jsp|rdf|rtf|pdf|ppt|psd|txt|xls|xlt|xml|flv|mov|mpg|mp4|mp3|ogg|swf|wmv|Z|gz|zip)$)|[=\/](feed|atom)/i", $_SERVER['REQUEST_URI'])>0) {
@@ -2007,22 +2026,22 @@ function wassupPrepend() {
2007
 
2008
  //Track visitors and save record in wassup table, after page is displayed
2009
  function wassupAppend() {
2010
- global $wpdb, $wassup_options, $current_user, $user_level, $wassupversion, $wassup_cookie_value, $debug_mode;
2011
 
2012
  if ($wassup_options->wassup_active == 0) { //do nothing
2013
  return;
2014
  }
2015
  @ignore_user_abort(1); // finish script in background if visitor aborts
2016
 
2017
- if ($debug_mode) { //#debug...
2018
  //debug mode must be off for media and non-html requests
2019
  if (preg_match("/(\.(gif|ico|jpe?g|png|tiff|css|doc|js|jar|rdf|rtf|pdf|ppt|psd|txt|xls|xlt|xml|flv|mov|mpg|mp4|mp3|ogg|swf|wmv|Z|gz|zip)$)|[=\/](feed|atom)/i", $_SERVER['REQUEST_URI'])>0) {
2020
- $debug_mode=false;
2021
  } elseif (is_feed()) {
2022
- $debug_mode=false;
2023
  } else {
2024
  $mode_reset=ini_get('display_errors');
2025
- $debug_reset=$debug_mode;
2026
  error_reporting(E_ALL); //debug, E_STRICT=php5 only
2027
  ini_set('display_errors','On'); //debug
2028
  //Debug: Output open comment tag to hide PHP errors from visitors
@@ -2036,7 +2055,7 @@ function wassupAppend() {
2036
  if (!empty($errlvl)) {
2037
  @error_reporting(E_ERROR);
2038
  }
2039
- } //end if $debug_mode
2040
 
2041
  $wpurl = get_bloginfo('wpurl');
2042
  $blogurl = get_option('home');
@@ -2049,7 +2068,7 @@ function wassupAppend() {
2049
  if (is_single() || is_page()) $post_ID = get_the_id();
2050
  else $post_ID=0;
2051
  //if (empty($current_user->user_login)) {
2052
- get_currentuserinfo(); //sets $current_user, $user_xx
2053
  //}
2054
  $logged_user = (!empty($current_user->user_login)? $current_user->user_login: "");
2055
  $urlRequested = $_SERVER['REQUEST_URI'];
@@ -2066,6 +2085,9 @@ function wassupAppend() {
2066
  //# First exclusion control is for admin user
2067
  if ($wassup_options->wassup_admin == "1" || $user_level < 8) {
2068
 
 
 
 
2069
  //# Record non-admin page visits and or hack attempts
2070
  if ((!is_admin() && stristr($urlRequested,"/wp-admin/")===FALSE && stristr($urlRequested,"/wp-includes/")===FALSE) || $hackercheck) {
2071
  //Get post/page id, if any
@@ -2107,7 +2129,6 @@ function wassupAppend() {
2107
  //exclusion control by specific username/url
2108
  if (!$exclude_visit) {
2109
  $wassup_id = "";
2110
- $screen_res = "";
2111
  $cookieIP = "";
2112
  $cookieHost = "";
2113
  //check for wassup cookie and read contents
@@ -2119,7 +2140,7 @@ function wassupAppend() {
2119
  $wassup_cookie = explode('::',$cookie_data);
2120
  $wassup_id = $wassup_cookie[0];
2121
  if (!empty($wassup_cookie[2])) {
2122
- $screen_res = $wassup_cookie[2];
2123
  }
2124
  if (!empty($wassup_cookie[3])) {
2125
  $cookieIP = $wassup_cookie[3];
@@ -2129,14 +2150,14 @@ function wassupAppend() {
2129
  }
2130
  }
2131
  //### set screen resolution value from cookie or browser header data, if any
2132
- if (empty($screen_res)) {
2133
  if (isset($_COOKIE['wassup_screen_res'])) {
2134
- $screen_res = attribute_escape(trim($_COOKIE['wassup_screen_res']));
2135
- if ($screen_res == "x") $screen_res = "";
2136
  }
2137
- if (empty($screen_res) && isset($_SERVER['HTTP_UA_PIXELS'])) {
2138
  //resolution in IE/IEMobile header sometimes
2139
- $screen_res = str_replace('X',' x ',attribute_escape($_SERVER['HTTP_UA_PIXELS']));
2140
  }
2141
  }
2142
  //#### Get the visitor's details from http header...
@@ -2245,16 +2266,16 @@ function wassupAppend() {
2245
  // and get previous settings to prevent redundant checks on same
2246
  // visitor. Dup==same wassup_id, same URL, and timestamp <180 secs
2247
  $dup_urlrequest=0;
2248
- $w_pageviews=0;
2249
  $spamresult=0;
2250
  $wpdb->query("SET wait_timeout = 7"); //don't wait for slow responses
2251
- $recent = $wpdb->get_results("SELECT wassup_id, urlrequested, spam, screen_res, `timestamp`, browser, spider, os, feed, `language`, `agent`, `referrer` FROM ".$table_tmp_name." WHERE wassup_id='".$wassup_id."' AND `timestamp` >".($timestamp-180)." ORDER BY `timestamp` DESC");
2252
- if (!empty($recent)) {
2253
- $w_pageviews=count($recent);
2254
  //check 1st record only
2255
  //record is dup if same url (with 'wscr' removed) and same user-agent
2256
- if ($recent[0]->urlrequested == $urlRequested || $recent[0]->urlrequested == remove_query_arg('wscr',$urlRequested) || $recent[0]->urlrequested == "[404] $urlRequested") {
2257
- if ($recent[0]->agent == $userAgent || empty($recent[0]->agent)) {
2258
  $dup_urlrequest=1;
2259
  }
2260
  } elseif (preg_match("/\.(gif|ico|jpe?g|png|tiff)$/", $_SERVER['REQUEST_URI']) >0) {
@@ -2263,53 +2284,54 @@ function wassupAppend() {
2263
  }
2264
 
2265
  //retrieve previous spam check results
2266
- $spamresult = $recent[0]->spam;
2267
 
2268
  //check for screen resolution and update, if not previously recorded
2269
  //...queue the update because of "delayed insert"
2270
- if (empty($recent[0]->screen_res) && !empty($screen_res)) {
2271
- $wassup_dbtask[] = "UPDATE $wassup_table SET `screen_res`='$screen_res' WHERE `wassup_id`='$wassup_id' AND `screen_res`='' ";
2272
  }
2273
 
2274
  //get previously recorded settings for this visitor to
2275
  // avoid redundant tests
2276
  if ($dup_urlrequest == 0) {
2277
- if (empty($screen_res) && !empty($recent[0]->screen_res)) {
2278
- $screen_res = $recent[0]->screen_res;
2279
  }
2280
  if ($spam == 0 && (int)$spamresult >0 ) {
2281
  $spam = $spamresult;
2282
  }
2283
- if ($recent[0]->agent == $userAgent || empty($userAgent)) {
2284
- $browser = $recent[0]->browser;
2285
- $spider = $recent[0]->spider;
2286
- $os = $recent[0]->os;
2287
  if (empty($language)) {
2288
- $language = $recent[0]->language;
2289
  }
2290
  //feed reader only if this page is feed
2291
- if (!empty($recent[0]->feed) && is_feed()) {
2292
- $feed = $recent[0]->feed;
2293
  }
2294
  }
2295
  }
2296
  // Detect disguised spiders and harvesters by checking for
2297
  // excessive pageviews (threshold: 8+ views in < 16 secs)
2298
- if ($w_pageviews >7 && empty($spider)) {
2299
- $visitstart = $recent[7]->timestamp;
2300
- if (($timestamp - $recent[7]->timestamp) < 16) {
 
2301
  $is_spider=true;
2302
- $pagetest[]="$urlRequested";
2303
  //a spider is unlikely to hit same page 2+ times
2304
- foreach ($recent AS $w_pgview) {
2305
  if (stristr($w_pgview->urlrequested,"robots.txt")!==false) {
2306
  $is_spider = true;
2307
  break;
2308
- } elseif (in_array($w_pgview->urlrequested,$pagetest)) {
2309
  $is_spider = false;
2310
  break;
2311
  } else {
2312
- $pagetest[] = $w_pgview->urlrequested;
2313
  }
2314
  }
2315
  if ($is_spider) {
@@ -2318,20 +2340,20 @@ function wassupAppend() {
2318
  }
2319
  }
2320
  }
2321
- } //end if recent
2322
- if ($debug_mode) { //debug
2323
- if (!empty($recent)) {
2324
  echo "<br />\nRecent visit data found in wassup_tmp:\n"; //debug
2325
- print_r($recent); //debug
2326
  echo "\n";
2327
- $debug_output .="\n\n".date('H:i:s.u').' Recent data lookup results: $recent='.serialize($recent)."\n";
2328
  if ($dup_urlrequest == 1) {
2329
  echo "\nDuplicate record!\n";
2330
  }
2331
- if ($recent[0]->agent != $userAgent) {
2332
  echo "\nUser Agents NOT Identical:";
2333
  echo "\n\tCurrent user agent: ".$userAgent;
2334
- echo "\n\tPrevious user agent:".$recent[0]->agent."\n";
2335
  }
2336
  } else {
2337
  echo "<br />\nNo Recent visit data found in wassup_tmp.\n"; //debug
@@ -2340,11 +2362,13 @@ function wassupAppend() {
2340
  $wpdb->query("SET wait_timeout = 60");
2341
 
2342
  //don't record 404 unless 1st visit or hack attempt
2343
- if ($req_code == 200 || empty($recent) || ($hackercheck && (stristr($urlRequested,"/wp-")!==FALSE || preg_match('/\.(php|ini|aspx?|dll|cgi)|(\.\.\/\.\.\/|root[^a-z0-9\-_]|[^a-z0-9\-_]passw|\=admin[^a-z0-9\-_]|\=\-\d+|(bin|etc)\/)/i',$urlRequested)>0))) {
2344
  //identify hackers
2345
- if ($req_code != 200 && preg_match('#(\.(php|cgi|aspx?)|[\*\,\'"]|\=\-1$)#i',$urlRequested)>0) {
2346
- //visitors trying to run non-existent server-side scripts are up to no good.
2347
- $spam = 3;
 
 
2348
  } elseif (preg_match('#\.\./\.\./(etc/passwd|\.\./\.\./)#i',$urlRequested)>0 || preg_match('#[\[&\?/](dir|document_root\]?|id|page|thisdir)\=https?\://#i',$urlRequested)>0) {
2349
  //anyone trying to access root files, password or ids are up to no good
2350
  $spam = 3;
@@ -2352,11 +2376,11 @@ function wassupAppend() {
2352
  $spam = 3;
2353
  }
2354
  //retroactively update record for hack attempt
2355
- if ($spam == "3" && $spamresult == "0" && !empty($recent)) {
2356
  $wassup_dbtask[] = "UPDATE $wassup_table SET `spam`='3' WHERE `wassup_id`='$wassup_id' AND `spam`='0' ";
2357
  }
2358
 
2359
- //# Exclude duplicates and avoid redundant checks on multi-page visits
2360
  if ($dup_urlrequest == 0) {
2361
  //##### Extract useful visit information from http header..
2362
  //#Identify user-agent...
@@ -2385,13 +2409,12 @@ function wassupAppend() {
2385
  } //end else agenttype
2386
  $os = $ua->os;
2387
  if (!empty($ua->resolution)) {
2388
- //TODO?: Write 'wassup_screen_res' cookie, if none
2389
- $screen_res = (preg_match('/^\d+x\d+$/',$ua->resolution)>0)?str_replace('x',' x ',$ua->resolution):$ua->resolution;
2390
  }
2391
  if (!empty($ua->language) && empty($language)) {
2392
  $language=$ua->language;
2393
  }
2394
- if ($debug_mode) $debug_output .= "\n".date('H:i:s.u').' UAdetecter results: $ua='.serialize($ua)."\n";
2395
  } //end if $ua->name
2396
 
2397
  $agent = (!empty($browser)?$browser:$spider);
@@ -2400,7 +2423,7 @@ function wassupAppend() {
2400
  if ((empty($agent) || stristr($agent,'unknown')!==false) && !empty($userAgent)) {
2401
  list($browser,$os) = wGetBrowser($userAgent);
2402
  if (!empty($browser)) $agent= $browser;
2403
- if ($debug_mode) $debug_output .= "\n".date('H:i:s.u').' wGetBrowser results: $browser='.$browser.' $os='.$os."\n";
2404
  }
2405
 
2406
  //# Some spiders, such as Yahoo and MSN, don't
@@ -2411,7 +2434,7 @@ function wassupAppend() {
2411
  //#Identify spiders and feeds with wGetSpider...
2412
  if (empty($agent) || stristr($agent,'unknown')!==false || preg_match($spider_hosts,$hostname)>0 ) {
2413
  list($spider,$spidertype,$feed) = wGetSpider($userAgent,$hostname,$browser);
2414
- if ($debug_mode) $debug_output .= "\n".date('H:i:s.u').' wGetSpider results: $spider='.$spider.' $spidertype='.$spidertype.' $feed='.$feed."\n";
2415
  //it's a browser
2416
  if ($spidertype == "B" && $urlRequested != "/robots.txt") {
2417
  if (empty($browser)) $browser = $spider;
@@ -2426,7 +2449,7 @@ function wassupAppend() {
2426
  //#Identify spiders and feed with wGetSpider...
2427
  } elseif(!empty($userAgent) && (strlen($agent)<5 || strstr($agent,'N/A') || ($agent == $browser && (empty($os) || preg_match("#\s?([a-z]+(?:bot|crawler|spider|reader|agent))[^a-z]#i",$userAgent)>0 || strstr($urlRequested,"robots.txt")!==FALSE || is_feed())))) {
2428
  list($spider,$spidertype,$feed) = wGetSpider($userAgent,$hostname,$browser);
2429
- if ($debug_mode) $debug_output .= "\n".date('H:i:s.u').' wGetSpider results: $spider='.$spider.' $spidertype='.$spidertype.' $feed='.$feed."\n";
2430
  //it's a browser
2431
  if ($spidertype == "B" && $urlRequested != "/robots.txt") {
2432
  if (empty($browser)) $browser = $spider;
@@ -2444,7 +2467,7 @@ function wassupAppend() {
2444
  } //end if empty(browser) && empty(spider)
2445
 
2446
  //if 1st request is "robots.txt" then this is a bot
2447
- if (empty($spider) && strstr($urlRequested,"robots.txt")!==FALSE && empty($recent)) {
2448
  $spider = __("Unknown Spider","wassup");
2449
 
2450
  //empty userAgent is a bot
@@ -2458,25 +2481,25 @@ function wassupAppend() {
2458
 
2459
  //# some valid spiders to exclude from spam check below
2460
  $goodbot = false;
2461
- if ($hostname!="" && !empty($spider) && preg_match('/^(googlebot|bingbot|msnbot|yahoo\!\ slurp|technorati)/i',$spider)>0 && preg_match('/\.(googlebot|live|msn|yahoo|technorati)\.(com|net)$/i',$hostname)>0){
2462
  $goodbot = true;
2463
  }
2464
 
2465
  //do spam exclusion controls, unless disabled in wassup_spamcheck
2466
- if ($wassup_options->wassup_spamcheck == 1 && $spam == 0) {
2467
  $spamComment = New wassup_checkComment;
2468
 
2469
  //### 1st Check for referrer spam...faster, if positive
2470
- if ($wassup_options->wassup_refspam == 1 && !empty($referrer) && !$goodbot) {
2471
  //#...skip if referrer is own blog
2472
- if (stristr($referrer,$wpurl)===FALSE && stristr($referrer,$blogurl)===FALSE && !$debug_mode) {
2473
  // Do a control if it is Referrer Spam
2474
- //check if referer is a previous comment spammer
2475
  if ($spamComment->isRefSpam($referrer)>0) {
2476
  $spam = 2;
2477
  //check referer against a list of known spammers
2478
  } else {
2479
- if ($debug_mode) {
2480
  $isspam = wGetSpamRef($referrer,$hostname);
2481
  } else {
2482
  $isspam = @wGetSpamRef($referrer,$hostname);
@@ -2489,7 +2512,7 @@ function wassupAppend() {
2489
  //### Check for comment spammers...
2490
  //# No spam check on known bots (google, yahoo,...) unless
2491
  //# there is a comment or forum page request...
2492
- if ($spam == 0 && (empty($spider) || !$goodbot || stristr($urlRequested,"comment")!== FALSE || stristr($urlRequested,"forum")!== FALSE || !empty($comment_user))) {
2493
 
2494
  //if (isset($spamresult) && stristr($urlRequested,"comment") === FALSE && stristr($urlRequested,"forum") === FALSE && empty($comment_user) && empty($_POST['comment'])) {
2495
  // $spam = $spamresult; //redundant - set in dup check
@@ -2504,8 +2527,8 @@ function wassupAppend() {
2504
  $spam=1;
2505
  }
2506
  //#lastly check for comment spammers using Akismet API
2507
- // Note: this may cause "header already sent" errors with "send_headers" hook in some Wordpress configurations
2508
- if ($wassup_options->wassup_spam == 1 && stristr($urlRequested,"comment") !== FALSE && $spam == 0) {
2509
  $akismet_key = get_option('wordpress_api_key');
2510
  $akismet_class = dirname(__FILE__).'/lib/akismet.class.php';
2511
  if (!empty($akismet_key) && file_exists($akismet_class)) {
@@ -2534,7 +2557,7 @@ function wassupAppend() {
2534
  } //end if wassup_spam
2535
 
2536
  //retroactively update visitor's hits as spam, in case late detection
2537
- if (!empty($recent) && !empty($spam) && $spamresult==0) {
2538
  //queue the update...
2539
  $wassup_dbtask[]="UPDATE $wassup_table SET `spam`='".$spam."' WHERE `wassup_id`='".$wassup_id."' AND `spam`='0' ";
2540
  }
@@ -2553,14 +2576,15 @@ function wassupAppend() {
2553
  $searchengine="";
2554
  $search_phrase="";
2555
  $searchpage="";
 
2556
  //don't check own blog for search engine data
2557
- if (!empty($referrer) && $spam == "0" && stristr($referrer,$blogurl)!=$referrer && !$debug_mode) {
2558
- //if ($debug_mode) { //debug
2559
  // echo '<br />\n$Referrer="'.$referrer.'" is NOT own site: '.$blogurl.'. Checking for search engine data...'."\n"; //debug
2560
  //}
2561
  //get GET type search results, ex: search=x
2562
  if (strpos($referrer,'=')!==false) {
2563
- list($searchengine,$search_phrase,$searchpage,$searchlang,$searchcountry)=explode("|",wGetSE($referrer));
2564
  if ($search_phrase != '') {
2565
  $sedomain = parse_url($referrer);
2566
  $searchdomain = $sedomain['host'];
@@ -2580,26 +2604,36 @@ function wassupAppend() {
2580
  if ($search_phrase != '') {
2581
  if (!empty($searchengine)) {
2582
  if (stristr($searchengine,"images")===FALSE && stristr($referrer,'&imgurl=')===FALSE) {
 
 
 
 
 
 
2583
  // NOTE: Position retrieved in Google Images is
2584
  // the position number of image NOT page rank position like web search
2585
  $searchpage=(int)($searchpage/10)+1;
2586
  }
2587
- if (empty($searchcountry) && preg_match('/(\.([a-z]{2})$|^([a-z]{2})\.)/i',$searchdomain,$match)) {
 
 
2588
  if (!empty($match[2])) {
2589
  $searchcountry = $match[2];
2590
  } elseif (!empty($match[3])) {
2591
  $searchcountry = $match[3];
2592
  }
2593
- }
2594
- if (!empty($searchcountry) && $searchcountry != "us") {
2595
- $searchengine .= " ".strtoupper($searchcountry);
2596
  }
2597
  } else {
2598
  $searchengine = $searchdomain;
2599
  }
2600
  //use search engine country code as locale
2601
- $searchcountry = trim($searchcountry);
2602
- if (!empty($searchcounty) && ($language == "us" || empty($language))) {
 
 
2603
  $language=$searchcountry;
2604
  }
2605
  } //end if search_phrase
@@ -2623,7 +2657,7 @@ function wassupAppend() {
2623
  'os'=>$os,
2624
  'browser'=>$browser,
2625
  'language'=>$language,
2626
- 'screen_res'=>$screen_res,
2627
  'spider'=>$spider,
2628
  'feed'=>$feed,
2629
  'username'=>$logged_user,
@@ -2657,6 +2691,7 @@ function wassupAppend() {
2657
  } //end if wassup_exclude
2658
  } //end if !exclude_visit
2659
  } //end if !is_admin
 
2660
  } //end if loggeduser_level
2661
 
2662
  //### Notify admin if alert is set and wassup table > alert
@@ -2722,12 +2757,12 @@ function wassupAppend() {
2722
 
2723
  //perform scheduled database tasks
2724
  if (count($wassup_dbtask)>0) {
2725
- if ($debug_mode) {
2726
  $debug_output.="\n"."Performing Scheduled tasks:".serialize($wassup_dbtask)."\n";
2727
  }
2728
  wassup_scheduled_dbtask($wassup_dbtask);
2729
  }
2730
- if ($debug_mode) {
2731
  if (!empty($wassup_rec)) {
2732
  echo "<br />\nWassUp record data:\n";
2733
  print_r($wassup_rec); //debug
@@ -2846,17 +2881,17 @@ function wSanitizeData($var, $quotes=false) {
2846
  * @return array
2847
  */
2848
  function wGetQueryPairs($urlstring){
2849
- $return = array();
2850
  if (!empty($urlstring)) {
2851
- $tab=parse_url($urlstring);
2852
- if (key_exists("query",$tab)){
2853
- $query=$tab["query"];
2854
- $return=explode("&",$query);
2855
  } else {
2856
- $return=explode("&",$urlstring); //partial url
2857
  }
2858
  }
2859
- return $return;
2860
  } //end wGetQueryPairs
2861
 
2862
  /**
@@ -2954,10 +2989,11 @@ function wGetSE($referrer = null){
2954
  "Google Mobile|google.com/m/|q|cd|hl||",
2955
  "Google|www.google.|q|cd|hl||",
2956
  "Google|www.google.|as_q|start|hl||", //advanced query
2957
- "Yahoo Images|images.search.yahoo.com|p||||",
2958
- "Yahoo Mobile|m.search.yahoo.|p||||",
2959
- "Yahoo|search.yahoo.|p||||",
2960
- "Yahoo|answers.yahoo.com|p||||",
 
2961
  "Bing Mobile|m.bing.com|q|first|||",
2962
  "Bing Images|.bing.com/images/|q|first|||",
2963
  "Bing|.bing.com|q|first|||",
@@ -3036,6 +3072,8 @@ function wGetSE($referrer = null){
3036
  "Voil|voila.fr|kw|||fr|",
3037
  "Web|.web.de|su|||de|",
3038
  "Yahoo! Mobile|m.yahoo.com|p||||",
 
 
3039
  "Yandex|yandex.ru|text|||ru|",
3040
  "Yippy|search.yippy.com|query||||",
3041
  "Zoohoo|.zoohoo.cz|q|||cz|",
@@ -3057,21 +3095,21 @@ function wGetSE($referrer = null){
3057
  if ($se) { // found it!
3058
  $searchengine = $nome;
3059
  $search_phrase = "";
3060
- $variables=array();
3061
  // Google Images or Google Translate needs additional processing of search phrase after 'prev='
3062
  if ($nome == "Google Images" || $nome == "Google Translate") {
3063
  //'prev' is an encoded substring containing actual "q" query, so use html_entity_decode to show [&?] in url substring
3064
- $variables = wGetQueryPairs(html_entity_decode(preg_replace('#/\w+\?#i','', urldecode($match[1]))));
3065
  $key='q'; //q is actual search key
3066
  } elseif ($nome == "Google Cache") {
3067
  $n = strpos($match[1],$blogurl);
3068
  if ($n !== false) {
3069
  //blogurl in search phrase: cache of own site
3070
  $search_phrase = attribute_escape(urldecode(substr($match[1],$n+strlen($blogurl))));
3071
- $variables = wGetQueryPairs($referrer);
3072
  } elseif (strpos($referrer,$blogurl)!==false && preg_match('/\&prev\=([^&]+)/',$referrer,$match)!==false) {
3073
  //NOTE: 'prev=' requires html_entity_decode to show [&?] in url substring
3074
- $variables = wGetQueryPairs(html_entity_decode(preg_replace('#/\w+\?#i','', urldecode($match[1]))));
3075
  } else {
3076
  //no blogurl in search phrase: cache of an external site with referrer link
3077
  $searchengine = "";
@@ -3083,12 +3121,12 @@ function wGetSE($referrer = null){
3083
  $nome = "Google Mobile";
3084
  }
3085
  $search_phrase = attribute_escape(urldecode($match[1]));
3086
- $variables = wGetQueryPairs($referrer);
3087
  }
3088
  //retrieve search engine parameters
3089
- $i = count($variables);
3090
  while($i--){
3091
- $tab=explode("=",$variables[$i]);
3092
  if($tab[0] == $key && empty($search_phrase)){
3093
  $search_phrase=attribute_escape($tab[1]);
3094
  } else {
@@ -3098,6 +3136,10 @@ function wGetSE($referrer = null){
3098
  if (!empty($lang) && $lang == $tab[0]) {
3099
  $searchlang = attribute_escape($tab[1]);
3100
  }
 
 
 
 
3101
  }
3102
  } //end while
3103
  break 1;
@@ -3249,10 +3291,10 @@ function wGetSpider($agent="",$hostname="", $browser=""){
3249
  //# most common of these are MSN (ie6,win2k3), and Yahoo!
3250
  if (substr($hostname,-16) == ".crawl.yahoo.net" || (substr($hostname,-10)==".yahoo.com" && substr($hostname,0,3)=="ycar")) {
3251
  if (stristr($ua,"Slurp")) {
3252
- $crawler = "Yahoo!Slurp";
3253
  $crawlertype="R";
3254
  } elseif (stristr($ua,"mobile")) {
3255
- $crawler = "Yahoo!Mobile";
3256
  $crawlertype="R";
3257
  } else {
3258
  $crawler = "Yahoo!";
@@ -3315,7 +3357,7 @@ function wGetSpider($agent="",$hostname="", $browser=""){
3315
  $key = null;
3316
  // array format: "Spider Name|UserAgent keywords (no spaces)| Spider type (R=robot, B=Browser/downloader, F=feedreader, H=hacker, L=Link checker, M=siteMap generator, S=Spammer/email harvester, V=CSS/Html validator)
3317
  $lines = array("Googlebot|Googlebot/|R|",
3318
- "Yahoo!|Yahoo!Slurp|R|",
3319
  "FeedBurner|FeedBurner|F|",
3320
  "AboutUsBot|AboutUsBot/|R|",
3321
  "80bot|80legs.com|R|",
@@ -3653,7 +3695,7 @@ function wGetSpider($agent="",$hostname="", $browser=""){
3653
 
3654
  //#get the visitor locale/language
3655
  function wGetLocale($language="",$hostname="",$referrer="") {
3656
- global $wpdb, $wassup_options, $debug_mode;
3657
  $clocale="";
3658
  $country="";
3659
  $language = trim(strtolower($language));
@@ -3742,7 +3784,7 @@ function wGetLocale($language="",$hostname="",$referrer="") {
3742
  * @return boolean
3743
  */
3744
  function wGetSpamRef($referrer,$hostname="") {
3745
- global $debug_mode;
3746
  $referrer=attribute_escape(strip_tags(str_replace(" ","",html_entity_decode($referrer))));
3747
  $badhost=false;
3748
  //$key = null;
@@ -3758,8 +3800,24 @@ function wGetSpamRef($referrer,$hostname="") {
3758
  $referrer_host = $rurl['host'];
3759
  //$referrer_path = $rurl['path'];
3760
  $thissite = parse_url(get_option('home'));
 
3761
  if (isset($thissite['host']) && $referrer_host == $thissite['host']) {
3762
  $referrer_host = "";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3763
  }
3764
  } else { //faked referrer string
3765
  $badhost=true;
@@ -3767,8 +3825,8 @@ function wGetSpamRef($referrer,$hostname="") {
3767
  //#a shortened URL is likely FAKED referrer string!
3768
  if (!$badhost && !empty($referrer_host)) {
3769
  $url_shorteners = array('bit.ly', 'cli.gs',
3770
- 'goo.gl', 'is.gd',
3771
- 'shorturl.com', 'snurl.com',
3772
  'tinyurl.com','tr.im');
3773
  if(in_array($referrer_host,$url_shorteners)) {
3774
  $badhost=true;
@@ -3777,16 +3835,18 @@ function wGetSpamRef($referrer,$hostname="") {
3777
  } //end elseif
3778
  if (empty($referrer_host) || $badhost) return $badhost;
3779
 
3780
- if ($debug_mode) echo "\$referrer_host = $referrer_host.\n";
3781
  //compare against a list of recent referer spammers
3782
  $lines = array( '123666123\.com',
3783
  '209\.29\.25\.180',
 
3784
  'aerhaethjsry\.com',
3785
  'aimtrust\.com',
3786
  'american\-insurance\-companies\.com',
3787
  'amipregnantquizzes\.com',
3788
  'all\-lasik\-centers\.com',
3789
  'allmymovies\.biz',
 
3790
  'baby\-kleidung\.runashop\.com',
3791
  'bayanbag\.tk',
3792
  'beachvitality\.com',
@@ -3798,10 +3858,16 @@ function wGetSpamRef($referrer,$hostname="") {
3798
  'carartexpert\.com',
3799
  'celebritydietdoctor\.com',
3800
  'celebrity\-?diets\.(com|org|net|info|biz)',
 
3801
  'chocolate\.com',
3802
  'clients\.your\-server\.de',
3803
  'couplesresortsonline\.com',
 
 
 
3804
  '.*dietplan\.com',
 
 
3805
  'dreamworksdentalcenter\.com',
3806
  'duunot\.eu',
3807
  '\.ewebesales\.net',
@@ -3810,10 +3876,12 @@ function wGetSpamRef($referrer,$hostname="") {
3810
  'freefarmvillesecrets\.info',
3811
  'frenchforbeginnerssite\.com',
3812
  'gameskillinggames\.net',
 
3813
  'globalringtones\.net',
 
3814
  'gskstudio\.com',
3815
- 'h\-13\d\-\d{3}\.cssgroup\.lv',
3816
  'hearcam\.org',
 
3817
  'highheelsale\.com',
3818
  'homebasedaffiliatemarketingbusiness\.com',
3819
  'hosting37\d{2}\.com/',
@@ -3823,7 +3891,10 @@ function wGetSpamRef($referrer,$hostname="") {
3823
  'intl\-alliance\.com',
3824
  'it\.n\-able\.com',
3825
  'justanimal\.com',
 
 
3826
  'koreanracinggirls\.com',
 
3827
  'lactoseintolerancesymptoms\.net',
3828
  'liquiddiet[a-z\-]*\.com',
3829
  'locksmith[a-z\-]+\.org',
@@ -3841,6 +3912,7 @@ function wGetSpamRef($referrer,$hostname="") {
3841
  'pharmondo\.com',
3842
  'pinky\-vs\-cherokee\.com',
3843
  'pinkyxxx\.org',
 
3844
  'play\-mp3\.com',
3845
  'poker\-review\.tk',
3846
  'pornobesto\.ru',
@@ -3855,9 +3927,12 @@ function wGetSpamRef($referrer,$hostname="") {
3855
  'singlesvacationspackages\.com',
3856
  'sitetalk\-revolution\.com',
3857
  'smartforexsignal\.com',
 
 
3858
  'staphinfectionpictures\.org',
3859
  'static\.theplanet\.com',
3860
  '[a-z]+\-[a-z]+\-symptoms\.com',
 
3861
  'thik\-chik\.com',
3862
  'thisweekendsmovies\.com',
3863
  'unassigned\.psychz\.net',
@@ -4134,24 +4209,36 @@ function microtime_float() { //replicates microtime(true) from PHP5
4134
 
4135
  // hook function to put a timestamp in page footer for page caching test
4136
  function wassup_foot() {
4137
- global $wassup_options, $wassupversion, $debug_mode;
4138
- if ($wassup_options->wassup_active == "1") {
4139
- //New in 1.8.2: separate screen resolution cookie for IE
4140
- if (!isset($_COOKIE['wassup_screen_res'])) {
4141
- echo "\n"; ?>
 
 
4142
  <!--[if IE]>
4143
  <script language=javascript>
4144
- var sheight = screen.height;
4145
- var swidth = screen.width;
4146
- document.cookie = "wassup_screen_res=" + swidth + " x " + sheight + "; path=/; domain=" + document.domain;
 
 
 
 
 
 
 
 
 
 
4147
  </script>
4148
  <![endif]--><?php
4149
- }
4150
- //Output a comment with a current timestamp to verify that page is not cached (i.e. visit is being recorded).
4151
- echo "<!--\n<p class=\"small\"> WassUp $wassupversion ".__("timestamp","wassup").": ".date('Y-m-d h:i:sA T')." (".gmdate('h:iA',time()+(get_option('gmt_offset')*3600)).")<br />\n";
4152
- echo __("If above timestamp is not current time, this page is cached","wassup").".</p> -->\n";
4153
- }
4154
- }
4155
 
4156
  /**
4157
  * Perform db operations on wassup tables
@@ -4269,9 +4356,10 @@ function wassup_widget($wargs) {
4269
  }
4270
  }
4271
 
 
4272
  // Widget TOP Browsers
4273
  if ($wassup_settings['wassup_widget_topbr'] == 1) {
4274
- $top_period = '`timestamp` > 0'; //all time
4275
  $top_limit = attribute_escape($topbrlimit);
4276
  $top_results = wGetStats("browser",$top_limit,$top_period);
4277
  if (count($top_results) > 0) {
@@ -4286,7 +4374,7 @@ function wassup_widget($wargs) {
4286
 
4287
  // Widget TOP OSes
4288
  if ($wassup_settings['wassup_widget_topos'] == 1) {
4289
- $top_period = '`timestamp` > 0'; //all time
4290
  $top_limit = attribute_escape($toposlimit);
4291
  $top_results = wGetStats("os",$top_limit,$top_period);
4292
  if (count($top_results) > 0) {
@@ -4300,7 +4388,7 @@ function wassup_widget($wargs) {
4300
  }
4301
 
4302
  // Widget Visitors Online
4303
- $TotWid = New MainItems($table_tmp_name,$from_date,$to_date);
4304
 
4305
  $currenttot = $TotWid->calc_tot("count", null, null, "DISTINCT");
4306
  $currentlogged = $TotWid->calc_tot("count", null, "AND username!=''", "DISTINCT");
@@ -4520,8 +4608,9 @@ function wassup_sidebar($before_widget='', $after_widget='', $before_title='', $
4520
  }
4521
  }
4522
 
 
4523
  if ($wtopbr == 1) {
4524
- $top_period = '`timestamp` > 0'; //all time
4525
  $top_limit = attribute_escape($topbrlimit);
4526
  $top_results = wGetStats("browser",$top_limit,$top_period);
4527
  if (count($top_results) > 0) {
@@ -4535,7 +4624,7 @@ function wassup_sidebar($before_widget='', $after_widget='', $before_title='', $
4535
  }
4536
 
4537
  if ($wtopos == 1) {
4538
- $top_period = '`timestamp` > 0'; //all time
4539
  $top_limit = attribute_escape($toposlimit);
4540
  $top_results = wGetStats("os",$top_limit,$top_period);
4541
  if (count($top_results) > 0) {
@@ -4549,7 +4638,7 @@ function wassup_sidebar($before_widget='', $after_widget='', $before_title='', $
4549
  }
4550
 
4551
  // Visitors Online
4552
- $TotWid = New MainItems($table_tmp_name,$from_date,$to_date);
4553
 
4554
  $currenttot = $TotWid->calc_tot("count", null, null, "DISTINCT");
4555
  $currentlogged = $TotWid->calc_tot("count", null, "AND username!=''", "DISTINCT");
@@ -4583,7 +4672,7 @@ function wassupDashChart() {
4583
  if ($wassup_options->wassup_dashboard_chart == 1) {
4584
  $chart_type = ($wassup_options->wassup_chart_type >0)? $wassup_options->wassup_chart_type: "2";
4585
  $to_date = current_time("timestamp");
4586
- $Chart = New MainItems($wassup_table,"",$to_date);
4587
  $chart_url = $Chart->TheChart(1, "400", "125", "", $chart_type, "bg,s,efebef|c,lg,90,edffff,0,efebef,0.8", "dashboard"); ?>
4588
  <h3>WassUp <?php _e('Stats','wassup'); ?> <cite><a href="admin.php?page=<?php echo WASSUPFOLDER; ?>"><?php _e('More','wassup'); ?> &raquo;</a></cite></h3>
4589
  <div id="placeholder" align="left">
@@ -4601,7 +4690,7 @@ function wassup_dashboard_widget_function() {
4601
  $to_date = current_time("timestamp");
4602
  $chart_type = ($wassup_options->wassup_chart_type >0)? $wassup_options->wassup_chart_type: "2";
4603
  $res = ((int)$wassup_options->wassup_screen_res-160)/2;
4604
- $Chart = New MainItems($wassup_table,"",$to_date);
4605
  $chart_url = $Chart->TheChart(1, $res, "180", "", $chart_type, "bg,s,efebef|c,lg,90,edffff,0,eae9e9,0.8", "dashboard");
4606
  $max_char_len= 40;
4607
  $wpurl = get_bloginfo('wpurl');
@@ -4610,7 +4699,7 @@ function wassup_dashboard_widget_function() {
4610
  #placeholder {
4611
  margin:-10px !important;
4612
  padding:2px 0 5px;
4613
- background: #eae9e9 url("'.WASSUPFOLDER.'/css/images/bg_wrap.png") repeat;
4614
  font-size:11px;
4615
  }
4616
  #wassup_dashboard_widget .wassup_dash_box {
3
  Plugin Name: WassUp
4
  Plugin URI: http://www.wpwp.org
5
  Description: Analyze your visitors traffic with real-time stats, charts, and a lot of chronological information. Includes a sidebar widget of current online visitors and other statistics and an admin dashboard widget with chart. For Wordpress 2.2 or higher. Caution: don't upgrade when your site is busy!
6
+ Version: 1.8.3
7
  Author: Michele Marcucci, Helene Duncker
8
  Author URI: http://www.michelem.org/
9
  Disclaimer: Use at your own risk. No warranty expressed or implied is provided.
10
 
11
+ Copyright (c) 2007-2011 Michele Marcucci
12
  Released under the GNU General Public License (GPL)
13
  http://www.gnu.org/licenses/gpl.txt
14
  */
23
  }
24
  //wassup globals & constants
25
  global $wp_version, $current_user, $user_level, $wassup_options;
26
+ $wassupversion="1.8.3";
27
  $wassup_cookie_value="";
28
+ $wdebug_mode=false; //turn on debugging (global)...Use cautiously! Will display errors from all plugins, not just WassUp
29
  define('WASSUPDIR', dirname(__FILE__)); //new constant in v1.8
30
  define('WASSUPFOLDER', plugin_basename(dirname(__FILE__)));
31
  require_once(WASSUPDIR.'/lib/wassup.class.php');
66
  //#Add/update wassup settings in Wordpress options table
67
  $wassup_options = new wassupOptions; //#settings initialized here
68
  $wassup_table = (!empty($wassup_options->wassup_table))? $wassup_options->wassup_table : $wpdb->prefix . "wassup";
69
+ $wassup_meta_table = $wassup_table . "_meta";
70
 
71
  //# wassup should not be active during install
72
  $wassup_options->wassup_active = 0;
108
  require_once(WASSUPDIR.'/lib/upgrade.php');
109
  } else {
110
  echo "file: ".WASSUPDIR.'/lib/upgrade.php does not exist!';
111
+ exit(1);
112
  }
113
+ $wsuccess = wassup_tableInstaller();
114
  //double-check that main table was installed
115
+ if ($wsuccess){
116
+ $wassup_options->wassup_alert_message = "Wassup $wassupversion: ".__("Database created/upgraded successfully","wassup"); //debug
117
+ } else {
118
+ $wassup_options->wassup_alert_message = "Wassup $wassupversion: ".__("An error occured during the upgrade. WassUp table structure may not have been updated properly.","wassup"); //debug
119
+ }
120
+ if ($wpdb->get_var("SHOW TABLES LIKE '{$wassup_table}'") == $wassup_table) {
121
  //Reset 'dbengine' MySQL setting with each upgrade...because host server settings can change
122
  if (!empty($wassup_options->wassup_version)) { //upgrade only
123
  $wassup_options->wassup_dbengine = $wassup_options->getMySQLsetting('engine');
124
  }
125
  //turn off wassup_cache if meta table does not exist
 
126
  if ($wassup_options->wassup_cache == 1) {
127
+ if ($wpdb->get_var("SHOW TABLES LIKE \'$wassup_meta_table\'") != $wassup_meta_table) {
128
  $wassup_options->wassup_cache = 0;
129
  }
130
  }
131
 
132
  //show warning when 'WP_CACHE' constant is set
133
  if (wassup_compatCheck("WP_CACHE") == true) {
134
+ $wassup_options->wassup_alert_message = '<strong style="color:#c00;padding:5px;">'.__("WassUp cannot generate accurate statistics with page caching enabled.","wassup")." ".__("If your cache plugin stores whole Wordpress pages/posts as HTML documents, then WassUp won't run properly. Please deactivate your cache plugin and remove \"WP_CACHE\" from \"wp_config.php\".","wassup").'</strong>';
135
  }
136
  //TODO: Show warning when 'wp_footer()' does not exist in active theme template (non-cache setups only)
137
 
138
  //#Since v1.7: put current version# in options after update
139
  $wassup_options->wassup_version = $wassupversion;
140
 
 
 
 
141
  $wassup_options->wassup_active = 1; //start recording
142
  $wassup_options->saveSettings();
143
 
147
  if (function_exists('deactivate_plugins')) {
148
  deactivate_plugins(__FILE__);
149
  }
150
+ echo '<strong style="color:#c00;padding:5px;">'.__("An error occured during WassUp table install","wassup").'</strong>'.". <br/>debug: return code: ".(int)$wsuccess." <br/>wassup table: $wassup_table &nbsp; meta table: $wassup_meta_table";
151
  exit(1); //exit with error
152
  }
153
  } //end function
195
 
196
  /**
197
  * Output javascript in page head for wassup tracking
198
+ * @param none
199
  * @return none;
200
  */
201
+ function wassup_head() {
202
+ global $wassup_options, $wassupversion, $wscreen_res, $current_user;
203
+
204
+ //if ($wassup_options->wassup_active == "1") { //redundant, in hook
205
+ //Since v.1.8: removed meta tag to reduce plugin bloat
206
+ //print '<meta name="wassup-version" content="'.$wassupversion.'" />'."\n";
207
+ //add screen resolution javascript to blog header
208
+ if ($wscreen_res == "" && isset($_COOKIE['wassup_screen_res'])) {
209
+ $wscreen_res = attribute_escape(trim($_COOKIE['wassup_screen_res']));
210
+ if ($wscreen_res == "x") $wscreen_res = "";
211
+ }
212
+ if (empty($wscreen_res) && isset($_SERVER['HTTP_UA_PIXELS'])) {
213
+ //resolution in IE/IEMobile header sometimes
214
+ $wscreen_res = str_replace('X',' x ',$_SERVER['HTTP_UA_PIXELS']);
215
+ }
216
+ if (empty($wscreen_res) && isset($_COOKIE['wassup'])) {
217
+ $cookie_data = explode('::',attribute_escape(base64_decode(urldecode($_COOKIE['wassup']))));
218
+ $wscreen_res=(!empty($cookie_data[2]))?$cookie_data[2]:"";
219
+ }
220
  //Get visitor's screen resolution using javascript and a cookie.
221
  // - Added here so javascript code is placed in document <head>
222
  // to store this client-side only variable in a cookie that PHP
223
  // can read. -Helene D. 2009-01-19 ?>
224
  <script type="text/javascript">
225
  //<![CDATA[
226
+ var screen_res = "<?php echo $wscreen_res; ?>";
227
+ <?php
228
+ if (empty($wscreen_res) && !isset($_COOKIE['wassup_screen_res'])) { ?>
229
  function writeCookie(name,value,hours) {
230
  var the_cookie = name+"="+escape(value)+"; expires=";
231
  var expires = "";
257
  } //end if !isset('wassup_screen_res')
258
  ?>
259
  //]]>
260
+ </script><?php
261
+ echo "\n";
262
+ //} // end if wassup_active == "1"
263
  } //end function wassup_head
264
 
265
  //# Wassup init hook actions performed before headers are sent:
270
  global $wp_version, $wassup_options;
271
 
272
  //block any obvious sql injection attempts involving WassUp -Helene D. 2009-06-16
273
+ $request_uri = $_SERVER['REQUEST_URI'];
274
+ if (!$request_uri) $request_uri = $_SERVER['SCRIPT_NAME']; // IIS
275
+ if (stristr($request_uri,'wassup')!==FALSE || (isset($_SERVER['HTTP_REFERER']) && stristr($_SERVER['HTTP_REFERER'],'wassup')!==FALSE)) {
276
+ if (preg_match('/[&?].+\=(\-(1|9)+|.*(select|update|delete|alter|drop|union|create)[ %&].*(?:from)?.*wp_\w+)/i',str_replace(array('\\','&#92;','"','%22','&#34;','&quot','&#39;','\'','`','&#96;'),'',$request_uri))>0) {
277
  header("HTTP/1.1 403 Forbidden");
278
  wp_die('Illegal request - Permission Denied!');
279
  } elseif (preg_match('/(<|&lt;|&#60;|%3C)script[^a-z0-9]/i',$_SERVER['REQUEST_URI'])>0) {
294
  wp_deregister_script('jquery');
295
  }
296
  // the safe way to load jquery into WP
297
+ wp_register_script('jquery', WASSUPURL.'/js/jquery.min.js',FALSE,'1.6.2');
298
  }
299
  if ($_GET['page'] == "wassup-spia") {
300
  //the safe way to load a jquery dependent script
301
  wp_enqueue_script('spia', WASSUPURL.'/js/spia.js', array('jquery'), '1.4');
302
  } elseif($_GET['page'] == "wassup-options") {
303
  //if (version_compare($wp_version, '2.7', '<')) {
304
+ wp_enqueue_script('jqueryui', 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js', array('jquery'), '1.8.16');
305
  //} else {
306
  // wp_enqueue_script('ui.core', array('jquery'));
307
  // wp_enqueue_script('ui.tabs', array('jquery'));
334
 
335
  //Add the wassup stylesheet and other javascripts...
336
  function add_wassup_css() {
337
+ global $wassup_options, $wdebug_mode;
338
 
339
  $plugin_page = $_GET['page'];
340
  if (stristr($plugin_page,'wassup') !== FALSE) { $plugin_page="wassup"; }
347
  }
348
  //preassign "GET" parameters for "action.php" in "action_param"
349
  $action_param='&whash='.$wassup_options->whash;
350
+ if ($wdebug_mode) {
351
  $action_param .= '&debug_mode=true';
352
  }
353
  //Important Note: In WordPress 2.6+ "/wp-content/" can be
370
  ?>
371
  <script type='text/javascript'>
372
  //<![CDATA[
373
+ // var selftimerID = 0;
374
  function selfRefresh(){
375
  location.href='?<?php print $_SERVER['QUERY_STRING']; ?>';
376
  }
377
+ // selftimerID = setTimeout('selfRefresh()', <?php print ($wassup_options->wassup_refresh * 60000)+2000; ?>);
378
  //]]>
379
+ </script><?php
380
+ //Since 1.8.2: restrict refresh to range 0-180 minutes (3 hrs)
381
  $wrefresh = 0;
382
  if (!is_numeric($wassup_options->wassup_refresh) || $wassup_options->wassup_refresh < 0 || $wassup_options->wassup_refresh > 180) {
383
  $wrefresh = 3; //3 minutes default;
454
 
455
  //show larger icons on mouse-over
456
  $("img.delete-icon").mouseover(function() {
457
+ $(this).attr("src","<?php echo WASSUPURL.'/img/b_delete2.png'; ?>");
458
  }).mouseout(function() {
459
+ $(this).attr("src","<?php echo WASSUPURL.'/img/b_delete.png'; ?>");
460
  });
461
  $("img.table-icon").mouseover(function() {
462
+ $(this).attr("src","<?php echo WASSUPURL.'/img/b_select2.png'; ?>");
463
  }).mouseout(function() {
464
+ $(this).attr("src","<?php echo WASSUPURL.'/img/b_select.png'; ?>");
465
  });
466
 
467
  $("a.deleteID").click(function(){
476
  if (html == "")
477
  $("div#delID" + id).fadeOut("slow");
478
  else
479
+ $("div#delID" + id).find('p.delbut').append("<br/><br/><small style='color:#404;font-weight:bold;text-align:right;float:right;'> <nobr><?php _e('Sorry, delete failed!','wassup'); ?></nobr> " + html + "</small>");
480
  },
481
  error: function (XMLHttpReq, txtStatus, errThrown) {
482
+ $("div#delID" + id).find('p.delbut').append("<br/><br/><small style='color:#404;font-weight:bold;text-align:right;float:right;'> <nobr><?php _e('Sorry, delete failed!','wassup'); ?></nobr> " + txtStatus + ": " + errThrown + "</small>");
483
  }
484
  });
485
  return false;
489
  if (empty($_GET['search'])) {
490
  echo "\n"; ?>
491
  $("div.search-ip").slideDown("slow");
492
+ $("a.show-search").html("<?php _e('Hide Search', 'wassup'); ?>");
493
  },function() {
494
  $("div.search-ip").slideUp("slow");
495
+ $("a.show-search").html("<?php _e('Search', 'wassup'); ?>");
496
  return false; <?php
497
  } else {
498
  echo "\n"; ?>
499
  $("div.search-ip").slideUp("slow");
500
+ $("a.show-search").html("<?php _e('Search', 'wassup'); ?>");
501
  },function() {
502
  $("div.search-ip").slideDown("slow");
503
+ $("a.show-search").html("<?php _e('Hide Search', 'wassup'); ?>");
504
  return false; <?php
505
  }
506
  echo "\n"; ?>
507
  });
508
+ /*
509
+
510
+ // Since v1.8.3: deleted hide/show "top stats" javascript because it is not used
 
 
 
 
 
511
 
512
+ */
513
  $("a.toggle-all").toggle(function() {
514
  $("div.togglenavi").slideDown("slow");
515
+ $("a.toggle-all").html("<?php _e('Collapse All', 'wassup'); ?>");
516
  },function() {
517
  $("div.togglenavi").slideUp("slow");
518
+ $("a.toggle-all").html("<?php _e('Expand All', 'wassup'); ?>");
519
  return false;
520
  });
521
  $("a.toggle-allcrono").toggle(function() {
522
  $("div.togglecrono").slideUp("slow");
523
+ $("a.toggle-allcrono").html("<?php _e('Expand Chronology', 'wassup'); ?>");
524
  },function() {
525
  $("div.togglecrono").slideDown("slow");
526
+ $("a.toggle-allcrono").html("<?php _e('Collapse Chronology', 'wassup'); ?>");
527
  return false;
528
  });
529
  <?php
530
+ //Since v1.8.2: don't add timer click function when wrefresh==0
531
  if ($wrefresh > 0) { ?>
532
  $("#CountDownPanel").click(function(){ //Pause|Resume countdown
533
  var timeleft = _currentSeconds*1000;
550
  </script>
551
  <?php } //end if page != wassup-options
552
 
 
 
553
  if ($_GET['page'] == "wassup-options") {
554
  //#Current active tabs are indentified after page reload with
555
  //# either $_GET['tab']=N or $_POST['submit-optionsN'] where
557
  //# "settings.php" with <li class="ui-tabs-selected">
558
  //<link rel="stylesheet" href="WASSUPURL.'/css/ui.tabs.css'" type="text/css" />
559
  echo "\n"; ?>
560
+ <link href='http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/themes/base/jquery-ui.css' rel='stylesheet' type='text/css' />
561
  <script type="text/javascript">
562
  //<![CDATA[
563
  jQuery(document).ready(function($) {
564
  var $tabs = $('#tabcontainer').tabs();
 
565
  $('.submit-opt').click(function(){
566
  $(this).css("background-color", "#d71");
567
  });
591
  $('#spyContainer').spy({
592
  limit: 12,
593
  fadeLast: 5,
594
+ ajax: <?php echo "'".WASSUPURL."/lib/action.php?action=spia&spiatype=".$spytype.$action_param."',\n";
595
+ if (!empty($wassup_options->wassup_spy_speed) && is_numeric($wassup_options->wassup_spy_speed)) {
596
+ echo "\t\ttimeout: ".$wassup_options->wassup_spy_speed;
597
+ } else {
598
+ echo "\t\ttimeout: 5000";
599
+ } ?>,
600
  'timestamp': myTimestamp,
601
  fadeInSpeed: 1100 });
602
 
605
  $("#spy-play").css("background-color", "#eae9e9"); <?php
606
  if (!empty($wassup_options->wassup_geoip_map)) {
607
  echo "\n"; ?>
608
+ $("div#map").css({"opacity": "0.6", "background": "none"}); <?php
609
  } ?>
610
  });
611
  $('#spy-play').click(function(){
683
  * Wassup's admin page manager - displays WassUp admin pages
684
  */
685
  function WassUp() {
686
+ global $wpdb, $wp_version, $current_user, $user_level, $wassupversion, $wassup_options, $wdebug_mode;
687
 
688
  // Start getting time of execution to debug SQL query
689
  $starttime = microtime_float();
690
 
691
  //#debug...
692
+ if ($wdebug_mode) {
693
  $mode_reset=ini_get('display_errors');
694
  //error_reporting(E_ALL | E_STRICT); //debug, E_STRICT=php5 only
695
  error_reporting(E_ALL); //debug
708
 
709
  //"action_param" are preassigned "GET" parameters used for "action.php" external/ajax calls like "top ten"
710
  $action_param='&whash='.$wassup_options->whash;
711
+ if ($wdebug_mode) {
712
  $action_param .= '&debug_mode=true';
713
  }
714
  //wpabspath param required for non-standard wp-content directory location
823
  $wassup_options->delete_filter = $_POST['delete_filter'];
824
  }
825
  $wassup_options->wassup_screen_res = $_POST['wassup_screen_res'];
826
+ //Since v1.8.2: validate wassup_refresh input value
827
  if (is_numeric($_POST['wassup_refresh']) && $_POST['wassup_refresh']>=0 && $_POST['wassup_refresh']<=180) {
828
  $wassup_options->wassup_refresh = (int)$_POST['wassup_refresh'];
829
  }
834
  if (!empty($_POST['wassup_googlemaps_key'])) { //don't clear geoip key
835
  $wassup_options->wassup_googlemaps_key = $_POST['wassup_googlemaps_key'];
836
  }
837
+ if (!empty($_POST['wassup_spy_speed']) && is_numeric($_POST['wassup_spy_speed']) && (int)$_POST['wassup_spy_speed'] >1000) {
838
+ $wassup_options->wassup_spy_speed = (int)$_POST['wassup_spy_speed'];
839
+ }
840
  $wassup_options->wassup_time_format = $_POST['wassup_time_format'];
841
  $wassup_options->wassup_time_period = $_POST['wassup_time_period'];
842
  $wassup_options->wassup_default_type = $_POST['wassup_default_type'];
843
  $wassup_options->wassup_default_limit = $_POST['wassup_default_limit'];
844
+ //New in v1.8.3: 1) toplimit input for top stats (top10)
845
+ // list size and 2) top_nospider input to exclude spiders
846
+ // from all top stats
847
+ $top_ten = array("toplimit" => (isset($_POST['toplimit'])? (int)$_POST['toplimit']:"10"),
848
+ "topsearch" => $_POST['topsearch'],
849
  "topreferrer" => $_POST['topreferrer'],
850
  "toprequest" => $_POST['toprequest'],
851
  "topbrowser" => $_POST['topbrowser'],
852
  "topos" => $_POST['topos'],
853
  "toplocale" => (isset($_POST['toplocale'])?$_POST['toplocale']:"0"),
854
  "topvisitor" => (isset($_POST['topvisitor'])?$_POST['topvisitor']:"0"),
855
+ "toppostid" => (isset($_POST['toppostid'])?$_POST['toppostid']:"0"),
856
+ "topreferrer_exclude" => $_POST['topreferrer_exclude'],
857
+ "top_nospider" => (isset($_POST['top_nospider'])?$_POST['top_nospider']:"0"));
858
  $wassup_options->wassup_top10 = attribute_escape(serialize($top_ten));
859
  $wassup_options->wassup_cache = (!empty($_POST['wassup_cache'])?"1":"0");
860
  if ($wassup_options->saveSettings()) {
1200
  //## Filter detail list by date range...
1201
  $to_date = current_time("timestamp"); //wordpress time function
1202
  if (isset($_GET['last']) && is_numeric($_GET['last'])) {
1203
+ $wlast = $_GET['last'];
1204
+ $stickyFilters.='&last='.$wlast;
1205
  } else {
1206
+ $wlast = $wassup_options->wassup_time_period;
1207
  }
1208
+ if ($wlast == 0) {
1209
  $from_date = "0"; //all time
1210
  } else {
1211
+ $from_date = $to_date - (int)(($wlast*24)*3600);
1212
  //extend start date to within a rounded time
1213
+ if ($wlast < .25) { //start on 1 minute
1214
  $from_date = ((int)($from_date/60))*60;
1215
+ } elseif ($wlast < 7) {
1216
  $from_date = ((int)($from_date/300))*300;
1217
+ } elseif ($wlast < 30) {
1218
  $from_date = ((int)($from_date/1800))*1800;
1219
+ } elseif ($wlast < 365) {
1220
  $from_date = ((int)($from_date/86400))*86400;
1221
  } else {
1222
  $from_date = ((int)($from_date/604800))*604800;
1225
 
1226
  //## Filter detail lists by visitor type...
1227
  if (isset($_GET['type'])) {
1228
+ $wtype = attribute_escape($_GET['type']);
1229
+ $stickyFilters.='&type='.$wtype;
1230
  } else {
1231
+ $wtype = $wassup_options->wassup_default_type;
1232
  }
1233
+ if (!empty($wtype) && $wtype != 'everything') {
1234
+ $wwhereis=$wassup_options->getKeyOptions("wassup_default_type","sql",$wtype);
1235
  } else {
1236
+ $wtype="";
1237
+ $wwhereis="";
1238
  }
1239
  //## Filter detail lists by a specific page and number
1240
  //# of items per page...
1241
+ $witems = 10; //default
1242
  if (isset($_GET['limit']) && is_numeric($_GET['limit'])) {
1243
+ //$witems = htmlentities(attribute_escape($_GET['limit']));
1244
+ $witems = (int)$_GET['limit'];
1245
  } elseif ($wassup_options->wassup_default_limit != '') {
1246
+ $witems = $wassup_options->wassup_default_limit;
1247
  }
1248
+ if ((int)$witems < 1 ) { $witems = 10; }
1249
  //# current page selections
1250
  if (isset($_GET['pages']) && is_numeric($_GET['pages'])) {
1251
+ $wpages = (int)$_GET['pages'];
1252
  } else {
1253
+ $wpages = 1;
1254
  }
1255
+ if ( $wpages > 1 ) {
1256
+ $wlimit = " LIMIT ".(($wpages-1)*$witems).",$witems";
1257
  } else {
1258
+ $wlimit = " LIMIT $witems";
1259
  }
1260
 
1261
  //## Filter detail lists by a searched item
1262
  if (!empty($_GET['search'])) {
1263
+ $wsearch = attribute_escape(strip_tags(html_entity_decode($_GET['search'])));
1264
+ $stickyFilters.='&search='.$wsearch;
1265
  } else {
1266
+ $wsearch = "";
1267
  }
1268
 
1269
  // DELETE EVERY RECORD MARKED BY IP
1288
  echo "<!--heartbeat-->\n";
1289
 
1290
  // Instantiate class to count items
1291
+ $wTot = New WassupItems($wassup_table,$from_date,$to_date,$wwhereis,$wlimit);
1292
+ $wTot->whereis = $wwhereis;
1293
+ $wTot->Limit = $wlimit;
1294
+ $wTot->WpUrl = $wpurl;
1295
  echo "<!--heartbeat-->\n";
1296
 
1297
  // MAIN QUERY
1298
+ $wmain = $wTot->calc_tot("main", $wsearch);
1299
  echo "<!--heartbeat-->\n";
1300
+ $witemstot = $wTot->calc_tot("count", $wsearch, null, "DISTINCT");
1301
  echo "<!--heartbeat-->\n";
1302
+ $wpagestot = $wTot->calc_tot("count", $wsearch);
1303
  echo "<!--heartbeat-->\n";
1304
+ $wspamtot = $wTot->calc_tot("count", $wsearch, "AND spam>0");
1305
  // Check if some records was marked
1306
  if ($wassup_options->wmark == "1") {
1307
+ $markedtot = $wTot->calc_tot("count", $wsearch, "AND ip = '".$wassup_options->wip."'", "DISTINCT");
1308
  }
1309
  echo "<!--heartbeat-->\n";
1310
  // Check if some records were searched
1311
+ if (!empty($wsearch)) {
1312
+ $searchtot = $wTot->calc_tot("count", $wsearch, null, "DISTINCT");
1313
  }
1314
  //# remove any delete request from $_SERVER['QUERY_STRING']
1315
  //# clear non-sticky filter parameters before applying new filters
1351
  _e('Details for the last','wassup'); ?>:
1352
  <select style="font-size: 11px;" name="last" onChange="window.location.href=this.options[this.selectedIndex].value;"><?php
1353
  $optionargs="?".attribute_escape($new_last."&last=");
1354
+ $wassup_options->showFormOptions("wassup_time_period","$wlast","$optionargs"); ?>
1355
  </select></td>
1356
  <td class="legend" align="right"><?php _e('Items per page','wassup'); ?>: <select name="navi" style="font-size: 11px;" onChange="window.location.href=this.options[this.selectedIndex].value;"><?php
1357
  //selectable filter by number of items on page (default_limit)
1360
  } else {
1361
  $new_limit = $URLQuery;
1362
  }
1363
+ $selected=$witems;
1364
  $optionargs="?".$new_limit."&limit=";
1365
  $wassup_options->showFormOptions("wassup_default_limit","$selected","$optionargs"); ?>
1366
  </select><span class="separator">|</span>
1367
  <?php _e('Filter items by','wassup'); ?>: <select style="font-size: 11px;" name="type" onChange="window.location.href=this.options[this.selectedIndex].value;">
1368
  <?php
1369
  //selectable filter by type of record (wassup_default_type)
1370
+ $selected=$wtype;
1371
+ $filter_args=str_replace("&type=$wtype","",$stickyFilters);
1372
  $optionargs="?page=".WASSUPFOLDER.$filter_args."&type=";
1373
  $wassup_options->showFormOptions("wassup_default_type","$selected","$optionargs"); ?>
1374
  </select></td>
1378
  <div class='centered'>
1379
  <div id='usage'>
1380
  <ul>
1381
+ <li><span style="border-bottom:2px solid #0077CC;"><?php echo $witemstot; ?></span> <?php _e('Visits','wassup'); ?></li>
1382
+ <li><span style="border-bottom:2px dashed #FF6D06;"><?php echo $wpagestot; ?></span> <?php _e('Pageviews','wassup'); ?></li>
1383
+ <li><span><?php echo @number_format(($wpagestot/$witemstot), 2); ?></span> <?php _e('Pages/Visits','wassup'); ?></li><?php
1384
  // Print spam usage only if enabled
1385
  if ($wassup_options->wassup_spamcheck == 1) { ?>
1386
+ <li><span> <a href="#TB_inline?width=400&inlineId=hiddenspam" class="thickbox"><?php echo $wspamtot; ?><span class="plaintext">(<?php echo @number_format(($wspamtot*100/$wpagestot), 1); ?>%)</span></a></span> <?php _e('Spams','wassup'); ?></li><?php
1387
  } ?>
1388
  </ul><br/>
1389
  <div id="placeholder" align="center"></div>
1391
  </div><?php
1392
  // Page breakdown
1393
  // paginate only when total records > items per page
1394
+ if ($witemstot > $witems) {
1395
  $p=new wassup_pagination();
1396
+ $p->items($witemstot);
1397
+ $p->limit($witems);
1398
+ $p->currentPage($wpages);
1399
+ $p->target("admin.php?page=".WASSUPFOLDER."&limit=$witems&type=$wtype&last=$wlast&search=$wsearch");
1400
  echo "<!--heartbeat-->\n";
1401
  $p->calculate();
1402
  $p->adjacents(5);
1425
  } ?></td>
1426
  <td align="right" class="legend">
1427
  <a href="<?php echo wCleanURL(WASSUPURL.'/lib/action.php?action=topten&from_date='.$from_date.'&to_date='.$to_date.$action_param.'&width='.($res+250).'&height=440','','url');
1428
+ if ($wdebug_mode) echo '" target="_blank';
1429
  else echo '" class="thickbox';
1430
+ ?>" title="Wassup <?php _e('Top Stats for','wassup');
1431
  $wdformat = get_option("date_format");
1432
  if (($to_date - $from_date) > 24*60*60) {
1433
  echo ": ".gmdate("$wdformat",$from_date)." - ".gmdate("$wdformat",$to_date);
1436
  } ?>"><?php _e('Show Top Stats','wassup'); ?></a>
1437
  <span class="separator">|</span>
1438
  <a href="#" class='show-search'><?php
1439
+ if (!empty($wsearch)) {
1440
  _e('Hide Search','wassup');
1441
  } else {
1442
  _e('Search','wassup');
1443
  } ?></a></td>
1444
  </tr>
1445
  <tr><td align="left" class="legend" colspan="2"><?php
1446
+ if (!empty($wsearch)) {
1447
+ echo " &nbsp; <strong>".(int)$searchtot."</strong> ".__('Matches found for search','wassup').": <strong>$wsearch</strong>";
1448
  } else {
1449
  echo "<br/>";
1450
  } ?>
1451
  </td>
1452
  <td align="right" class="legend">
1453
+ <div class="search-ip" <?php if (empty($wsearch)) echo 'style="display: none;"'; ?>>
1454
  <form action="" method="get">
1455
  <input type="hidden" name="page" value="<?php echo WASSUPFOLDER; ?>" /><?php
1456
  if (!empty($stickyFilters)) {
1457
  $wfilterargs=wGetQueryPairs($stickyFilters);
1458
+ if (!empty($wfilterargs)) {
1459
+ foreach ($wfilterargs AS $wfilter) {
1460
+ $wfilterval=explode('=',$wfilter);
1461
+ if (!empty($wfilterval[0]) && $wfilterval[0]!= 'type') {
1462
+ echo "\n"; ?>
1463
+ <input type="hidden" name="<?php echo $wfilterval[0].'" value="'.$wfilterval[1]; ?>" /><?php
1464
+ }
1465
  }
1466
  }
1467
+ }
1468
+ echo "\n"; ?>
1469
+ <input type="text" size="25" name="search" value="<?php if ($wsearch != "") print attribute_escape($wsearch); ?>" /><input type="submit" name="submit-search" value="search" />
1470
  </form>
1471
  </div> <!-- /search-ip -->
1472
  </td>
1474
  <div class='main-tabs'><?php
1475
  print $expcol;
1476
  //# Show Page numbers/Links...
1477
+ if ($witemstot > $witems) {
1478
  echo '<div id="pag" align="center">'.$p->show()."</div>\n";
1479
  }
1480
  //# Detailed List of Wassup Records...
1481
+ if ($witemstot >0 && count($wmain) >0) {
1482
+ foreach ($wmain as $rk) {
1483
  $timestampF = $rk->max_timestamp;
1484
  $dateF = gmdate("d M Y", $timestampF);
1485
  if ($wassup_options->wassup_time_format == 24) {
1570
  <li><?php echo __("Screen Resolution","wassup").': <span class="raw">'.$rk->screen_res.'</span>'; ?></li><?php
1571
  } ?>
1572
  <li><?php echo 'Wassup ID'.': <span class="raw">'.$rk->wassup_id.'</span>'; ?></li>
1573
+ <li><?php
1574
+ if ($numurl > 1) _e("End timestamp","wassup");
1575
+ else _e("Timestamp","wassup");
1576
+ echo ': <span class="raw">'.$datetimeF.' ( '.$rk->max_timestamp.' )</span>'; ?></li>
1577
  </ul>
1578
  </div> <!-- raw-wassup_id -->
1579
 
1599
  <a href="?<?php echo attribute_escape($URLQuery.'&deleteMARKED=1&dip='.$ip); ?>" style="text-decoration:none;" class="deleteIP"><img class="delete-icon" src="<?php echo WASSUPURL.'/img/cross.png" alt="'.__('delete','wassup').'" title="'.__('Delete ALL marked records with this IP','wassup'); ?>" /></a>
1600
  <a href="?<?php echo attribute_escape($URLQuery.'&wmark=0'); ?>" style="text-decoration:none;"><img class="unmark-icon" src="<?php echo WASSUPURL.'/img/error_delete.png" alt="'.__('unmark','wassup').'" title="'.__('UnMark IP','wassup'); ?>" /></a><?php
1601
  } else { ?>
1602
+ <a href="#" class="deleteID" id="<?php echo $rk->wassup_id ?>" style="text-decoration:none;"><img class="delete-icon" src="<?php echo WASSUPURL.'/img/b_delete.png" alt="'.__('delete','wassup').'" title="'.__('Delete this record','wassup'); ?>" /></a>
1603
  <a href="?<?php echo attribute_escape($URLQuery.'&wmark=1&wip='.$ip); ?>" style="text-decoration:none;"><img class="mark-icon" src="<?php echo WASSUPURL.'/img/error_add.png" alt="'.__('mark','wassup').'" title="'.__('Mark IP','wassup'); ?>" /></a><?php
1604
  } ?>
1605
+ <a href="#TB_inline?height=400&width=<?php echo $res.'&inlineId='.$raw_div; ?>" class="thickbox"><img class="table-icon" src="<?php echo WASSUPURL.'/img/b_select.png" alt="'.__('show raw table','wassup').'" title="'.__('Show the items as raw table','wassup'); ?>" /></a>
1606
  </p>
1607
  <div class="sum-box">
1608
  <span class="sum-box-ip <?php echo $unclass ?>"><?php
1759
  <?php
1760
  } //end foreach qry
1761
  print $expcol; //moved
1762
+ } //end if witemstot > 0
1763
+ if ($witemstot > $witems) {
1764
  print '<div align="center">'.$p->show().'</div><br />'."\n";
1765
  } ?>
1766
  </div><!-- /main-tabs --><?php
1768
  if (!empty($wassup_options->wassup_chart) || (!empty($_GET['chart']) && "1" == attribute_escape($_GET['chart']))) {
1769
  $chart_type = ($wassup_options->wassup_chart_type >0)? $wassup_options->wassup_chart_type: "2";
1770
  //show Google!Charts image
1771
+ if ($wpagestot > 12) {
1772
  $chartwidth=$res;
1773
  //let browser resize chart for small screens
1774
  if ((int)$wassup_options->wassup_screen_res <800){
1775
  $chartwidth=640;
1776
  }
1777
+ $chart_url = $wTot->TheChart($wlast, $chartwidth, "180", $wsearch, $chart_type, "bg,s,dedade|c,lg,90,edffff,0,dedade,0.8", "page", $wtype);
1778
  $html='<img src="'.$chart_url.'" alt="'.__("Graph of visitor hits","wassup").'" class="chart" width="'.$res.'" />';
1779
  } else {
1780
  $html='<p style="padding-top:10px;">'.__("Too few records to print chart","wassup").'...</p>';
1797
  <p><small>WassUp ver: <?php echo $wassupversion.' <span class="separator">|</span> '.__("Check the official","wassup").' <a href="http://www.wpwp.org" target="_BLANK">WassUp</a> '.__("page for updates, bug reports and your hints to improve it","wassup").' <span class="separator">|</span> <a href="http://trac.wpwp.org/wiki/Documentation" title="Wassup '.__("User Guide documentation","wassup").'">Wassup '.__("User Guide documentation","wassup").'</a>'; ?>
1798
  <nobr><span class="separator">|</span> <?php echo __('Exec time','wassup').": $totaltime"; ?></nobr></small></p>
1799
  <?php
1800
+ if ($wdebug_mode) {
1801
  //display MySQL errors/warnings in admin menus - for debug
1802
  $wpdb->print_error(); //debug
1803
 
1809
  <?php
1810
  } //end function Wassup
1811
 
1812
+ //Since v.1.8: createTable/upgradeTable functions moved to 'upgrade.php'
1813
+ // module and are loaded during install/upgrade/uninstall only to keep WassUp fast.
 
1814
  } //end if is_admin
1815
 
1816
  //### Wassup Tracking functions
1817
  //Set Wassup_id and cookie (before headers sent)
1818
  function wassupPrepend() {
1819
+ global $wassup_options, $current_user, $user_level, $wscreen_res, $wassup_cookie_value, $wdebug_mode;
1820
 
1821
  //reload wassup_options in case changed elsewhere (by admin)
1822
  $wassup_options = new wassupOptions;
1827
  }
1828
  $wassup_id = "";
1829
  $session_timeout = 1;
1830
+ $wscreen_res = "";
1831
  $cookieIP = "";
1832
  $cookieHost = "";
1833
+ $cookieUser = "";
1834
  $wassup_cookie_value="";
1835
  $wassup_dbtask=array();
1836
 
1844
  $wassup_timer = $cookie_data[1];
1845
  $session_timeout = ((int)$wassup_timer - (int)time());
1846
  }
1847
+ if (!empty($cookie_data[2])) $wscreen_res = $cookie_data[2];
1848
  if (!empty($cookie_data[3])) {
1849
  $cookieIP = $cookie_data[3];
1850
  if (!empty($cookie_data[4])) {
1851
  $cookieHost = $cookie_data[4];
1852
  }
1853
  }
1854
+ //new in v1.8.3: username in wassup cookie
1855
+ if (!empty($cookie_data[5])) {
1856
+ $cookieUser = $cookie_data[5];
1857
+ }
1858
  }
1859
  //set screen resolution value from cookie or browser header data, if any
1860
+ if (empty($wscreen_res)) {
1861
  if (isset($_COOKIE['wassup_screen_res'])) {
1862
+ $wscreen_res = attribute_escape(trim($_COOKIE['wassup_screen_res']));
1863
+ if ($wscreen_res == "x") $wscreen_res="";
1864
  }
1865
+ if (empty($wscreen_res) && isset($_SERVER['HTTP_UA_PIXELS'])) {
1866
  //resolution in IE/IEMobile header sometimes
1867
+ $wscreen_res = str_replace('X',' x ',$_SERVER['HTTP_UA_PIXELS']);
1868
  }
1869
+ //if (empty($wscreen_res) && isset($_GET['wscr'])) {
1870
+ // $wscreen_res = $_GET['wscr'];
1871
  //}
1872
  }
1873
 
1875
  //if (empty($current_user->user_login)) {
1876
  get_currentuserinfo(); //sets $current_user, $user_xx
1877
  //}
1878
+ //sometimes current_user is empty during wordpress init so use "cookieUser" variable sometimes
1879
+ $logged_user = (!empty($current_user->user_login)? $current_user->user_login: $cookieUser);
1880
  //exclude valid wordpress admin page visits and admin hits
1881
  if (($wassup_options->wassup_admin == "1" || $user_level < 8) && (!is_admin() || empty($logged_user))) {
1882
 
1883
  //write wassup cookie for new visits, visit timeout (45 mins) or empty screen_res
1884
+ if (empty($wassup_id) || $session_timeout < 1 || (empty($cookie_data[2]) && !empty($wscreen_res))) {
1885
  $ipAddress = "";
1886
  $proxy = "";
1887
  $hostname = "";
1989
  $cookiepath = $cookieurl['path'];
1990
  }
1991
  $expire = time()+3000; //expire based on utc timestamp, not on Wordpress time
1992
+ $cookie_data = implode('::',array("$wassup_id","$wassup_timer","$wscreen_res","$IP","$hostname","$logged_user"));
1993
  $wassup_cookie_value = urlencode(base64_encode($cookie_data));
1994
  setcookie("wassup", "$wassup_cookie_value", $expire, $cookiepath, $cookiedomain);
1995
  unset($temp_id, $tempUA, $templen);
1996
  } //end if empty(wassup_id)
1997
 
1998
  //place wassup tag and javascript in document head
1999
+ add_action('wp_head', 'wassup_head', 10);
2000
  //track visitor hits:
2001
  // use 'send_headers' hook to track media, downloads, and feed hits
2002
  if (preg_match("/(\.(gif|ico|jpe?g|png|svg|tiff|asp|cgi|css|doc|html?|js|jar|jsp|rdf|rtf|pdf|ppt|psd|txt|xls|xlt|xml|flv|mov|mpg|mp4|mp3|ogg|swf|wmv|Z|gz|zip)$)|[=\/](feed|atom)/i", $_SERVER['REQUEST_URI'])>0) {
2026
 
2027
  //Track visitors and save record in wassup table, after page is displayed
2028
  function wassupAppend() {
2029
+ global $wpdb, $wassup_options, $current_user, $user_level, $wassupversion, $wassup_cookie_value, $wscreen_res, $wdebug_mode;
2030
 
2031
  if ($wassup_options->wassup_active == 0) { //do nothing
2032
  return;
2033
  }
2034
  @ignore_user_abort(1); // finish script in background if visitor aborts
2035
 
2036
+ if ($wdebug_mode) { //#debug...
2037
  //debug mode must be off for media and non-html requests
2038
  if (preg_match("/(\.(gif|ico|jpe?g|png|tiff|css|doc|js|jar|rdf|rtf|pdf|ppt|psd|txt|xls|xlt|xml|flv|mov|mpg|mp4|mp3|ogg|swf|wmv|Z|gz|zip)$)|[=\/](feed|atom)/i", $_SERVER['REQUEST_URI'])>0) {
2039
+ $wdebug_mode=false;
2040
  } elseif (is_feed()) {
2041
+ $wdebug_mode=false;
2042
  } else {
2043
  $mode_reset=ini_get('display_errors');
2044
+ $debug_reset=$wdebug_mode;
2045
  error_reporting(E_ALL); //debug, E_STRICT=php5 only
2046
  ini_set('display_errors','On'); //debug
2047
  //Debug: Output open comment tag to hide PHP errors from visitors
2055
  if (!empty($errlvl)) {
2056
  @error_reporting(E_ERROR);
2057
  }
2058
+ } //end if $wdebug_mode
2059
 
2060
  $wpurl = get_bloginfo('wpurl');
2061
  $blogurl = get_option('home');
2068
  if (is_single() || is_page()) $post_ID = get_the_id();
2069
  else $post_ID=0;
2070
  //if (empty($current_user->user_login)) {
2071
+ get_currentuserinfo(); //gets $current_user, $user_xx
2072
  //}
2073
  $logged_user = (!empty($current_user->user_login)? $current_user->user_login: "");
2074
  $urlRequested = $_SERVER['REQUEST_URI'];
2085
  //# First exclusion control is for admin user
2086
  if ($wassup_options->wassup_admin == "1" || $user_level < 8) {
2087
 
2088
+ //# TODO?: Exclude wp-cron utility hits
2089
+ //if (stristr($urlRequested,"/wp-cron.php?doing_wp_cron")===FALSE || (!empty($_SERVER['SERVER_ADDR']) && $_SERVER['SERVER_ADDR'] != $_SERVER['REMOTE_ADDR'])) {
2090
+
2091
  //# Record non-admin page visits and or hack attempts
2092
  if ((!is_admin() && stristr($urlRequested,"/wp-admin/")===FALSE && stristr($urlRequested,"/wp-includes/")===FALSE) || $hackercheck) {
2093
  //Get post/page id, if any
2129
  //exclusion control by specific username/url
2130
  if (!$exclude_visit) {
2131
  $wassup_id = "";
 
2132
  $cookieIP = "";
2133
  $cookieHost = "";
2134
  //check for wassup cookie and read contents
2140
  $wassup_cookie = explode('::',$cookie_data);
2141
  $wassup_id = $wassup_cookie[0];
2142
  if (!empty($wassup_cookie[2])) {
2143
+ $wscreen_res = $wassup_cookie[2];
2144
  }
2145
  if (!empty($wassup_cookie[3])) {
2146
  $cookieIP = $wassup_cookie[3];
2150
  }
2151
  }
2152
  //### set screen resolution value from cookie or browser header data, if any
2153
+ if (empty($wscreen_res)) {
2154
  if (isset($_COOKIE['wassup_screen_res'])) {
2155
+ $wscreen_res = attribute_escape(trim($_COOKIE['wassup_screen_res']));
2156
+ if ($wscreen_res == "x") $wscreen_res = "";
2157
  }
2158
+ if (empty($wscreen_res) && isset($_SERVER['HTTP_UA_PIXELS'])) {
2159
  //resolution in IE/IEMobile header sometimes
2160
+ $wscreen_res = str_replace('X',' x ',attribute_escape($_SERVER['HTTP_UA_PIXELS']));
2161
  }
2162
  }
2163
  //#### Get the visitor's details from http header...
2266
  // and get previous settings to prevent redundant checks on same
2267
  // visitor. Dup==same wassup_id, same URL, and timestamp <180 secs
2268
  $dup_urlrequest=0;
2269
+ $wpageviews=0;
2270
  $spamresult=0;
2271
  $wpdb->query("SET wait_timeout = 7"); //don't wait for slow responses
2272
+ $recent_hit = $wpdb->get_results("SELECT wassup_id, urlrequested, spam, screen_res, `timestamp`, browser, spider, os, feed, `language`, `agent`, `referrer` FROM ".$table_tmp_name." WHERE wassup_id='".$wassup_id."' AND `timestamp` >".($timestamp-180)." ORDER BY `timestamp` DESC");
2273
+ if (!empty($recent_hit)) {
2274
+ $wpageviews=count($recent_hit);
2275
  //check 1st record only
2276
  //record is dup if same url (with 'wscr' removed) and same user-agent
2277
+ if ($recent_hit[0]->urlrequested == $urlRequested || $recent_hit[0]->urlrequested == remove_query_arg('wscr',$urlRequested) || $recent_hit[0]->urlrequested == "[404] $urlRequested") {
2278
+ if ($recent_hit[0]->agent == $userAgent || empty($recent_hit[0]->agent)) {
2279
  $dup_urlrequest=1;
2280
  }
2281
  } elseif (preg_match("/\.(gif|ico|jpe?g|png|tiff)$/", $_SERVER['REQUEST_URI']) >0) {
2284
  }
2285
 
2286
  //retrieve previous spam check results
2287
+ $spamresult = $recent_hit[0]->spam;
2288
 
2289
  //check for screen resolution and update, if not previously recorded
2290
  //...queue the update because of "delayed insert"
2291
+ if (empty($recent_hit[0]->screen_res) && !empty($wscreen_res)) {
2292
+ $wassup_dbtask[] = "UPDATE $wassup_table SET `screen_res`='$wscreen_res' WHERE `wassup_id`='$wassup_id' AND `screen_res`='' ";
2293
  }
2294
 
2295
  //get previously recorded settings for this visitor to
2296
  // avoid redundant tests
2297
  if ($dup_urlrequest == 0) {
2298
+ if (empty($wscreen_res) && !empty($recent_hit[0]->screen_res)) {
2299
+ $wscreen_res = $recent_hit[0]->screen_res;
2300
  }
2301
  if ($spam == 0 && (int)$spamresult >0 ) {
2302
  $spam = $spamresult;
2303
  }
2304
+ if ($recent_hit[0]->agent == $userAgent || empty($userAgent)) {
2305
+ $browser = $recent_hit[0]->browser;
2306
+ $spider = $recent_hit[0]->spider;
2307
+ $os = $recent_hit[0]->os;
2308
  if (empty($language)) {
2309
+ $language = $recent_hit[0]->language;
2310
  }
2311
  //feed reader only if this page is feed
2312
+ if (!empty($recent_hit[0]->feed) && is_feed()) {
2313
+ $feed = $recent_hit[0]->feed;
2314
  }
2315
  }
2316
  }
2317
  // Detect disguised spiders and harvesters by checking for
2318
  // excessive pageviews (threshold: 8+ views in < 16 secs)
2319
+ if ($wpageviews >7 && empty($spider)) {
2320
+ $pageurls = array();
2321
+ $visitstart = $recent_hit[7]->timestamp;
2322
+ if (($timestamp - $recent_hit[7]->timestamp) < 16) {
2323
  $is_spider=true;
2324
+ $pageurls[]="$urlRequested";
2325
  //a spider is unlikely to hit same page 2+ times
2326
+ foreach ($recent_hit AS $w_pgview) {
2327
  if (stristr($w_pgview->urlrequested,"robots.txt")!==false) {
2328
  $is_spider = true;
2329
  break;
2330
+ } elseif (in_array($w_pgview->urlrequested,$pageurls)) {
2331
  $is_spider = false;
2332
  break;
2333
  } else {
2334
+ $pageurls[] = $w_pgview->urlrequested;
2335
  }
2336
  }
2337
  if ($is_spider) {
2340
  }
2341
  }
2342
  }
2343
+ } //end if recent_hit
2344
+ if ($wdebug_mode) { //debug
2345
+ if (!empty($recent_hit)) {
2346
  echo "<br />\nRecent visit data found in wassup_tmp:\n"; //debug
2347
+ print_r($recent_hit); //debug
2348
  echo "\n";
2349
+ $debug_output .="\n\n".date('H:i:s.u').' Recent data lookup results: $recent_hit='.serialize($recent_hit)."\n";
2350
  if ($dup_urlrequest == 1) {
2351
  echo "\nDuplicate record!\n";
2352
  }
2353
+ if ($recent_hit[0]->agent != $userAgent) {
2354
  echo "\nUser Agents NOT Identical:";
2355
  echo "\n\tCurrent user agent: ".$userAgent;
2356
+ echo "\n\tPrevious user agent:".$recent_hit[0]->agent."\n";
2357
  }
2358
  } else {
2359
  echo "<br />\nNo Recent visit data found in wassup_tmp.\n"; //debug
2362
  $wpdb->query("SET wait_timeout = 60");
2363
 
2364
  //don't record 404 unless 1st visit or hack attempt
2365
+ if ($req_code == 200 || empty($recent_hit) || ($hackercheck && (stristr($urlRequested,"/wp-")!==FALSE || preg_match('/\.(php|ini|aspx?|dll|cgi)|(\.\.\/\.\.\/|root[^a-z0-9\-_]|[^a-z0-9\-_]passw|\=admin[^a-z0-9\-_]|\=\-\d+|(bin|etc)\/)/i',$urlRequested)>0))) {
2366
  //identify hackers
2367
+ if ($req_code != 200 && preg_match('#(([a-z0-9_\*\-\#\,]+\.php[456]?)|\.(?:cgi|aspx?)|[\*\,\'"]|\=\-1$)#i',$urlRequested,$matches)>0) {
2368
+ //visitors requesting non-existent server-side scripts are up to no good
2369
+ if (empty($matches[2]) || $matches[2]!= "index.php") {
2370
+ $spam = 3;
2371
+ }
2372
  } elseif (preg_match('#\.\./\.\./(etc/passwd|\.\./\.\./)#i',$urlRequested)>0 || preg_match('#[\[&\?/](dir|document_root\]?|id|page|thisdir)\=https?\://#i',$urlRequested)>0) {
2373
  //anyone trying to access root files, password or ids are up to no good
2374
  $spam = 3;
2376
  $spam = 3;
2377
  }
2378
  //retroactively update record for hack attempt
2379
+ if ($spam == "3" && $spamresult == "0" && !empty($recent_hit)) {
2380
  $wassup_dbtask[] = "UPDATE $wassup_table SET `spam`='3' WHERE `wassup_id`='$wassup_id' AND `spam`='0' ";
2381
  }
2382
 
2383
+ //# Exclude duplicates and avoid redundant checks for multi-page visitors
2384
  if ($dup_urlrequest == 0) {
2385
  //##### Extract useful visit information from http header..
2386
  //#Identify user-agent...
2409
  } //end else agenttype
2410
  $os = $ua->os;
2411
  if (!empty($ua->resolution)) {
2412
+ $wscreen_res = (preg_match('/^\d+x\d+$/',$ua->resolution)>0)?str_replace('x',' x ',$ua->resolution):$ua->resolution;
 
2413
  }
2414
  if (!empty($ua->language) && empty($language)) {
2415
  $language=$ua->language;
2416
  }
2417
+ if ($wdebug_mode) $debug_output .= "\n".date('H:i:s.u').' UAdetecter results: $ua='.serialize($ua)."\n";
2418
  } //end if $ua->name
2419
 
2420
  $agent = (!empty($browser)?$browser:$spider);
2423
  if ((empty($agent) || stristr($agent,'unknown')!==false) && !empty($userAgent)) {
2424
  list($browser,$os) = wGetBrowser($userAgent);
2425
  if (!empty($browser)) $agent= $browser;
2426
+ if ($wdebug_mode) $debug_output .= "\n".date('H:i:s.u').' wGetBrowser results: $browser='.$browser.' $os='.$os."\n";
2427
  }
2428
 
2429
  //# Some spiders, such as Yahoo and MSN, don't
2434
  //#Identify spiders and feeds with wGetSpider...
2435
  if (empty($agent) || stristr($agent,'unknown')!==false || preg_match($spider_hosts,$hostname)>0 ) {
2436
  list($spider,$spidertype,$feed) = wGetSpider($userAgent,$hostname,$browser);
2437
+ if ($wdebug_mode) $debug_output .= "\n".date('H:i:s.u').' wGetSpider results: $spider='.$spider.' $spidertype='.$spidertype.' $feed='.$feed."\n";
2438
  //it's a browser
2439
  if ($spidertype == "B" && $urlRequested != "/robots.txt") {
2440
  if (empty($browser)) $browser = $spider;
2449
  //#Identify spiders and feed with wGetSpider...
2450
  } elseif(!empty($userAgent) && (strlen($agent)<5 || strstr($agent,'N/A') || ($agent == $browser && (empty($os) || preg_match("#\s?([a-z]+(?:bot|crawler|spider|reader|agent))[^a-z]#i",$userAgent)>0 || strstr($urlRequested,"robots.txt")!==FALSE || is_feed())))) {
2451
  list($spider,$spidertype,$feed) = wGetSpider($userAgent,$hostname,$browser);
2452
+ if ($wdebug_mode) $debug_output .= "\n".date('H:i:s.u').' wGetSpider results: $spider='.$spider.' $spidertype='.$spidertype.' $feed='.$feed."\n";
2453
  //it's a browser
2454
  if ($spidertype == "B" && $urlRequested != "/robots.txt") {
2455
  if (empty($browser)) $browser = $spider;
2467
  } //end if empty(browser) && empty(spider)
2468
 
2469
  //if 1st request is "robots.txt" then this is a bot
2470
+ if (empty($spider) && strstr($urlRequested,"robots.txt")!==FALSE && empty($recent_hit)) {
2471
  $spider = __("Unknown Spider","wassup");
2472
 
2473
  //empty userAgent is a bot
2481
 
2482
  //# some valid spiders to exclude from spam check below
2483
  $goodbot = false;
2484
+ if ($hostname!="" && !empty($spider) && preg_match('#^(googlebot|bingbot|msnbot|yahoo\!\sslurp|technorati)#i',$spider)>0 && preg_match('#\.(googlebot|live|msn|yahoo|technorati)\.(com|net)$#i',$hostname)>0){
2485
  $goodbot = true;
2486
  }
2487
 
2488
  //do spam exclusion controls, unless disabled in wassup_spamcheck
2489
+ if ($wassup_options->wassup_spamcheck == 1 && $spam == 0 && !$goodbot) {
2490
  $spamComment = New wassup_checkComment;
2491
 
2492
  //### 1st Check for referrer spam...faster, if positive
2493
+ if ($wassup_options->wassup_refspam == 1 && !empty($referrer)) {
2494
  //#...skip if referrer is own blog
2495
+ if (stristr($referrer,$wpurl)===FALSE && stristr($referrer,$blogurl)===FALSE && !$wdebug_mode) {
2496
  // Do a control if it is Referrer Spam
2497
+ //check if referrer is a previous comment spammer
2498
  if ($spamComment->isRefSpam($referrer)>0) {
2499
  $spam = 2;
2500
  //check referer against a list of known spammers
2501
  } else {
2502
+ if ($wdebug_mode) {
2503
  $isspam = wGetSpamRef($referrer,$hostname);
2504
  } else {
2505
  $isspam = @wGetSpamRef($referrer,$hostname);
2512
  //### Check for comment spammers...
2513
  //# No spam check on known bots (google, yahoo,...) unless
2514
  //# there is a comment or forum page request...
2515
+ if ($spam == 0 && (empty($spider) || stristr($urlRequested,"comment")!== FALSE || stristr($urlRequested,"forum")!== FALSE || !empty($comment_user))) {
2516
 
2517
  //if (isset($spamresult) && stristr($urlRequested,"comment") === FALSE && stristr($urlRequested,"forum") === FALSE && empty($comment_user) && empty($_POST['comment'])) {
2518
  // $spam = $spamresult; //redundant - set in dup check
2527
  $spam=1;
2528
  }
2529
  //#lastly check for comment spammers using Akismet API
2530
+ // Note: Akismet spam test may cause "header already sent" errors with "send_headers" hook in some Wordpress configurations
2531
+ if ($spam == 0 && $wassup_options->wassup_spam == 1 && stristr($urlRequested,"comment")!== FALSE && stristr($urlRequested,"/comments/feed/")== FALSE) {
2532
  $akismet_key = get_option('wordpress_api_key');
2533
  $akismet_class = dirname(__FILE__).'/lib/akismet.class.php';
2534
  if (!empty($akismet_key) && file_exists($akismet_class)) {
2557
  } //end if wassup_spam
2558
 
2559
  //retroactively update visitor's hits as spam, in case late detection
2560
+ if (!empty($recent_hit) && !empty($spam) && $spamresult==0) {
2561
  //queue the update...
2562
  $wassup_dbtask[]="UPDATE $wassup_table SET `spam`='".$spam."' WHERE `wassup_id`='".$wassup_id."' AND `spam`='0' ";
2563
  }
2576
  $searchengine="";
2577
  $search_phrase="";
2578
  $searchpage="";
2579
+ $searchcountry="";
2580
  //don't check own blog for search engine data
2581
+ if (!empty($referrer) && $spam == "0" && stristr($referrer,$blogurl)!=$referrer && !$wdebug_mode) {
2582
+ //if ($wdebug_mode) { //debug
2583
  // echo '<br />\n$Referrer="'.$referrer.'" is NOT own site: '.$blogurl.'. Checking for search engine data...'."\n"; //debug
2584
  //}
2585
  //get GET type search results, ex: search=x
2586
  if (strpos($referrer,'=')!==false) {
2587
+ list($searchengine,$search_phrase,$searchpage,$searchlang,$searchlocale)=explode("|",wGetSE($referrer));
2588
  if ($search_phrase != '') {
2589
  $sedomain = parse_url($referrer);
2590
  $searchdomain = $sedomain['host'];
2604
  if ($search_phrase != '') {
2605
  if (!empty($searchengine)) {
2606
  if (stristr($searchengine,"images")===FALSE && stristr($referrer,'&imgurl=')===FALSE) {
2607
+ // 2011-04-18: "page" parameter is now used on referrer string for Google Images et al.
2608
+ if (preg_match('#page[=/](\d+)#i',$referrer,$pcs)>0) {
2609
+ if ($searchpage != $pcs[1]) {
2610
+ $searchpage = $pcs[1];
2611
+ }
2612
+ } else {
2613
  // NOTE: Position retrieved in Google Images is
2614
  // the position number of image NOT page rank position like web search
2615
  $searchpage=(int)($searchpage/10)+1;
2616
  }
2617
+ }
2618
+ //append country code to search engine name
2619
+ if (preg_match('/(\.([a-z]{2})$|^([a-z]{2})\.)/i',$searchdomain,$match)) {
2620
  if (!empty($match[2])) {
2621
  $searchcountry = $match[2];
2622
  } elseif (!empty($match[3])) {
2623
  $searchcountry = $match[3];
2624
  }
2625
+ if (!empty($searchcountry) && $searchcountry != "us") {
2626
+ $searchengine .= " ".strtoupper($searchcountry);
2627
+ }
2628
  }
2629
  } else {
2630
  $searchengine = $searchdomain;
2631
  }
2632
  //use search engine country code as locale
2633
+ $searchlocale = trim($searchlocale);
2634
+ if (!empty($searchlocale)) {
2635
+ $language = $searchlocale;
2636
+ } elseif (!empty($searchcountry) && ($language == "us" || empty($language))) {
2637
  $language=$searchcountry;
2638
  }
2639
  } //end if search_phrase
2657
  'os'=>$os,
2658
  'browser'=>$browser,
2659
  'language'=>$language,
2660
+ 'screen_res'=>$wscreen_res,
2661
  'spider'=>$spider,
2662
  'feed'=>$feed,
2663
  'username'=>$logged_user,
2691
  } //end if wassup_exclude
2692
  } //end if !exclude_visit
2693
  } //end if !is_admin
2694
+ //} //TODO end if wp-cron.php?doing_wp_cron===FALSE
2695
  } //end if loggeduser_level
2696
 
2697
  //### Notify admin if alert is set and wassup table > alert
2757
 
2758
  //perform scheduled database tasks
2759
  if (count($wassup_dbtask)>0) {
2760
+ if ($wdebug_mode) {
2761
  $debug_output.="\n"."Performing Scheduled tasks:".serialize($wassup_dbtask)."\n";
2762
  }
2763
  wassup_scheduled_dbtask($wassup_dbtask);
2764
  }
2765
+ if ($wdebug_mode) {
2766
  if (!empty($wassup_rec)) {
2767
  echo "<br />\nWassUp record data:\n";
2768
  print_r($wassup_rec); //debug
2881
  * @return array
2882
  */
2883
  function wGetQueryPairs($urlstring){
2884
+ $wreturn = array();
2885
  if (!empty($urlstring)) {
2886
+ $wtab=parse_url($urlstring);
2887
+ if (key_exists("query",$wtab)){
2888
+ $query=$wtab["query"];
2889
+ $wreturn=explode("&",$query);
2890
  } else {
2891
+ $wreturn=explode("&",$urlstring); //partial url
2892
  }
2893
  }
2894
+ return $wreturn;
2895
  } //end wGetQueryPairs
2896
 
2897
  /**
2989
  "Google Mobile|google.com/m/|q|cd|hl||",
2990
  "Google|www.google.|q|cd|hl||",
2991
  "Google|www.google.|as_q|start|hl||", //advanced query
2992
+ "Yahoo! Images|images.search.yahoo.com|p||||",
2993
+ "Yahoo! Mobile|m.search.yahoo.|p||||",
2994
+ "Yahoo! Mobile|search.yahoo.com/mobile/|p||||",
2995
+ "Yahoo!|search.yahoo.|p||||",
2996
+ "Yahoo!|answers.yahoo.com|p||||",
2997
  "Bing Mobile|m.bing.com|q|first|||",
2998
  "Bing Images|.bing.com/images/|q|first|||",
2999
  "Bing|.bing.com|q|first|||",
3072
  "Voil|voila.fr|kw|||fr|",
3073
  "Web|.web.de|su|||de|",
3074
  "Yahoo! Mobile|m.yahoo.com|p||||",
3075
+ "Yahoo! Mobile|m2.yahoo.com|p||||",
3076
+ "Yahoo!|.yahoo.com|p||||",
3077
  "Yandex|yandex.ru|text|||ru|",
3078
  "Yippy|search.yippy.com|query||||",
3079
  "Zoohoo|.zoohoo.cz|q|||cz|",
3095
  if ($se) { // found it!
3096
  $searchengine = $nome;
3097
  $search_phrase = "";
3098
+ $svariables=array();
3099
  // Google Images or Google Translate needs additional processing of search phrase after 'prev='
3100
  if ($nome == "Google Images" || $nome == "Google Translate") {
3101
  //'prev' is an encoded substring containing actual "q" query, so use html_entity_decode to show [&?] in url substring
3102
+ $svariables = wGetQueryPairs(html_entity_decode(preg_replace('#/\w+\?#i','', urldecode($match[1]))));
3103
  $key='q'; //q is actual search key
3104
  } elseif ($nome == "Google Cache") {
3105
  $n = strpos($match[1],$blogurl);
3106
  if ($n !== false) {
3107
  //blogurl in search phrase: cache of own site
3108
  $search_phrase = attribute_escape(urldecode(substr($match[1],$n+strlen($blogurl))));
3109
+ $svariables = wGetQueryPairs($referrer);
3110
  } elseif (strpos($referrer,$blogurl)!==false && preg_match('/\&prev\=([^&]+)/',$referrer,$match)!==false) {
3111
  //NOTE: 'prev=' requires html_entity_decode to show [&?] in url substring
3112
+ $svariables = wGetQueryPairs(html_entity_decode(preg_replace('#/\w+\?#i','', urldecode($match[1]))));
3113
  } else {
3114
  //no blogurl in search phrase: cache of an external site with referrer link
3115
  $searchengine = "";
3121
  $nome = "Google Mobile";
3122
  }
3123
  $search_phrase = attribute_escape(urldecode($match[1]));
3124
+ $svariables = wGetQueryPairs($referrer);
3125
  }
3126
  //retrieve search engine parameters
3127
+ $i = count($svariables);
3128
  while($i--){
3129
+ $tab=explode("=",$svariables[$i]);
3130
  if($tab[0] == $key && empty($search_phrase)){
3131
  $search_phrase=attribute_escape($tab[1]);
3132
  } else {
3136
  if (!empty($lang) && $lang == $tab[0]) {
3137
  $searchlang = attribute_escape($tab[1]);
3138
  }
3139
+ //Indentify locale via Google search's new parameter, 'gl'
3140
+ if (strstr($nome,'Google')!==false && $tab[0] == "gl" && !empty($tab[1])) {
3141
+ $selocale = attribute_escape($tab[1]);
3142
+ }
3143
  }
3144
  } //end while
3145
  break 1;
3291
  //# most common of these are MSN (ie6,win2k3), and Yahoo!
3292
  if (substr($hostname,-16) == ".crawl.yahoo.net" || (substr($hostname,-10)==".yahoo.com" && substr($hostname,0,3)=="ycar")) {
3293
  if (stristr($ua,"Slurp")) {
3294
+ $crawler = "Yahoo! Slurp";
3295
  $crawlertype="R";
3296
  } elseif (stristr($ua,"mobile")) {
3297
+ $crawler = "Yahoo! Mobile";
3298
  $crawlertype="R";
3299
  } else {
3300
  $crawler = "Yahoo!";
3357
  $key = null;
3358
  // array format: "Spider Name|UserAgent keywords (no spaces)| Spider type (R=robot, B=Browser/downloader, F=feedreader, H=hacker, L=Link checker, M=siteMap generator, S=Spammer/email harvester, V=CSS/Html validator)
3359
  $lines = array("Googlebot|Googlebot/|R|",
3360
+ "Yahoo!|Yahoo! Slurp|R|",
3361
  "FeedBurner|FeedBurner|F|",
3362
  "AboutUsBot|AboutUsBot/|R|",
3363
  "80bot|80legs.com|R|",
3695
 
3696
  //#get the visitor locale/language
3697
  function wGetLocale($language="",$hostname="",$referrer="") {
3698
+ global $wpdb, $wassup_options, $wdebug_mode;
3699
  $clocale="";
3700
  $country="";
3701
  $language = trim(strtolower($language));
3784
  * @return boolean
3785
  */
3786
  function wGetSpamRef($referrer,$hostname="") {
3787
+ global $wdebug_mode;
3788
  $referrer=attribute_escape(strip_tags(str_replace(" ","",html_entity_decode($referrer))));
3789
  $badhost=false;
3790
  //$key = null;
3800
  $referrer_host = $rurl['host'];
3801
  //$referrer_path = $rurl['path'];
3802
  $thissite = parse_url(get_option('home'));
3803
+ //exclude current site as referrer
3804
  if (isset($thissite['host']) && $referrer_host == $thissite['host']) {
3805
  $referrer_host = "";
3806
+ //New in v1.8.3: check the path|query part of url for spammers
3807
+ } else {
3808
+ //rss.xml|sitemap.txt in referrer is faked
3809
+ if (preg_match('#.+/(rss\.xml|sitemap\.txt)$#',$referrer)>0) {
3810
+ $badhost=true;
3811
+ //membership|user id in referrer is faked
3812
+ } elseif (preg_match('#.+[^a-z0-9]((?:show)?user|u)\=\d+$#',$referrer)>0) {
3813
+ $badhost=true;
3814
+ //youtube video in referrer is faked
3815
+ } elseif (preg_match('#(\.|/)youtube\.com/watch\?v\=.+#"',$referrer)>0) {
3816
+ $badhost=true;
3817
+ //some facebook links in referrer are faked
3818
+ } elseif (preg_match('#(\.|/)facebook\.com\/ASeaOfSins$#"',$referrer)>0) {
3819
+ $badhost=true;
3820
+ }
3821
  }
3822
  } else { //faked referrer string
3823
  $badhost=true;
3825
  //#a shortened URL is likely FAKED referrer string!
3826
  if (!$badhost && !empty($referrer_host)) {
3827
  $url_shorteners = array('bit.ly', 'cli.gs',
3828
+ 'goo.gl', 'is.gd', 'ow.ly',
3829
+ 'shorturl.com', 'snurl.com', 'su.pr',
3830
  'tinyurl.com','tr.im');
3831
  if(in_array($referrer_host,$url_shorteners)) {
3832
  $badhost=true;
3835
  } //end elseif
3836
  if (empty($referrer_host) || $badhost) return $badhost;
3837
 
3838
+ if ($wdebug_mode) echo "\$referrer_host = $referrer_host.\n";
3839
  //compare against a list of recent referer spammers
3840
  $lines = array( '123666123\.com',
3841
  '209\.29\.25\.180',
3842
+ '[a-z]+19[0-9]{2}\.co\.cc',
3843
  'aerhaethjsry\.com',
3844
  'aimtrust\.com',
3845
  'american\-insurance\-companies\.com',
3846
  'amipregnantquizzes\.com',
3847
  'all\-lasik\-centers\.com',
3848
  'allmymovies\.biz',
3849
+ 'articlemarketingrobots\.org',
3850
  'baby\-kleidung\.runashop\.com',
3851
  'bayanbag\.tk',
3852
  'beachvitality\.com',
3858
  'carartexpert\.com',
3859
  'celebritydietdoctor\.com',
3860
  'celebrity\-?diets\.(com|org|net|info|biz)',
3861
+ '[a-z0-9]+\.cheapchocolatesale\.com',
3862
  'chocolate\.com',
3863
  'clients\.your\-server\.de',
3864
  'couplesresortsonline\.com',
3865
+ 'creditcardsinformation\.info',
3866
+ '.*\.css\-build\.info',
3867
+ 'h\-1.+\.cssgroup\.lv',
3868
  '.*dietplan\.com',
3869
+ 'dogcareinsurancetips\.sosblog\.com',
3870
+ 'dollhouserugs\.com',
3871
  'dreamworksdentalcenter\.com',
3872
  'duunot\.eu',
3873
  '\.ewebesales\.net',
3876
  'freefarmvillesecrets\.info',
3877
  'frenchforbeginnerssite\.com',
3878
  'gameskillinggames\.net',
3879
+ 'gardenactivities\.webnode\.com',
3880
  'globalringtones\.net',
3881
+ 'gossipchips\.com',
3882
  'gskstudio\.com',
 
3883
  'hearcam\.org',
3884
+ 'hearthealth\-hpe\.org',
3885
  'highheelsale\.com',
3886
  'homebasedaffiliatemarketingbusiness\.com',
3887
  'hosting37\d{2}\.com/',
3891
  'intl\-alliance\.com',
3892
  'it\.n\-able\.com',
3893
  'justanimal\.com',
3894
+ 'justbazaar\.com',
3895
+ 'knowledgehubdata\.com',
3896
  'koreanracinggirls\.com',
3897
+ 'lacomunidad\.elpais\.com',
3898
  'lactoseintolerancesymptoms\.net',
3899
  'liquiddiet[a-z\-]*\.com',
3900
  'locksmith[a-z\-]+\.org',
3912
  'pharmondo\.com',
3913
  'pinky\-vs\-cherokee\.com',
3914
  'pinkyxxx\.org',
3915
+ '[a-z]+\.pixnet\.net',
3916
  'play\-mp3\.com',
3917
  'poker\-review\.tk',
3918
  'pornobesto\.ru',
3927
  'singlesvacationspackages\.com',
3928
  'sitetalk\-revolution\.com',
3929
  'smartforexsignal\.com',
3930
+ 'socratestheme\.me',
3931
+ 'stableincomeplan\.blogspot\.com',
3932
  'staphinfectionpictures\.org',
3933
  'static\.theplanet\.com',
3934
  '[a-z]+\-[a-z]+\-symptoms\.com',
3935
+ 'thebestweddingparty\.com',
3936
  'thik\-chik\.com',
3937
  'thisweekendsmovies\.com',
3938
  'unassigned\.psychz\.net',
4209
 
4210
  // hook function to put a timestamp in page footer for page caching test
4211
  function wassup_foot() {
4212
+ global $wassup_options, $wassupversion, $wscreen_res, $wdebug_mode;
4213
+
4214
+ //Since 1.8.2: separate 'wassup_screen_res' cookie in footer for
4215
+ // IE users because Internet Explorer does not report screen height
4216
+ // or width until after it begins to render the document body.
4217
+ if (empty($wscreen_res) && !isset($_COOKIE['wassup_screen_res'])) {
4218
+ echo "\n"; ?>
4219
  <!--[if IE]>
4220
  <script language=javascript>
4221
+ //<![CDATA[
4222
+ if (screen_res=="") {
4223
+ screen_res = screen.width + " x " + screen.height;
4224
+ }
4225
+ if (screen_res!=" x ") {
4226
+ var cdate = new Date();
4227
+ cdate.setTime(cdate.getTime()+(48*60*60*1000));
4228
+ var cexpires = cdate.toGMTString();
4229
+ //var the_cookie = "wassup_screen_res="+escape(screen_res)+"; expires="+cexpires;
4230
+ document.cookie = "wassup_screen_res=" + escape(screen_res)+ "; path=/; domain=" + document.domain;
4231
+
4232
+ }
4233
+ //]]>
4234
  </script>
4235
  <![endif]--><?php
4236
+ } //end if !isset('wassup_screen_res')
4237
+
4238
+ //Output a comment with a current timestamp to verify that page is not cached (i.e. visit is being recorded).
4239
+ echo "<!--\n<p class=\"small\"> WassUp $wassupversion ".__("timestamp","wassup").": ".date('Y-m-d h:i:sA T')." (".gmdate('h:iA',time()+(get_option('gmt_offset')*3600)).")<br />\n";
4240
+ echo __("If above timestamp is not current time, this page is cached","wassup").".</p> -->\n";
4241
+ } //end wassup_foot
4242
 
4243
  /**
4244
  * Perform db operations on wassup tables
4356
  }
4357
  }
4358
 
4359
+ $wstart = (int)(current_time('timestamp') - 30.4*86400); //1 month in seconds
4360
  // Widget TOP Browsers
4361
  if ($wassup_settings['wassup_widget_topbr'] == 1) {
4362
+ $top_period = "'`timestamp` > $wstart'"; //one month
4363
  $top_limit = attribute_escape($topbrlimit);
4364
  $top_results = wGetStats("browser",$top_limit,$top_period);
4365
  if (count($top_results) > 0) {
4374
 
4375
  // Widget TOP OSes
4376
  if ($wassup_settings['wassup_widget_topos'] == 1) {
4377
+ $top_period = "'`timestamp` > $wstart'"; //one month
4378
  $top_limit = attribute_escape($toposlimit);
4379
  $top_results = wGetStats("os",$top_limit,$top_period);
4380
  if (count($top_results) > 0) {
4388
  }
4389
 
4390
  // Widget Visitors Online
4391
+ $TotWid = New WassupItems($table_tmp_name,$from_date,$to_date);
4392
 
4393
  $currenttot = $TotWid->calc_tot("count", null, null, "DISTINCT");
4394
  $currentlogged = $TotWid->calc_tot("count", null, "AND username!=''", "DISTINCT");
4608
  }
4609
  }
4610
 
4611
+ $wstart = (int)(current_time('timestamp') - 30.4*86400); //1 month in seconds
4612
  if ($wtopbr == 1) {
4613
+ $top_period = "'`timestamp` > $wstart'"; //one month
4614
  $top_limit = attribute_escape($topbrlimit);
4615
  $top_results = wGetStats("browser",$top_limit,$top_period);
4616
  if (count($top_results) > 0) {
4624
  }
4625
 
4626
  if ($wtopos == 1) {
4627
+ $top_period = "'`timestamp` > $wstart'"; //one month
4628
  $top_limit = attribute_escape($toposlimit);
4629
  $top_results = wGetStats("os",$top_limit,$top_period);
4630
  if (count($top_results) > 0) {
4638
  }
4639
 
4640
  // Visitors Online
4641
+ $TotWid = New WassupItems($table_tmp_name,$from_date,$to_date);
4642
 
4643
  $currenttot = $TotWid->calc_tot("count", null, null, "DISTINCT");
4644
  $currentlogged = $TotWid->calc_tot("count", null, "AND username!=''", "DISTINCT");
4672
  if ($wassup_options->wassup_dashboard_chart == 1) {
4673
  $chart_type = ($wassup_options->wassup_chart_type >0)? $wassup_options->wassup_chart_type: "2";
4674
  $to_date = current_time("timestamp");
4675
+ $Chart = New WassupItems($wassup_table,"",$to_date);
4676
  $chart_url = $Chart->TheChart(1, "400", "125", "", $chart_type, "bg,s,efebef|c,lg,90,edffff,0,efebef,0.8", "dashboard"); ?>
4677
  <h3>WassUp <?php _e('Stats','wassup'); ?> <cite><a href="admin.php?page=<?php echo WASSUPFOLDER; ?>"><?php _e('More','wassup'); ?> &raquo;</a></cite></h3>
4678
  <div id="placeholder" align="left">
4690
  $to_date = current_time("timestamp");
4691
  $chart_type = ($wassup_options->wassup_chart_type >0)? $wassup_options->wassup_chart_type: "2";
4692
  $res = ((int)$wassup_options->wassup_screen_res-160)/2;
4693
+ $Chart = New WassupItems($wassup_table,"",$to_date);
4694
  $chart_url = $Chart->TheChart(1, $res, "180", "", $chart_type, "bg,s,efebef|c,lg,90,edffff,0,eae9e9,0.8", "dashboard");
4695
  $max_char_len= 40;
4696
  $wpurl = get_bloginfo('wpurl');
4699
  #placeholder {
4700
  margin:-10px !important;
4701
  padding:2px 0 5px;
4702
+ background: #eae9e9 url("'.WASSUPFOLDER.'/img/bg_wrap.png") repeat;
4703
  font-size:11px;
4704
  }
4705
  #wassup_dashboard_widget .wassup_dash_box {